Index: llvm/include/llvm/Transforms/IPO/Attributor.h =================================================================== --- llvm/include/llvm/Transforms/IPO/Attributor.h +++ llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1409,6 +1409,12 @@ const AbstractAttribute *QueryingAA, bool &AllCallSitesKnown); + /// Efficiently compute the intersections between Values that can be + /// reached forwards from the arguments and the Values that can be + /// reached backwards from the instructions that would benefit. + /// from call site specific information. + void populateArgumentPathwayForFunction(Function *Funct); + /// Determine if CallBase context in \p IRP should be propagated. bool shouldPropagateCallBaseContext(const IRPosition &IRP); @@ -1498,6 +1504,9 @@ SmallPtrSet ToBeDeletedBlocks; SmallDenseSet ToBeDeletedInsts; ///} + + /// Values per function that are relevant to the call base context. + DenseMap> ArgumentPathway; }; /// An interface to query the internal state of an abstract attribute. Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -89,6 +89,12 @@ cl::desc("Allow the Attributor to do call site specific analysis"), cl::init(false)); +static cl::opt + CallSiteSpecificDepth("attributor-call-site-depth", cl::Hidden, + cl::desc("Maximum depth of values that call site " + "specific analysis will invalidate."), + cl::init(6)); + /// Logic operators for the change status enum class. /// ///{ @@ -797,11 +803,89 @@ return true; } +void Attributor::populateArgumentPathwayForFunction(Function *Funct) { + assert(Funct != nullptr); + + SmallVector SuccsessfullValues; + SmallVector Worklist; + SmallPtrSet ForwardsVisited; + + for (Argument *V = Funct->arg_begin(); V != Funct->arg_end(); V++) { + Worklist.push_back(V); + } + + for (unsigned I = 0; I < CallSiteSpecificDepth && !Worklist.empty(); I++) { + Value *Val = Worklist.pop_back_val(); + + // Avoid infinite loops. + if (!ForwardsVisited.insert(Val).second) + continue; + + if (auto *Instr = dyn_cast(Val)) { + // Keep track of important instructions. + if (Instr->isTerminator()) + SuccsessfullValues.push_back(Instr); + } + + for (User *U : Val->users()) + Worklist.push_back(U); + } + + Worklist.assign(SuccsessfullValues.begin(), SuccsessfullValues.end()); + + SmallSet BackwardsVisited; + for (unsigned I = 0; I < CallSiteSpecificDepth && !Worklist.empty(); I++) { + Value *Val = Worklist.pop_back_val(); + + // Avoid infinite loops. + if (!BackwardsVisited.insert(Val).second) + continue; + + for (Use &U : Val->uses()) { + // Avoid visiting nodes that can not be reached by the arguments. + // this creates the intersection. + if (ForwardsVisited.count((Value *)U)) + continue; + Worklist.push_back((Value *)U); + } + } + + LLVM_DEBUG(dbgs() << "[Attributor] Argument pathway for function: " << *Funct + << "\n"); + for (SmallPtrSet::iterator it = ForwardsVisited.begin(); + it != ForwardsVisited.end(); it++) { + LLVM_DEBUG(dbgs() << "[Attributor]" << **it << " is in Argument Pathway." + << "\n"); + } + ArgumentPathway[Funct] = std::move(ForwardsVisited); +} + bool Attributor::shouldPropagateCallBaseContext(const IRPosition &IRP) { - // TODO: Maintain a cache of Values that are on the pathway from a Argument to - // a - // Instruction that would effect the liveness/return state etc. - return EnableCallSiteSpecific; + if (!EnableCallSiteSpecific) + return false; + + // Certain positions must always propogate call base context. + switch (IRP.getPositionKind()) { + case IRPosition::IRP_RETURNED: + case IRPosition::IRP_ARGUMENT: + case IRPosition::IRP_FUNCTION: + return true; + case IRPosition::IRP_FLOAT: + break; + default: + return false; + } + Function *Func = IRP.getAssociatedFunction(); + if (!Func) + return false; + + auto ArgPathwayIt = ArgumentPathway.find(Func); + if (ArgPathwayIt == ArgumentPathway.end()) { + populateArgumentPathwayForFunction(Func); + ArgPathwayIt = ArgumentPathway.find(Func); + } + + return ((*ArgPathwayIt).second).count(&IRP.getAnchorValue()); } bool Attributor::checkForAllReturnedValuesAndReturnInsts(