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,33 @@ /// 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,22 @@ 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!