bool AggressiveDCEPass::EliminateDeadFunctions() {
  // Identify live functions first. Those that are not live
  // are dead. ADCE is disabled for non-shaders so we do not check for exported
  // functions here.
  std::unordered_set<const Function*> live_function_set;
  ProcessFunction mark_live = [&live_function_set](Function* fp) {
    live_function_set.insert(fp);
    return false;
  };
  context()->ProcessEntryPointCallTree(mark_live);

  bool modified = false;
  for (auto funcIter = get_module()->begin();
       funcIter != get_module()->end();) {
    if (live_function_set.count(&*funcIter) == 0) {
      modified = true;
      EliminateFunction(&*funcIter);
      funcIter = funcIter.Erase();
    } else {
      ++funcIter;
    }
  }

  return modified;
}
Pass::Status EliminateDeadFunctionsPass::Process(ir::IRContext* c) {
  InitializeProcessing(c);

  // Identify live functions first.  Those that are not live
  // are dead.
  std::unordered_set<const ir::Function*> live_function_set;
  ProcessFunction mark_live = [&live_function_set](ir::Function* fp) {
    live_function_set.insert(fp);
    return false;
  };
  ProcessReachableCallTree(mark_live, context());

  bool modified = false;
  for (auto funcIter = get_module()->begin();
       funcIter != get_module()->end();) {
    if (live_function_set.count(&*funcIter) == 0) {
      modified = true;
      EliminateFunction(&*funcIter);
      funcIter = funcIter.Erase();
    } else {
      ++funcIter;
    }
  }

  return modified ? Pass::Status::SuccessWithChange
                  : Pass::Status::SuccessWithoutChange;
}