diff options
Diffstat (limited to 'lib/Transforms/Scalar/LoopUnrollPass.cpp')
| -rw-r--r-- | lib/Transforms/Scalar/LoopUnrollPass.cpp | 116 | 
1 files changed, 79 insertions, 37 deletions
diff --git a/lib/Transforms/Scalar/LoopUnrollPass.cpp b/lib/Transforms/Scalar/LoopUnrollPass.cpp index e955821effa0d..38b80f48ed0e2 100644 --- a/lib/Transforms/Scalar/LoopUnrollPass.cpp +++ b/lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -540,7 +540,7 @@ static Optional<EstimatedUnrollCost> analyzeLoopUnrollCost(          }        } -      TerminatorInst *TI = BB->getTerminator(); +      Instruction *TI = BB->getTerminator();        // Add in the live successors by first checking whether we have terminator        // that may be simplified based on the values simplified by this call. @@ -661,11 +661,6 @@ static bool HasUnrollEnablePragma(const Loop *L) {    return GetUnrollMetadataForLoop(L, "llvm.loop.unroll.enable");  } -// Returns true if the loop has an unroll(disable) pragma. -static bool HasUnrollDisablePragma(const Loop *L) { -  return GetUnrollMetadataForLoop(L, "llvm.loop.unroll.disable"); -} -  // Returns true if the loop has an runtime unroll(disable) pragma.  static bool HasRuntimeUnrollDisablePragma(const Loop *L) {    return GetUnrollMetadataForLoop(L, "llvm.loop.unroll.runtime.disable"); @@ -713,12 +708,19 @@ static uint64_t getUnrolledLoopSize(  // Returns true if unroll count was set explicitly.  // Calculates unroll count and writes it to UP.Count. +// Unless IgnoreUser is true, will also use metadata and command-line options +// that are specific to to the LoopUnroll pass (which, for instance, are +// irrelevant for the LoopUnrollAndJam pass). +// FIXME: This function is used by LoopUnroll and LoopUnrollAndJam, but consumes +// many LoopUnroll-specific options. The shared functionality should be +// refactored into it own function.  bool llvm::computeUnrollCount(      Loop *L, const TargetTransformInfo &TTI, DominatorTree &DT, LoopInfo *LI,      ScalarEvolution &SE, const SmallPtrSetImpl<const Value *> &EphValues,      OptimizationRemarkEmitter *ORE, unsigned &TripCount, unsigned MaxTripCount,      unsigned &TripMultiple, unsigned LoopSize,      TargetTransformInfo::UnrollingPreferences &UP, bool &UseUpperBound) { +    // Check for explicit Count.    // 1st priority is unroll count set by "unroll-count" option.    bool UserUnrollCount = UnrollCount.getNumOccurrences() > 0; @@ -801,7 +803,7 @@ bool llvm::computeUnrollCount(      }    } -  // 4th priority is loop peeling +  // 4th priority is loop peeling.    computePeelCount(L, LoopSize, UP, TripCount, SE);    if (UP.PeelCount) {      UP.Runtime = false; @@ -963,13 +965,15 @@ static LoopUnrollResult tryToUnrollLoop(      Loop *L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution &SE,      const TargetTransformInfo &TTI, AssumptionCache &AC,      OptimizationRemarkEmitter &ORE, bool PreserveLCSSA, int OptLevel, -    Optional<unsigned> ProvidedCount, Optional<unsigned> ProvidedThreshold, -    Optional<bool> ProvidedAllowPartial, Optional<bool> ProvidedRuntime, -    Optional<bool> ProvidedUpperBound, Optional<bool> ProvidedAllowPeeling) { +    bool OnlyWhenForced, Optional<unsigned> ProvidedCount, +    Optional<unsigned> ProvidedThreshold, Optional<bool> ProvidedAllowPartial, +    Optional<bool> ProvidedRuntime, Optional<bool> ProvidedUpperBound, +    Optional<bool> ProvidedAllowPeeling) {    LLVM_DEBUG(dbgs() << "Loop Unroll: F["                      << L->getHeader()->getParent()->getName() << "] Loop %"                      << L->getHeader()->getName() << "\n"); -  if (HasUnrollDisablePragma(L)) +  TransformationMode TM = hasUnrollTransformation(L); +  if (TM & TM_Disable)      return LoopUnrollResult::Unmodified;    if (!L->isLoopSimplifyForm()) {      LLVM_DEBUG( @@ -977,6 +981,11 @@ static LoopUnrollResult tryToUnrollLoop(      return LoopUnrollResult::Unmodified;    } +  // When automtatic unrolling is disabled, do not unroll unless overridden for +  // this loop. +  if (OnlyWhenForced && !(TM & TM_Enable)) +    return LoopUnrollResult::Unmodified; +    unsigned NumInlineCandidates;    bool NotDuplicatable;    bool Convergent; @@ -1066,14 +1075,39 @@ static LoopUnrollResult tryToUnrollLoop(    if (TripCount && UP.Count > TripCount)      UP.Count = TripCount; +  // Save loop properties before it is transformed. +  MDNode *OrigLoopID = L->getLoopID(); +    // Unroll the loop. +  Loop *RemainderLoop = nullptr;    LoopUnrollResult UnrollResult = UnrollLoop(        L, UP.Count, TripCount, UP.Force, UP.Runtime, UP.AllowExpensiveTripCount,        UseUpperBound, MaxOrZero, TripMultiple, UP.PeelCount, UP.UnrollRemainder, -      LI, &SE, &DT, &AC, &ORE, PreserveLCSSA); +      LI, &SE, &DT, &AC, &ORE, PreserveLCSSA, &RemainderLoop);    if (UnrollResult == LoopUnrollResult::Unmodified)      return LoopUnrollResult::Unmodified; +  if (RemainderLoop) { +    Optional<MDNode *> RemainderLoopID = +        makeFollowupLoopID(OrigLoopID, {LLVMLoopUnrollFollowupAll, +                                        LLVMLoopUnrollFollowupRemainder}); +    if (RemainderLoopID.hasValue()) +      RemainderLoop->setLoopID(RemainderLoopID.getValue()); +  } + +  if (UnrollResult != LoopUnrollResult::FullyUnrolled) { +    Optional<MDNode *> NewLoopID = +        makeFollowupLoopID(OrigLoopID, {LLVMLoopUnrollFollowupAll, +                                        LLVMLoopUnrollFollowupUnrolled}); +    if (NewLoopID.hasValue()) { +      L->setLoopID(NewLoopID.getValue()); + +      // Do not setLoopAlreadyUnrolled if loop attributes have been specified +      // explicitly. +      return UnrollResult; +    } +  } +    // If loop has an unroll count pragma or unrolled by explicitly set count    // mark loop as unrolled to prevent unrolling beyond that requested.    // If the loop was peeled, we already "used up" the profile information @@ -1092,6 +1126,12 @@ public:    static char ID; // Pass ID, replacement for typeid    int OptLevel; + +  /// If false, use a cost model to determine whether unrolling of a loop is +  /// profitable. If true, only loops that explicitly request unrolling via +  /// metadata are considered. All other loops are skipped. +  bool OnlyWhenForced; +    Optional<unsigned> ProvidedCount;    Optional<unsigned> ProvidedThreshold;    Optional<bool> ProvidedAllowPartial; @@ -1099,15 +1139,16 @@ public:    Optional<bool> ProvidedUpperBound;    Optional<bool> ProvidedAllowPeeling; -  LoopUnroll(int OptLevel = 2, Optional<unsigned> Threshold = None, +  LoopUnroll(int OptLevel = 2, bool OnlyWhenForced = false, +             Optional<unsigned> Threshold = None,               Optional<unsigned> Count = None,               Optional<bool> AllowPartial = None, Optional<bool> Runtime = None,               Optional<bool> UpperBound = None,               Optional<bool> AllowPeeling = None) -      : LoopPass(ID), OptLevel(OptLevel), ProvidedCount(std::move(Count)), -        ProvidedThreshold(Threshold), ProvidedAllowPartial(AllowPartial), -        ProvidedRuntime(Runtime), ProvidedUpperBound(UpperBound), -        ProvidedAllowPeeling(AllowPeeling) { +      : LoopPass(ID), OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), +        ProvidedCount(std::move(Count)), ProvidedThreshold(Threshold), +        ProvidedAllowPartial(AllowPartial), ProvidedRuntime(Runtime), +        ProvidedUpperBound(UpperBound), ProvidedAllowPeeling(AllowPeeling) {      initializeLoopUnrollPass(*PassRegistry::getPassRegistry());    } @@ -1130,8 +1171,8 @@ public:      bool PreserveLCSSA = mustPreserveAnalysisID(LCSSAID);      LoopUnrollResult Result = tryToUnrollLoop( -        L, DT, LI, SE, TTI, AC, ORE, PreserveLCSSA, OptLevel, ProvidedCount, -        ProvidedThreshold, ProvidedAllowPartial, ProvidedRuntime, +        L, DT, LI, SE, TTI, AC, ORE, PreserveLCSSA, OptLevel, OnlyWhenForced, +        ProvidedCount, ProvidedThreshold, ProvidedAllowPartial, ProvidedRuntime,          ProvidedUpperBound, ProvidedAllowPeeling);      if (Result == LoopUnrollResult::FullyUnrolled) @@ -1161,14 +1202,16 @@ INITIALIZE_PASS_DEPENDENCY(LoopPass)  INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)  INITIALIZE_PASS_END(LoopUnroll, "loop-unroll", "Unroll loops", false, false) -Pass *llvm::createLoopUnrollPass(int OptLevel, int Threshold, int Count, -                                 int AllowPartial, int Runtime, int UpperBound, +Pass *llvm::createLoopUnrollPass(int OptLevel, bool OnlyWhenForced, +                                 int Threshold, int Count, int AllowPartial, +                                 int Runtime, int UpperBound,                                   int AllowPeeling) {    // TODO: It would make more sense for this function to take the optionals    // directly, but that's dangerous since it would silently break out of tree    // callers.    return new LoopUnroll( -      OptLevel, Threshold == -1 ? None : Optional<unsigned>(Threshold), +      OptLevel, OnlyWhenForced, +      Threshold == -1 ? None : Optional<unsigned>(Threshold),        Count == -1 ? None : Optional<unsigned>(Count),        AllowPartial == -1 ? None : Optional<bool>(AllowPartial),        Runtime == -1 ? None : Optional<bool>(Runtime), @@ -1176,8 +1219,8 @@ Pass *llvm::createLoopUnrollPass(int OptLevel, int Threshold, int Count,        AllowPeeling == -1 ? None : Optional<bool>(AllowPeeling));  } -Pass *llvm::createSimpleLoopUnrollPass(int OptLevel) { -  return createLoopUnrollPass(OptLevel, -1, -1, 0, 0, 0, 0); +Pass *llvm::createSimpleLoopUnrollPass(int OptLevel, bool OnlyWhenForced) { +  return createLoopUnrollPass(OptLevel, OnlyWhenForced, -1, -1, 0, 0, 0, 0);  }  PreservedAnalyses LoopFullUnrollPass::run(Loop &L, LoopAnalysisManager &AM, @@ -1207,7 +1250,8 @@ PreservedAnalyses LoopFullUnrollPass::run(Loop &L, LoopAnalysisManager &AM,    bool Changed =        tryToUnrollLoop(&L, AR.DT, &AR.LI, AR.SE, AR.TTI, AR.AC, *ORE, -                      /*PreserveLCSSA*/ true, OptLevel, /*Count*/ None, +                      /*PreserveLCSSA*/ true, OptLevel, OnlyWhenForced, +                      /*Count*/ None,                        /*Threshold*/ None, /*AllowPartial*/ false,                        /*Runtime*/ false, /*UpperBound*/ false,                        /*AllowPeeling*/ false) != LoopUnrollResult::Unmodified; @@ -1333,23 +1377,21 @@ PreservedAnalyses LoopUnrollPass::run(Function &F,      Loop *ParentL = L.getParentLoop();  #endif -    // The API here is quite complex to call, but there are only two interesting -    // states we support: partial and full (or "simple") unrolling. However, to -    // enable these things we actually pass "None" in for the optional to avoid -    // providing an explicit choice. -    Optional<bool> AllowPartialParam, RuntimeParam, UpperBoundParam, -        AllowPeeling;      // Check if the profile summary indicates that the profiled application      // has a huge working set size, in which case we disable peeling to avoid      // bloating it further. +    Optional<bool> LocalAllowPeeling = UnrollOpts.AllowPeeling;      if (PSI && PSI->hasHugeWorkingSetSize()) -      AllowPeeling = false; +      LocalAllowPeeling = false;      std::string LoopName = L.getName(); -    LoopUnrollResult Result = -        tryToUnrollLoop(&L, DT, &LI, SE, TTI, AC, ORE, -                        /*PreserveLCSSA*/ true, OptLevel, /*Count*/ None, -                        /*Threshold*/ None, AllowPartialParam, RuntimeParam, -                        UpperBoundParam, AllowPeeling); +    // The API here is quite complex to call and we allow to select some +    // flavors of unrolling during construction time (by setting UnrollOpts). +    LoopUnrollResult Result = tryToUnrollLoop( +        &L, DT, &LI, SE, TTI, AC, ORE, +        /*PreserveLCSSA*/ true, UnrollOpts.OptLevel, UnrollOpts.OnlyWhenForced, +        /*Count*/ None, +        /*Threshold*/ None, UnrollOpts.AllowPartial, UnrollOpts.AllowRuntime, +        UnrollOpts.AllowUpperBound, LocalAllowPeeling);      Changed |= Result != LoopUnrollResult::Unmodified;      // The parent must not be damaged by unrolling!  | 
