Exemple #1
0
// doInitialization - Initializes the vector of functions that have not 
// been annotated with the "always inline" attribute.
bool AlwaysInliner::doInitialization(CallGraph &CG) {
  Module &M = CG.getModule();
  
  for (Module::iterator I = M.begin(), E = M.end();
       I != E; ++I)
    if (!I->isDeclaration() && !I->hasFnAttr(Attribute::AlwaysInline))
      NeverInline.insert(I);

  return false;
}
Exemple #2
0
/// Finalize CG
bool CGPassManager::doFinalization(CallGraph &CG) {
  bool Changed = false;
  for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {  
    Pass *P = getContainedPass(Index);
    if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) {
      Changed |= CGSP->doFinalization(CG);
    } else {
      FPPassManager *FP = dynamic_cast<FPPassManager *>(P);
      assert (FP && "Invalid CGPassManager member");
      Changed |= FP->doFinalization(CG.getModule());
    }
  }
  return Changed;
}
// doInitialization - Initializes the vector of functions that have been
// annotated with the noinline attribute.
bool SimpleInliner::doInitialization(CallGraph &CG) {
  CA.setTargetData(getAnalysisIfAvailable<TargetData>());

  Module &M = CG.getModule();

  for (Module::iterator I = M.begin(), E = M.end();
       I != E; ++I)
    if (!I->isDeclaration() && I->hasFnAttr(Attribute::NoInline))
      NeverInline.insert(I);

  // Get llvm.noinline
  GlobalVariable *GV = M.getNamedGlobal("llvm.noinline");

  if (GV == 0)
    return false;

  // Don't crash on invalid code
  if (!GV->hasDefinitiveInitializer())
    return false;

  const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());

  if (InitList == 0)
    return false;

  // Iterate over each element and add to the NeverInline set
  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {

    // Get Source
    const Constant *Elt = InitList->getOperand(i);

    if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(Elt))
      if (CE->getOpcode() == Instruction::BitCast)
        Elt = CE->getOperand(0);

    // Insert into set of functions to never inline
    if (const Function *F = dyn_cast<Function>(Elt))
      NeverInline.insert(F);
  }

  return false;
}
Exemple #4
0
// Make sure that there is a devirtualization trigger function that CoroSplit
// pass uses the force restart CGSCC pipeline. If devirt trigger function is not
// found, we will create one and add it to the current SCC.
static void createDevirtTriggerFunc(CallGraph &CG, CallGraphSCC &SCC) {
  Module &M = CG.getModule();
  if (M.getFunction(CORO_DEVIRT_TRIGGER_FN))
    return;

  LLVMContext &C = M.getContext();
  auto *FnTy = FunctionType::get(Type::getVoidTy(C), Type::getInt8PtrTy(C),
                                 /*IsVarArgs=*/false);
  Function *DevirtFn =
      Function::Create(FnTy, GlobalValue::LinkageTypes::PrivateLinkage,
                       CORO_DEVIRT_TRIGGER_FN, &M);
  DevirtFn->addFnAttr(Attribute::AlwaysInline);
  auto *Entry = BasicBlock::Create(C, "entry", DevirtFn);
  ReturnInst::Create(C, Entry);

  auto *Node = CG.getOrInsertFunction(DevirtFn);

  SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end());
  Nodes.push_back(Node);
  SCC.initialize(Nodes);
}
Exemple #5
0
/// Remove dead functions that are not included in DNR (Do Not Remove) list.
bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) {
  SmallVector<CallGraphNode*, 16> FunctionsToRemove;
  SmallVector<CallGraphNode *, 16> DeadFunctionsInComdats;
  SmallDenseMap<const Comdat *, int, 16> ComdatEntriesAlive;

  auto RemoveCGN = [&](CallGraphNode *CGN) {
    // Remove any call graph edges from the function to its callees.
    CGN->removeAllCalledFunctions();

    // Remove any edges from the external node to the function's call graph
    // node.  These edges might have been made irrelegant due to
    // optimization of the program.
    CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);

    // Removing the node for callee from the call graph and delete it.
    FunctionsToRemove.push_back(CGN);
  };

  // Scan for all of the functions, looking for ones that should now be removed
  // from the program.  Insert the dead ones in the FunctionsToRemove set.
  for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {
    CallGraphNode *CGN = I->second;
    Function *F = CGN->getFunction();
    if (!F || F->isDeclaration())
      continue;

    // Handle the case when this function is called and we only want to care
    // about always-inline functions. This is a bit of a hack to share code
    // between here and the InlineAlways pass.
    if (AlwaysInlineOnly && !F->hasFnAttribute(Attribute::AlwaysInline))
      continue;

    // If the only remaining users of the function are dead constants, remove
    // them.
    F->removeDeadConstantUsers();

    if (!F->isDefTriviallyDead())
      continue;

    // It is unsafe to drop a function with discardable linkage from a COMDAT
    // without also dropping the other members of the COMDAT.
    // The inliner doesn't visit non-function entities which are in COMDAT
    // groups so it is unsafe to do so *unless* the linkage is local.
    if (!F->hasLocalLinkage()) {
      if (const Comdat *C = F->getComdat()) {
        --ComdatEntriesAlive[C];
        DeadFunctionsInComdats.push_back(CGN);
        continue;
      }
    }

    RemoveCGN(CGN);
  }
  if (!DeadFunctionsInComdats.empty()) {
    // Count up all the entities in COMDAT groups
    auto ComdatGroupReferenced = [&](const Comdat *C) {
      auto I = ComdatEntriesAlive.find(C);
      if (I != ComdatEntriesAlive.end())
        ++(I->getSecond());
    };
    for (const Function &F : CG.getModule())
      if (const Comdat *C = F.getComdat())
        ComdatGroupReferenced(C);
    for (const GlobalVariable &GV : CG.getModule().globals())
      if (const Comdat *C = GV.getComdat())
        ComdatGroupReferenced(C);
    for (const GlobalAlias &GA : CG.getModule().aliases())
      if (const Comdat *C = GA.getComdat())
        ComdatGroupReferenced(C);
    for (CallGraphNode *CGN : DeadFunctionsInComdats) {
      Function *F = CGN->getFunction();
      const Comdat *C = F->getComdat();
      int NumAlive = ComdatEntriesAlive[C];
      // We can remove functions in a COMDAT group if the entire group is dead.
      assert(NumAlive >= 0);
      if (NumAlive > 0)
        continue;

      RemoveCGN(CGN);
    }
  }

  if (FunctionsToRemove.empty())
    return false;

  // Now that we know which functions to delete, do so.  We didn't want to do
  // this inline, because that would invalidate our CallGraph::iterator
  // objects. :(
  //
  // Note that it doesn't matter that we are iterating over a non-stable order
  // here to do this, it doesn't matter which order the functions are deleted
  // in.
  array_pod_sort(FunctionsToRemove.begin(), FunctionsToRemove.end());
  FunctionsToRemove.erase(std::unique(FunctionsToRemove.begin(),
                                      FunctionsToRemove.end()),
                          FunctionsToRemove.end());
  for (SmallVectorImpl<CallGraphNode *>::iterator I = FunctionsToRemove.begin(),
                                                  E = FunctionsToRemove.end();
       I != E; ++I) {
    delete CG.removeFunctionFromModule(*I);
    ++NumDeleted;
  }
  return true;
}
Exemple #6
0
bool ArgPromotion::doInitialization(CallGraph &CG) {
  FunctionDIs = makeSubprogramMap(CG.getModule());
  return CallGraphSCCPass::doInitialization(CG);
}
Exemple #7
0
bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,
                                 CallGraph &CG, bool &CallGraphUpToDate,
                                 bool &DevirtualizedCall) {
  bool Changed = false;
  PMDataManager *PM = P->getAsPMDataManager();
  Module &M = CG.getModule();

  if (!PM) {
    CallGraphSCCPass *CGSP = (CallGraphSCCPass *)P;
    if (!CallGraphUpToDate) {
      DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false);
      CallGraphUpToDate = true;
    }

    {
      unsigned InstrCount, SCCCount = 0;
      bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();
      TimeRegion PassTimer(getPassTimer(CGSP));
      if (EmitICRemark)
        InstrCount = initSizeRemarkInfo(M);
      Changed = CGSP->runOnSCC(CurSCC);

      if (EmitICRemark) {
        // FIXME: Add getInstructionCount to CallGraphSCC.
        SCCCount = M.getInstructionCount();
        // Is there a difference in the number of instructions in the module?
        if (SCCCount != InstrCount) {
          // Yep. Emit a remark and update InstrCount.
          int64_t Delta =
              static_cast<int64_t>(SCCCount) - static_cast<int64_t>(InstrCount);
          emitInstrCountChangedRemark(P, M, Delta, InstrCount);
          InstrCount = SCCCount;
        }
      }
    }

    // After the CGSCCPass is done, when assertions are enabled, use
    // RefreshCallGraph to verify that the callgraph was correctly updated.
#ifndef NDEBUG
    if (Changed)
      RefreshCallGraph(CurSCC, CG, true);
#endif

    return Changed;
  }

  assert(PM->getPassManagerType() == PMT_FunctionPassManager &&
         "Invalid CGPassManager member");
  FPPassManager *FPP = (FPPassManager*)P;

  // Run pass P on all functions in the current SCC.
  for (CallGraphNode *CGN : CurSCC) {
    if (Function *F = CGN->getFunction()) {
      dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
      {
        TimeRegion PassTimer(getPassTimer(FPP));
        Changed |= FPP->runOnFunction(*F);
      }
      F->getContext().yield();
    }
  }

  // The function pass(es) modified the IR, they may have clobbered the
  // callgraph.
  if (Changed && CallGraphUpToDate) {
    LLVM_DEBUG(dbgs() << "CGSCCPASSMGR: Pass Dirtied SCC: " << P->getPassName()
                      << '\n');
    CallGraphUpToDate = false;
  }
  return Changed;
}
Exemple #8
0
/// Remove dead functions that are not included in DNR (Do Not Remove) list.
bool LegacyInlinerBase::removeDeadFunctions(CallGraph &CG,
                                            bool AlwaysInlineOnly) {
  SmallVector<CallGraphNode *, 16> FunctionsToRemove;
  SmallVector<Function *, 16> DeadFunctionsInComdats;

  auto RemoveCGN = [&](CallGraphNode *CGN) {
    // Remove any call graph edges from the function to its callees.
    CGN->removeAllCalledFunctions();

    // Remove any edges from the external node to the function's call graph
    // node.  These edges might have been made irrelegant due to
    // optimization of the program.
    CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);

    // Removing the node for callee from the call graph and delete it.
    FunctionsToRemove.push_back(CGN);
  };

  // Scan for all of the functions, looking for ones that should now be removed
  // from the program.  Insert the dead ones in the FunctionsToRemove set.
  for (const auto &I : CG) {
    CallGraphNode *CGN = I.second.get();
    Function *F = CGN->getFunction();
    if (!F || F->isDeclaration())
      continue;

    // Handle the case when this function is called and we only want to care
    // about always-inline functions. This is a bit of a hack to share code
    // between here and the InlineAlways pass.
    if (AlwaysInlineOnly && !F->hasFnAttribute(Attribute::AlwaysInline))
      continue;

    // If the only remaining users of the function are dead constants, remove
    // them.
    F->removeDeadConstantUsers();

    if (!F->isDefTriviallyDead())
      continue;

    // It is unsafe to drop a function with discardable linkage from a COMDAT
    // without also dropping the other members of the COMDAT.
    // The inliner doesn't visit non-function entities which are in COMDAT
    // groups so it is unsafe to do so *unless* the linkage is local.
    if (!F->hasLocalLinkage()) {
      if (F->hasComdat()) {
        DeadFunctionsInComdats.push_back(F);
        continue;
      }
    }

    RemoveCGN(CGN);
  }
  if (!DeadFunctionsInComdats.empty()) {
    // Filter out the functions whose comdats remain alive.
    filterDeadComdatFunctions(CG.getModule(), DeadFunctionsInComdats);
    // Remove the rest.
    for (Function *F : DeadFunctionsInComdats)
      RemoveCGN(CG[F]);
  }

  if (FunctionsToRemove.empty())
    return false;

  // Now that we know which functions to delete, do so.  We didn't want to do
  // this inline, because that would invalidate our CallGraph::iterator
  // objects. :(
  //
  // Note that it doesn't matter that we are iterating over a non-stable order
  // here to do this, it doesn't matter which order the functions are deleted
  // in.
  array_pod_sort(FunctionsToRemove.begin(), FunctionsToRemove.end());
  FunctionsToRemove.erase(
      std::unique(FunctionsToRemove.begin(), FunctionsToRemove.end()),
      FunctionsToRemove.end());
  for (CallGraphNode *CGN : FunctionsToRemove) {
    delete CG.removeFunctionFromModule(CGN);
    ++NumDeleted;
  }
  return true;
}
Exemple #9
0
bool LegacyInlinerBase::doInitialization(CallGraph &CG) {
  if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No)
    ImportedFunctionsStats.setModuleInfo(CG.getModule());
  return false; // No changes to CallGraph.
}