[llvm] c777057 - Revert "[unroll] Move multiple exit costing into consumer pass [NFC]"

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 2 13:29:19 PDT 2021


Thanks for the revert.  Now to go figure out a) why I didn't see the 
test failure locally, and b) why the test failed on what should have 
been an NFC.

Philip

On 8/2/21 1:23 PM, Nikita Popov via llvm-commits wrote:
> Author: Nikita Popov
> Date: 2021-08-02T22:23:34+02:00
> New Revision: c7770574f9b1c7b8548bf0596ed2008aa5cc5ca4
>
> URL: https://github.com/llvm/llvm-project/commit/c7770574f9b1c7b8548bf0596ed2008aa5cc5ca4
> DIFF: https://github.com/llvm/llvm-project/commit/c7770574f9b1c7b8548bf0596ed2008aa5cc5ca4.diff
>
> LOG: Revert "[unroll] Move multiple exit costing into consumer pass [NFC]"
>
> This reverts commit 76940577e4bf9c63a8a4ebd32b556bd7feb8cad3.
>
> This causes Transforms/LoopUnroll/ARM/multi-blocks.ll to fail.
>
> Added:
>      
>
> Modified:
>      llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
>      llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp
>
> Removed:
>      
>
>
> ################################################################################
> diff  --git a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
> index b8799622d8ab..49501f324a49 100644
> --- a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
> +++ b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
> @@ -175,14 +175,6 @@ static cl::opt<unsigned>
>                              cl::desc("Default threshold (max size of unrolled "
>                                       "loop), used in all but O3 optimizations"));
>   
> -static cl::opt<bool> UnrollRuntimeMultiExit(
> -    "unroll-runtime-multi-exit", cl::init(false), cl::Hidden,
> -    cl::desc("Allow runtime unrolling for loops with multiple exits, when "
> -             "epilog is generated"));
> -static cl::opt<bool> UnrollRuntimeOtherExitPredictable(
> -    "unroll-runtime-other-exit-predictable", cl::init(false), cl::Hidden,
> -    cl::desc("Assume the non latch exit block to be predictable"));
> -
>   /// A magic value for use with the Threshold parameter to indicate
>   /// that the loop unroll should be performed regardless of how much
>   /// code expansion would result.
> @@ -742,57 +734,6 @@ static unsigned getFullUnrollBoostingFactor(const EstimatedUnrollCost &Cost,
>       return MaxPercentThresholdBoost;
>   }
>   
> -/// Returns true if we can profitably unroll the multi-exit loop L. Currently,
> -/// unrolling a multiple exit loop is generally considered unprofitable outside
> -/// of some very restricted cases.  (TODO: Relax this!)
> -static bool canProfitablyUnrollMultiExitLoop(Loop *L) {
> -
> -  SmallVector<BasicBlock *> OtherExits;
> -  L->getUniqueNonLatchExitBlocks(OtherExits);
> -
> -  // Priority goes to UnrollRuntimeMultiExit if it's supplied.
> -  if (UnrollRuntimeMultiExit.getNumOccurrences())
> -    return UnrollRuntimeMultiExit;
> -
> -  // The main pain point with multi-exit loop unrolling is that once unrolled,
> -  // we will not be able to merge all blocks into a straight line code.
> -  // There are branches within the unrolled loop that go to the OtherExits.
> -  // The second point is the increase in code size, but this is true
> -  // irrespective of multiple exits.
> -
> -  // Note: Both the heuristics below are coarse grained. We are essentially
> -  // enabling unrolling of loops that have a single side exit other than the
> -  // normal LatchExit (i.e. exiting into a deoptimize block).
> -  // The heuristics considered are:
> -  // 1. low number of branches in the unrolled version.
> -  // 2. high predictability of these extra branches.
> -  // We avoid unrolling loops that have more than two exiting blocks. This
> -  // limits the total number of branches in the unrolled loop to be atmost
> -  // the unroll factor (since one of the exiting blocks is the latch block).
> -  SmallVector<BasicBlock*, 4> ExitingBlocks;
> -  L->getExitingBlocks(ExitingBlocks);
> -  if (ExitingBlocks.size() > 2)
> -    return false;
> -
> -  // Allow unrolling of loops with no non latch exit blocks.
> -  if (OtherExits.size() == 0)
> -    return true;
> -
> -  // The second heuristic is that L has one exit other than the latchexit and
> -  // that exit is a deoptimize block. We know that deoptimize blocks are rarely
> -  // taken, which also implies the branch leading to the deoptimize block is
> -  // highly predictable. When UnrollRuntimeOtherExitPredictable is specified, we
> -  // assume the other exit branch is predictable even if it has no deoptimize
> -  // call.
> -  return (OtherExits.size() == 1 &&
> -          (UnrollRuntimeOtherExitPredictable ||
> -           OtherExits[0]->getTerminatingDeoptimizeCall()));
> -  // TODO: These can be fine-tuned further to consider code size or deopt states
> -  // that are captured by the deoptimize exit block.
> -  // Also, we can extend this to support more cases, if we actually
> -  // know of kinds of multiexit loops that would benefit from unrolling.
> -}
> -
>   // Produce an estimate of the unrolled cost of the specified loop.  This
>   // is used to a) produce a cost estimate for partial unrolling and b) to
>   // cheaply estimate cost for full unrolling when we don't want to symbolically
> @@ -1041,13 +982,6 @@ bool llvm::computeUnrollCount(
>       }
>     }
>   
> -  // Is this is a multiple exit loop which we consider unprofitable to
> -  // unroll?
> -  if (!L->getExitingBlock() && !canProfitablyUnrollMultiExitLoop(L)) {
> -    UP.Count = 0;
> -    return false;
> -  }
> -
>     // Reduce count based on the type of unrolling and the threshold values.
>     UP.Runtime |= PragmaEnableUnroll || PragmaCount > 0 || UserUnrollCount;
>     if (!UP.Runtime) {
>
> diff  --git a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp
> index 8305165d401d..e2eb0015af10 100644
> --- a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp
> +++ b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp
> @@ -46,6 +46,13 @@ using namespace llvm;
>   
>   STATISTIC(NumRuntimeUnrolled,
>             "Number of loops unrolled with run-time trip counts");
> +static cl::opt<bool> UnrollRuntimeMultiExit(
> +    "unroll-runtime-multi-exit", cl::init(false), cl::Hidden,
> +    cl::desc("Allow runtime unrolling for loops with multiple exits, when "
> +             "epilog is generated"));
> +static cl::opt<bool> UnrollRuntimeOtherExitPredictable(
> +    "unroll-runtime-other-exit-predictable", cl::init(false), cl::Hidden,
> +    cl::desc("Assume the non latch exit block to be predictable"));
>   
>   /// Connect the unrolling prolog code to the original loop.
>   /// The unrolling prolog code contains code to execute the
> @@ -454,6 +461,61 @@ static bool canSafelyUnrollMultiExitLoop(Loop *L, BasicBlock *LatchExit,
>     return true;
>   }
>   
> +/// Returns true if we can profitably unroll the multi-exit loop L. Currently,
> +/// we return true only if UnrollRuntimeMultiExit is set to true.
> +static bool canProfitablyUnrollMultiExitLoop(
> +    Loop *L, SmallVectorImpl<BasicBlock *> &OtherExits, BasicBlock *LatchExit,
> +    bool PreserveLCSSA, bool UseEpilogRemainder) {
> +
> +#if !defined(NDEBUG)
> +  assert(canSafelyUnrollMultiExitLoop(L, LatchExit, PreserveLCSSA,
> +                                      UseEpilogRemainder) &&
> +         "Should be safe to unroll before checking profitability!");
> +#endif
> +
> +  // Priority goes to UnrollRuntimeMultiExit if it's supplied.
> +  if (UnrollRuntimeMultiExit.getNumOccurrences())
> +    return UnrollRuntimeMultiExit;
> +
> +  // The main pain point with multi-exit loop unrolling is that once unrolled,
> +  // we will not be able to merge all blocks into a straight line code.
> +  // There are branches within the unrolled loop that go to the OtherExits.
> +  // The second point is the increase in code size, but this is true
> +  // irrespective of multiple exits.
> +
> +  // Note: Both the heuristics below are coarse grained. We are essentially
> +  // enabling unrolling of loops that have a single side exit other than the
> +  // normal LatchExit (i.e. exiting into a deoptimize block).
> +  // The heuristics considered are:
> +  // 1. low number of branches in the unrolled version.
> +  // 2. high predictability of these extra branches.
> +  // We avoid unrolling loops that have more than two exiting blocks. This
> +  // limits the total number of branches in the unrolled loop to be atmost
> +  // the unroll factor (since one of the exiting blocks is the latch block).
> +  SmallVector<BasicBlock*, 4> ExitingBlocks;
> +  L->getExitingBlocks(ExitingBlocks);
> +  if (ExitingBlocks.size() > 2)
> +    return false;
> +
> +  // Allow unrolling of loops with no non latch exit blocks.
> +  if (OtherExits.size() == 0)
> +    return true;
> +
> +  // The second heuristic is that L has one exit other than the latchexit and
> +  // that exit is a deoptimize block. We know that deoptimize blocks are rarely
> +  // taken, which also implies the branch leading to the deoptimize block is
> +  // highly predictable. When UnrollRuntimeOtherExitPredictable is specified, we
> +  // assume the other exit branch is predictable even if it has no deoptimize
> +  // call.
> +  return (OtherExits.size() == 1 &&
> +          (UnrollRuntimeOtherExitPredictable ||
> +           OtherExits[0]->getTerminatingDeoptimizeCall()));
> +  // TODO: These can be fine-tuned further to consider code size or deopt states
> +  // that are captured by the deoptimize exit block.
> +  // Also, we can extend this to support more cases, if we actually
> +  // know of kinds of multiexit loops that would benefit from unrolling.
> +}
> +
>   // Assign the maximum possible trip count as the back edge weight for the
>   // remainder loop if the original loop comes with a branch weight.
>   static void updateLatchBranchWeightsForRemainderLoop(Loop *OrigLoop,
> @@ -597,7 +659,9 @@ bool llvm::UnrollRuntimeLoopRemainder(
>     L->getUniqueNonLatchExitBlocks(OtherExits);
>     bool isMultiExitUnrollingEnabled =
>         canSafelyUnrollMultiExitLoop(L, LatchExit, PreserveLCSSA,
> -                                   UseEpilogRemainder);
> +                                   UseEpilogRemainder) &&
> +      canProfitablyUnrollMultiExitLoop(L, OtherExits, LatchExit, PreserveLCSSA,
> +                                       UseEpilogRemainder);
>     // Support only single exit and exiting block unless multi-exit loop unrolling is enabled.
>     if (!isMultiExitUnrollingEnabled &&
>         (!L->getExitingBlock() || OtherExits.size())) {
>
>
>          
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list