Index: include/llvm/Transforms/Scalar/LoopUnrollPass.h =================================================================== --- include/llvm/Transforms/Scalar/LoopUnrollPass.h +++ include/llvm/Transforms/Scalar/LoopUnrollPass.h @@ -10,6 +10,7 @@ #ifndef LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H #define LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H +#include "llvm/ADT/Optional.h" #include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/IR/PassManager.h" @@ -35,12 +36,45 @@ /// It will also put loops into canonical form (simplified and LCSSA). class LoopUnrollPass : public PassInfoMixin { const int OptLevel; + Optional AllowPartial; + Optional AllowRuntime; + Optional AllowPeeling; + Optional AllowUpperBound; public: /// This uses the target information (or flags) to control the thresholds for /// different unrolling stategies but supports all of them. explicit LoopUnrollPass(int OptLevel = 2) : OptLevel(OptLevel) {} + /// Selector for the optional behavior - Partial unrolling. + /// Call with \p Partial being true to enable, false to disable. + /// Without calling this a global default will be used. + LoopUnrollPass &&setPartial(bool Partial) && { + AllowPartial = Partial; + return std::move(*this); + } + /// Selector for the optional behavior - Runtime unrolling. + /// Call with \p Runtime being true to enable, false to disable. + /// Without calling this a global default will be used. + LoopUnrollPass &&setRuntime(bool Runtime) && { + AllowRuntime = Runtime; + return std::move(*this); + } + /// Selector for the optional behavior - Peeling. + /// Call with \p Peeling being true to enable, false to disable. + /// Without calling this a global default will be used. + LoopUnrollPass &&setPeeling(bool Peeling) && { + AllowPeeling = Peeling; + return std::move(*this); + } + /// Selector for the optional behavior - UpperBound. + /// Call with \p UpperBound being true to enable, false to disable. + /// Without calling this a global default will be used. + LoopUnrollPass &&setUpperBound(bool UpperBound) && { + AllowUpperBound = UpperBound; + return std::move(*this); + } + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; Index: lib/Transforms/Scalar/LoopUnrollPass.cpp =================================================================== --- lib/Transforms/Scalar/LoopUnrollPass.cpp +++ lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -1333,23 +1333,21 @@ 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 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. if (PSI && PSI->hasHugeWorkingSetSize()) AllowPeeling = false; std::string LoopName = L.getName(); + // The API here is quite complex to call and we allow to select some + // flavors of unrolling during construction time (by setting Allow* values). + // As soon as the caller does not care we pass None for the corresponding + // optional to avoid providing an explicit choice. LoopUnrollResult Result = tryToUnrollLoop(&L, DT, &LI, SE, TTI, AC, ORE, /*PreserveLCSSA*/ true, OptLevel, /*Count*/ None, - /*Threshold*/ None, AllowPartialParam, RuntimeParam, - UpperBoundParam, AllowPeeling); + /*Threshold*/ None, AllowPartial, AllowRuntime, + AllowUpperBound, AllowPeeling); Changed |= Result != LoopUnrollResult::Unmodified; // The parent must not be damaged by unrolling!