diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -149,6 +149,14 @@ /// NOTE: The mechanics of adding a new "concrete" abstract attribute are /// described in the file comment. struct Attributor { + /// Constructor + /// + /// \param DependenceRecomputeInterval Number of iterations until the + /// dependences between abstract attributes are recomputed. + Attributor(unsigned DependenceRecomputeInterval) + : DependenceRecomputeInterval(DependenceRecomputeInterval) {} + + /// Destructor ~Attributor() { DeleteContainerPointers(AllAbstractAttributes); } /// Run the analyses until a fixpoint is reached or enforced (timeout). @@ -298,6 +306,10 @@ QueryMapTy QueryMap; ///} + /// Number of iterations until the dependences between abstract attributes are + /// recomputed. + const unsigned DependenceRecomputeInterval; + /// Check if the state of the abstract attribute \p AA may depend on /// information derived from a non-exact definition. /// diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -64,6 +64,11 @@ cl::desc("Maximal number of fixpoint iterations."), cl::init(32)); +static cl::opt DepRecInterval( + "attributor-dependence-recompute-interval", cl::Hidden, + cl::desc("Number of iterations until dependences are recomputed."), + cl::init(0)); + static cl::opt DisableAttributor( "attributor-disable", cl::Hidden, cl::desc("Disable the attributor inter-procedural deduction pass."), @@ -675,10 +680,21 @@ SetVector Worklist; Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end()); + bool RecomputeDependences = false; + do { LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter << ", Worklist size: " << Worklist.size() << "\n"); + // If dependences (=QueryMap) are recomputed we have to look at all abstract + // attributes again, regardless of what changed in the last iteration. + if (RecomputeDependences) { + QueryMap.clear(); + ChangedAAs.clear(); + Worklist.insert(AllAbstractAttributes.begin(), + AllAbstractAttributes.end()); + } + // Add all abstract attributes that are potentially dependent on one that // changed to the work list. for (AbstractAttribute *ChangedAA : ChangedAAs) { @@ -695,10 +711,16 @@ if (AA->update(*this) == ChangeStatus::CHANGED) ChangedAAs.push_back(AA); + // Check if we recompute the dependences in the next iteration. + RecomputeDependences = + (DependenceRecomputeInterval > 0 && + IterationCounter % DependenceRecomputeInterval == 0); + // Reset the work list and repopulate with the changed abstract attributes. // Note that dependent ones are added above. Worklist.clear(); - Worklist.insert(ChangedAAs.begin(), ChangedAAs.end()); + if (!RecomputeDependences) + Worklist.insert(ChangedAAs.begin(), ChangedAAs.end()); } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations); @@ -987,7 +1009,7 @@ // Create an Attributor and initially empty information cache that is filled // while we identify default attribute opportunities. - Attributor A; + Attributor A(DepRecInterval); InformationCache InfoCache; for (Function &F : M) {