From c9da41492fb9dcd03376fb7ce63f1e861bae7382 Mon Sep 17 00:00:00 2001 From: Michael Zolotukhin Date: Fri, 6 Feb 2015 20:20:40 +0000 Subject: [PATCH] Use estimated number of optimized insns in unroll-threshold computation. If complete-unroll could help us to optimize away N% of instructions, we might want to do this even if the final size would exceed loop-unroll threshold. However, we don't want to unroll huge loop, and we are add AbsoluteThreshold to avoid that - this threshold will never be crossed, even if we expect to optimize 99% instructions after that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228434 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/TargetTransformInfo.h | 7 ++++ lib/Transforms/Scalar/LoopUnrollPass.cpp | 46 ++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 1c3bcdbdf74..15eab52d6a1 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -217,6 +217,13 @@ public: /// exceed this cost. Set this to UINT_MAX to disable the loop body cost /// restriction. unsigned Threshold; + /// If complete unrolling could help other optimizations (e.g. InstSimplify) + /// to remove N% of instructions, then we can go beyond unroll threshold. + /// This value set the minimal percent for allowing that. + unsigned MinPercentOfOptimized; + /// The absolute cost threshold. We won't go beyond this even if complete + /// unrolling could result in optimizing out 90% of instructions. + unsigned AbsoluteThreshold; /// The cost threshold for the unrolled loop when optimizing for size (set /// to UINT_MAX to disable). unsigned OptSizeThreshold; diff --git a/lib/Transforms/Scalar/LoopUnrollPass.cpp b/lib/Transforms/Scalar/LoopUnrollPass.cpp index 87237c62299..f691beb7219 100644 --- a/lib/Transforms/Scalar/LoopUnrollPass.cpp +++ b/lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -45,6 +45,17 @@ static cl::opt UnrollMaxIterationsCountToAnalyze( cl::desc("Don't allow loop unrolling to simulate more than this number of" "iterations when checking full unroll profitability")); +static cl::opt UnrollMinPercentOfOptimized( + "unroll-percent-of-optimized-for-complete-unroll", cl::init(20), cl::Hidden, + cl::desc("If complete unrolling could trigger further optimizations, and, " + "by that, remove the given percent of instructions, perform the " + "complete unroll even if it's beyond the threshold")); + +static cl::opt UnrollAbsoluteThreshold( + "unroll-absolute-threshold", cl::init(2000), cl::Hidden, + cl::desc("Don't unroll if the unrolled size is bigger than this threshold," + " even if we can remove big portion of instructions later.")); + static cl::opt UnrollCount("unroll-count", cl::init(0), cl::Hidden, cl::desc("Use this unroll count for all loops including those with " @@ -70,11 +81,16 @@ namespace { static char ID; // Pass ID, replacement for typeid LoopUnroll(int T = -1, int C = -1, int P = -1, int R = -1) : LoopPass(ID) { CurrentThreshold = (T == -1) ? UnrollThreshold : unsigned(T); + CurrentAbsoluteThreshold = UnrollAbsoluteThreshold; + CurrentMinPercentOfOptimized = UnrollMinPercentOfOptimized; CurrentCount = (C == -1) ? UnrollCount : unsigned(C); CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P; CurrentRuntime = (R == -1) ? UnrollRuntime : (bool)R; UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0); + UserAbsoluteThreshold = (UnrollAbsoluteThreshold.getNumOccurrences() > 0); + UserPercentOfOptimized = + (UnrollMinPercentOfOptimized.getNumOccurrences() > 0); UserAllowPartial = (P != -1) || (UnrollAllowPartial.getNumOccurrences() > 0); UserRuntime = (R != -1) || (UnrollRuntime.getNumOccurrences() > 0); @@ -98,10 +114,16 @@ namespace { unsigned CurrentCount; unsigned CurrentThreshold; + unsigned CurrentAbsoluteThreshold; + unsigned CurrentMinPercentOfOptimized; bool CurrentAllowPartial; bool CurrentRuntime; bool UserCount; // CurrentCount is user-specified. bool UserThreshold; // CurrentThreshold is user-specified. + bool UserAbsoluteThreshold; // CurrentAbsoluteThreshold is + // user-specified. + bool UserPercentOfOptimized; // CurrentMinPercentOfOptimized is + // user-specified. bool UserAllowPartial; // CurrentAllowPartial is user-specified. bool UserRuntime; // CurrentRuntime is user-specified. @@ -133,6 +155,8 @@ namespace { void getUnrollingPreferences(Loop *L, const TargetTransformInfo &TTI, TargetTransformInfo::UnrollingPreferences &UP) { UP.Threshold = CurrentThreshold; + UP.AbsoluteThreshold = CurrentAbsoluteThreshold; + UP.MinPercentOfOptimized = CurrentMinPercentOfOptimized; UP.OptSizeThreshold = OptSizeUnrollThreshold; UP.PartialThreshold = CurrentThreshold; UP.PartialOptSizeThreshold = OptSizeUnrollThreshold; @@ -160,13 +184,32 @@ namespace { void selectThresholds(const Loop *L, bool HasPragma, const TargetTransformInfo::UnrollingPreferences &UP, unsigned &Threshold, unsigned &PartialThreshold, - unsigned NumberOfSimplifiedInstructions) { + unsigned NumberOfOptimizedInstructions) { // Determine the current unrolling threshold. While this is // normally set from UnrollThreshold, it is overridden to a // smaller value if the current function is marked as // optimize-for-size, and the unroll threshold was not user // specified. Threshold = UserThreshold ? CurrentThreshold : UP.Threshold; + + // If we are allowed to completely unroll if we can remove M% of + // instructions, and we know that with complete unrolling we'll be able + // to kill N instructions, then we can afford to completely unroll loops + // with unrolled size up to N*100/M. + // Adjust the threshold according to that: + unsigned PercentOfOptimizedForCompleteUnroll = + UserPercentOfOptimized ? CurrentMinPercentOfOptimized + : UP.MinPercentOfOptimized; + unsigned AbsoluteThreshold = UserAbsoluteThreshold + ? CurrentAbsoluteThreshold + : UP.AbsoluteThreshold; + if (PercentOfOptimizedForCompleteUnroll) + Threshold = std::max(Threshold, + NumberOfOptimizedInstructions * 100 / + PercentOfOptimizedForCompleteUnroll); + // But don't allow unrolling loops bigger than absolute threshold. + Threshold = std::min(Threshold, AbsoluteThreshold); + PartialThreshold = UserThreshold ? CurrentThreshold : UP.PartialThreshold; if (!UserThreshold && L->getHeader()->getParent()->getAttributes(). @@ -186,7 +229,6 @@ namespace { PartialThreshold = std::max(PartialThreshold, PragmaUnrollThreshold); } - Threshold += NumberOfSimplifiedInstructions; } }; } -- 2.34.1