Index: llvm/trunk/include/llvm/Transforms/IPO/Attributor.h =================================================================== --- llvm/trunk/include/llvm/Transforms/IPO/Attributor.h +++ llvm/trunk/include/llvm/Transforms/IPO/Attributor.h @@ -568,7 +568,15 @@ /// NOTE: The mechanics of adding a new "concrete" abstract attribute are /// described in the file comment. struct Attributor { - Attributor(InformationCache &InfoCache) : InfoCache(InfoCache) {} + /// Constructor + /// + /// \param InformationCache Cache to hold various information accessible for + /// the abstract attributes. + /// \param DepRecomputeInterval Number of iterations until the dependences + /// between abstract attributes are recomputed. + Attributor(InformationCache &InfoCache, unsigned DepRecomputeInterval) + : InfoCache(InfoCache), DepRecomputeInterval(DepRecomputeInterval) {} + ~Attributor() { DeleteContainerPointers(AllAbstractAttributes); } /// Run the analyses until a fixpoint is reached or enforced (timeout). @@ -775,6 +783,10 @@ /// The information cache that holds pre-processed (LLVM-IR) information. InformationCache &InfoCache; + /// Number of iterations until the dependences between abstract attributes are + /// recomputed. + const unsigned DepRecomputeInterval; + /// Functions, blocks, and instructions we delete after manifest is done. /// ///{ Index: llvm/trunk/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/Attributor.cpp +++ llvm/trunk/lib/Transforms/IPO/Attributor.cpp @@ -123,6 +123,11 @@ "manifestation of attributes -- may issue false-positive errors"), cl::init(false)); +static cl::opt DepRecInterval( + "attributor-dependence-recompute-interval", cl::Hidden, + cl::desc("Number of iterations until dependences are recomputed."), + cl::init(4)); + /// Logic operators for the change status enum class. /// ///{ @@ -2548,12 +2553,25 @@ SetVector Worklist; Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end()); + bool RecomputeDependences = false; + do { // Remember the size to determine new attributes. size_t NumAAs = AllAbstractAttributes.size(); 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) { + LLVM_DEBUG( + dbgs() << "[Attributor] Run all AAs to recompute dependences\n"); + 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) { @@ -2575,6 +2593,10 @@ if (AA->update(*this) == ChangeStatus::CHANGED) ChangedAAs.push_back(AA); + // Check if we recompute the dependences in the next iteration. + RecomputeDependences = (DepRecomputeInterval > 0 && + IterationCounter % DepRecomputeInterval == 0); + // Add attributes to the changed set if they have been created in the last // iteration. ChangedAAs.append(AllAbstractAttributes.begin() + NumAAs, @@ -2589,13 +2611,18 @@ size_t NumFinalAAs = AllAbstractAttributes.size(); + if (VerifyMaxFixpointIterations && IterationCounter != MaxFixpointIterations) { + errs() << "\n[Attributor] Fixpoint iteration done after: " + << IterationCounter << "/" << MaxFixpointIterations + << " iterations\n"; + llvm_unreachable("The fixpoint was not reached with exactly the number of " + "specified iterations!"); + } + LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: " << IterationCounter << "/" << MaxFixpointIterations << " iterations\n"); - if (VerifyMaxFixpointIterations && IterationCounter != MaxFixpointIterations) - llvm_unreachable("The fixpoint was not reached with exactly the number of " - "specified iterations!"); bool FinishedAtFixpoint = Worklist.empty(); @@ -2930,7 +2957,7 @@ // Create an Attributor and initially empty information cache that is filled // while we identify default attribute opportunities. InformationCache InfoCache(M.getDataLayout()); - Attributor A(InfoCache); + Attributor A(InfoCache, DepRecInterval); for (Function &F : M) { // TODO: Not all attributes require an exact definition. Find a way to Index: llvm/trunk/test/Transforms/FunctionAttrs/align.ll =================================================================== --- llvm/trunk/test/Transforms/FunctionAttrs/align.ll +++ llvm/trunk/test/Transforms/FunctionAttrs/align.ll @@ -1,4 +1,4 @@ -; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR +; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=14 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll =================================================================== --- llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll +++ llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll @@ -1,6 +1,6 @@ ; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=BOTH,FNATTR ; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=BOTH,FNATTR -; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=BOTH,ATTRIBUTOR +; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=10 -S < %s | FileCheck %s --check-prefixes=BOTH,ATTRIBUTOR target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: llvm/trunk/test/Transforms/FunctionAttrs/noreturn_sync.ll =================================================================== --- llvm/trunk/test/Transforms/FunctionAttrs/noreturn_sync.ll +++ llvm/trunk/test/Transforms/FunctionAttrs/noreturn_sync.ll @@ -1,4 +1,4 @@ -; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 -S < %s | FileCheck %s +; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s ; ; This file is the same as noreturn_async.ll but with a personality which ; indicates that the exception handler *cannot* catch asynchronous exceptions.