Commit 3dcaf296 authored by Arkady Shlykov's avatar Arkady Shlykov
Browse files

[Loop Peeling] Add possibility to enable peeling on loop nests.

Summary:
Current peeling implementation bails out in case of loop nests.
The patch introduces a field in TargetTransformInfo structure that
certain targets can use to relax the constraints if it's
profitable (disabled by default).
Also additional option is added to enable peeling manually for
experimenting and testing purposes.

Reviewers: fhahn, lebedev.ri, xbolva00

Reviewed By: xbolva00

Subscribers: RKSimon, xbolva00, hiraditya, zzheng, llvm-commits

Differential Revision: https://reviews.llvm.org/D70304
parent 78f9e5d0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -494,6 +494,8 @@ public:
    bool UpperBound;
    /// Allow peeling off loop iterations.
    bool AllowPeeling;
    /// Allow peeling off loop iterations for loop nests.
    bool AllowLoopNestsPeeling;
    /// Allow unrolling of all the iterations of the runtime loop remainder.
    bool UnrollRemainder;
    /// Allow unroll and jam. Used to enable unroll and jam for the target.
+8 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "llvm/Analysis/DemandedBits.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/IVDescriptors.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MustExecute.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Dominators.h"
@@ -31,6 +32,7 @@
#include "llvm/IR/Operator.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Casting.h"
#include "llvm/Transforms/Utils/ValueMapper.h"

namespace llvm {

@@ -426,6 +428,12 @@ void appendReversedLoopsToWorklist(RangeT &&,
/// already reversed loops in LI.
/// FIXME: Consider changing the order in LoopInfo.
void appendLoopsToWorklist(LoopInfo &, SmallPriorityWorklist<Loop *, 4> &);

/// Recursively clone the specified loop and all of its children,
/// mapping the blocks with the specified map.
Loop *cloneLoop(Loop *L, Loop *PL, ValueToValueMapTy &VM,
                LoopInfo *LI, LPPassManager *LPM);

} // end namespace llvm

#endif // LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
+7 −0
Original line number Diff line number Diff line
@@ -154,6 +154,10 @@ static cl::opt<bool>
                       cl::desc("Allows loops to be peeled when the dynamic "
                                "trip count is known to be low."));

static cl::opt<bool> UnrollAllowLoopNestsPeeling(
    "unroll-allow-loop-nests-peeling", cl::init(false), cl::Hidden,
    cl::desc("Allows loop nests to be peeled."));

static cl::opt<bool> UnrollUnrollRemainder(
  "unroll-remainder", cl::Hidden,
  cl::desc("Allow the loop remainder to be unrolled."));
@@ -215,6 +219,7 @@ TargetTransformInfo::UnrollingPreferences llvm::gatherUnrollingPreferences(
  UP.Force = false;
  UP.UpperBound = false;
  UP.AllowPeeling = true;
  UP.AllowLoopNestsPeeling = false;
  UP.UnrollAndJam = false;
  UP.PeelProfiledIterations = true;
  UP.UnrollAndJamInnerLoopThreshold = 60;
@@ -255,6 +260,8 @@ TargetTransformInfo::UnrollingPreferences llvm::gatherUnrollingPreferences(
    UP.UpperBound = false;
  if (UnrollAllowPeeling.getNumOccurrences() > 0)
    UP.AllowPeeling = UnrollAllowPeeling;
  if (UnrollAllowLoopNestsPeeling.getNumOccurrences() > 0)
    UP.AllowLoopNestsPeeling = UnrollAllowLoopNestsPeeling;
  if (UnrollUnrollRemainder.getNumOccurrences() > 0)
    UP.UnrollRemainder = UnrollUnrollRemainder;

+0 −24
Original line number Diff line number Diff line
@@ -903,30 +903,6 @@ bool LoopUnswitch::unswitchIfProfitable(Value *LoopCond, Constant *Val,
  return true;
}

/// Recursively clone the specified loop and all of its children,
/// mapping the blocks with the specified map.
static Loop *cloneLoop(Loop *L, Loop *PL, ValueToValueMapTy &VM, LoopInfo *LI,
                       LPPassManager *LPM) {
  Loop &New = *LI->AllocateLoop();
  if (PL)
    PL->addChildLoop(&New);
  else
    LI->addTopLevelLoop(&New);
  LPM->addLoop(New);

  // Add all of the blocks in L to the new loop.
  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
       I != E; ++I)
    if (LI->getLoopFor(*I) == L)
      New.addBasicBlockToLoop(cast<BasicBlock>(VM[*I]), *LI);

  // Add all of the subloops to the new loop.
  for (Loop *I : *L)
    cloneLoop(I, &New, VM, LI, LPM);

  return &New;
}

/// Emit a conditional branch on two values if LIC == Val, branch to TrueDst,
/// otherwise branch to FalseDest. Insert the code immediately before OldBranch
/// and remove (but not erase!) it from the function.
+14 −3
Original line number Diff line number Diff line
@@ -289,8 +289,10 @@ void llvm::computePeelCount(Loop *L, unsigned LoopSize,
  if (!canPeel(L))
    return;

  // Only try to peel innermost loops.
  if (!L->empty())
  // Only try to peel innermost loops by default.
  // The constraint can be relaxed by the target in TTI.getUnrollingPreferences
  // or by the flag -unroll-allow-loop-nests-peeling.
  if (!UP.AllowLoopNestsPeeling && !L->empty())
    return;

  // If the user provided a peel count, use that.
@@ -508,7 +510,10 @@ static void cloneLoopBlocks(
    BasicBlock *NewBB = CloneBasicBlock(*BB, VMap, ".peel", F);
    NewBlocks.push_back(NewBB);

    if (ParentLoop)
    // If an original block is an immediate child of the loop L, its copy
    // is a child of a ParentLoop after peeling. If a block is a child of
    // a nested loop, it is handled in the cloneLoop() call below.
    if (ParentLoop && LI->getLoopFor(*BB) == L)
      ParentLoop->addBasicBlockToLoop(NewBB, *LI);

    VMap[*BB] = NewBB;
@@ -525,6 +530,12 @@ static void cloneLoopBlocks(
    }
  }

  // Recursively create the new Loop objects for nested loops, if any,
  // to preserve LoopInfo.
  for (Loop *ChildLoop : *L) {
    cloneLoop(ChildLoop, ParentLoop, VMap, LI, nullptr);
  }

  // Hook-up the control flow for the newly inserted blocks.
  // The new header is hooked up directly to the "top", which is either
  // the original loop preheader (for the first iteration) or the previous
Loading