Skip to content

Commit b2e1fe6

Browse files
author
Marek Sedlacek
committed
Try reminder unrolling, when checks fail, rotate loop and retry
1 parent cfb1619 commit b2e1fe6

File tree

4 files changed

+63
-72
lines changed

4 files changed

+63
-72
lines changed

llvm/include/llvm/Transforms/Utils/UnrollLoop.h

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,6 @@ enum class LoopUnrollResult {
7272
FullyUnrolled
7373
};
7474

75-
/// Represents the result of a \c UnrollRuntimeLoopRemainder invocation.
76-
enum class LoopReminderUnrollResult {
77-
/// The loop reminder was not modified.
78-
Unmodified,
79-
80-
/// The loop was rotated, but not unrolled.
81-
Rotated,
82-
83-
/// The loop reminder was unrolled.
84-
Unrolled
85-
};
86-
8775
struct UnrollLoopOptions {
8876
unsigned Count;
8977
bool Force;
@@ -105,13 +93,13 @@ LLVM_ABI LoopUnrollResult UnrollLoop(Loop *L, UnrollLoopOptions ULO,
10593
Loop **RemainderLoop = nullptr,
10694
AAResults *AA = nullptr);
10795

108-
LLVM_ABI LoopReminderUnrollResult UnrollRuntimeLoopRemainder(
96+
LLVM_ABI bool UnrollRuntimeLoopRemainder(
10997
Loop *L, unsigned Count, bool AllowExpensiveTripCount,
11098
bool UseEpilogRemainder, bool UnrollRemainder, bool ForgetAllSCEV,
11199
LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC,
112100
const TargetTransformInfo *TTI, bool PreserveLCSSA,
113101
unsigned SCEVExpansionBudget, bool RuntimeUnrollMultiExit,
114-
bool AllowLoopRotation, Loop **ResultLoop = nullptr);
102+
Loop **ResultLoop = nullptr);
115103

116104
LLVM_ABI LoopUnrollResult UnrollAndJamLoop(
117105
Loop *L, unsigned Count, unsigned TripCount, unsigned TripMultiple,

llvm/lib/Transforms/Utils/LoopUnroll.cpp

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
5959
#include "llvm/Transforms/Utils/Cloning.h"
6060
#include "llvm/Transforms/Utils/Local.h"
61+
#include "llvm/Transforms/Utils/LoopRotationUtils.h"
6162
#include "llvm/Transforms/Utils/LoopSimplify.h"
6263
#include "llvm/Transforms/Utils/LoopUtils.h"
6364
#include "llvm/Transforms/Utils/SimplifyIndVar.h"
@@ -535,31 +536,60 @@ llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
535536
UnrollRuntimeEpilog.getNumOccurrences() ? UnrollRuntimeEpilog
536537
: isEpilogProfitable(L);
537538

538-
LoopReminderUnrollResult UnrollReminderResult =
539-
LoopReminderUnrollResult::Unmodified;
539+
bool LoopRotated = false;
540+
bool ReminderUnrolled = false;
540541
if (ULO.Runtime) {
541-
UnrollReminderResult = UnrollRuntimeLoopRemainder(
542+
// Call unroll with disabled rotation, to see if it is possible without it.
543+
ReminderUnrolled = UnrollRuntimeLoopRemainder(
542544
L, ULO.Count, ULO.AllowExpensiveTripCount, EpilogProfitability,
543545
ULO.UnrollRemainder, ULO.ForgetAllSCEV, LI, SE, DT, AC, TTI,
544546
PreserveLCSSA, ULO.SCEVExpansionBudget, ULO.RuntimeUnrollMultiExit,
545-
/*AllowLoopRotation*/ true, RemainderLoop);
547+
RemainderLoop);
548+
549+
// If unroll is not possible, then try with loop rotation.
550+
if (!ReminderUnrolled) {
551+
BasicBlock *OrigHeader = L->getHeader();
552+
BranchInst *BI = dyn_cast<BranchInst>(OrigHeader->getTerminator());
553+
if (BI && !BI->isUnconditional() &&
554+
isa<SCEVCouldNotCompute>(SE->getExitCount(L, L->getLoopLatch())) &&
555+
!isa<SCEVCouldNotCompute>(SE->getExitCount(L, OrigHeader))) {
556+
LLVM_DEBUG(
557+
dbgs() << " Rotating loop to make the exit count computable.\n");
558+
SimplifyQuery SQ{OrigHeader->getDataLayout()};
559+
SQ.TLI = nullptr;
560+
SQ.DT = DT;
561+
SQ.AC = AC;
562+
LoopRotated =
563+
llvm::LoopRotation(L, LI, TTI, AC, DT, SE,
564+
/*MemorySSAUpdater*/ nullptr, SQ,
565+
/*RotationOnly*/ false, /*Threshold*/ 16,
566+
/*IsUtilMode*/ false, /*PrepareForLTO*/ false,
567+
[](Loop *, ScalarEvolution *) { return true; });
568+
}
569+
if (LoopRotated) {
570+
// Loop was rotated, try unrolling.
571+
ReminderUnrolled = UnrollRuntimeLoopRemainder(
572+
L, ULO.Count, ULO.AllowExpensiveTripCount, EpilogProfitability,
573+
ULO.UnrollRemainder, ULO.ForgetAllSCEV, LI, SE, DT, AC, TTI,
574+
PreserveLCSSA, ULO.SCEVExpansionBudget, ULO.RuntimeUnrollMultiExit,
575+
RemainderLoop);
576+
}
577+
}
578+
// Latch block needs to be updated.
546579
LatchBlock = L->getLoopLatch();
547580
LatchIsExiting = L->isLoopExiting(LatchBlock);
548581
}
549582

550-
if (ULO.Runtime &&
551-
UnrollReminderResult != LoopReminderUnrollResult::Unrolled) {
583+
if (ULO.Runtime && !ReminderUnrolled) {
552584
if (ULO.Force)
553585
ULO.Runtime = false;
554586
else {
555587
LLVM_DEBUG(dbgs() << "Won't unroll; remainder loop could not be "
556588
"generated when assuming runtime trip count\n");
557589
// Loop might have been rotated inside of UnrollRuntimeLoopRemainder and
558590
// this needs to be propagated.
559-
return UnrollReminderResult == LoopReminderUnrollResult::Rotated
560-
? LoopUnrollResult::Modified
561-
: LoopUnrollResult::Unmodified;
562-
;
591+
return LoopRotated ? LoopUnrollResult::Modified
592+
: LoopUnrollResult::Unmodified;
563593
}
564594
}
565595

llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -237,18 +237,16 @@ llvm::UnrollAndJamLoop(Loop *L, unsigned Count, unsigned TripCount,
237237
// Are we eliminating the loop control altogether?
238238
bool CompletelyUnroll = (Count == TripCount);
239239

240+
// We use the runtime remainder in cases where we don't know trip multiple
240241
if (TripMultiple % Count != 0) {
241-
auto UnrollReminderResult = UnrollRuntimeLoopRemainder(
242-
L, Count, /*AllowExpensiveTripCount*/ false,
243-
/*UseEpilogRemainder*/ true, UnrollRemainder, /*ForgetAllSCEV*/ false,
244-
LI, SE, DT, AC, TTI, /*PreserveLCSSA*/ true, SCEVCheapExpansionBudget,
245-
/*AllowLoopRotation*/ false, EpilogueLoop);
246-
if (UnrollReminderResult != LoopReminderUnrollResult::Unrolled) {
242+
if (!UnrollRuntimeLoopRemainder(L, Count, /*AllowExpensiveTripCount*/ false,
243+
/*UseEpilogRemainder*/ true,
244+
UnrollRemainder, /*ForgetAllSCEV*/ false,
245+
LI, SE, DT, AC, TTI, true,
246+
SCEVCheapExpansionBudget, EpilogueLoop)) {
247247
LLVM_DEBUG(dbgs() << "Won't unroll-and-jam; remainder loop could not be "
248248
"generated when assuming runtime trip count\n");
249-
return UnrollReminderResult == LoopReminderUnrollResult::Rotated
250-
? LoopUnrollResult::Modified
251-
: LoopUnrollResult::Unmodified;
249+
return LoopUnrollResult::Unmodified;
252250
}
253251
}
254252

llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
3838
#include "llvm/Transforms/Utils/Cloning.h"
3939
#include "llvm/Transforms/Utils/Local.h"
40-
#include "llvm/Transforms/Utils/LoopRotationUtils.h"
4140
#include "llvm/Transforms/Utils/LoopUtils.h"
4241
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
4342
#include "llvm/Transforms/Utils/UnrollLoop.h"
@@ -575,46 +574,22 @@ static Value *CreateTripRemainder(IRBuilder<> &B, Value *BECount,
575574
/// if (extraiters != 0) jump Epil: // Omitted if unroll factor is 2.
576575
/// EpilExit:
577576

578-
LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
577+
bool llvm::UnrollRuntimeLoopRemainder(
579578
Loop *L, unsigned Count, bool AllowExpensiveTripCount,
580579
bool UseEpilogRemainder, bool UnrollRemainder, bool ForgetAllSCEV,
581580
LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC,
582581
const TargetTransformInfo *TTI, bool PreserveLCSSA,
583582
unsigned SCEVExpansionBudget, bool RuntimeUnrollMultiExit,
584-
bool AllowLoopRotation, Loop **ResultLoop) {
583+
Loop **ResultLoop) {
585584
LLVM_DEBUG(dbgs() << "Trying runtime unrolling on Loop: \n");
586585
LLVM_DEBUG(L->dump());
587586
LLVM_DEBUG(UseEpilogRemainder ? dbgs() << "Using epilog remainder.\n"
588587
: dbgs() << "Using prolog remainder.\n");
589588

590-
LoopReminderUnrollResult Result = LoopReminderUnrollResult::Unmodified;
591-
592-
// Rotate loop if it makes the exit count from the latch computable.
593-
if (AllowLoopRotation) {
594-
BasicBlock *OrigHeader = L->getHeader();
595-
BranchInst *BI = dyn_cast<BranchInst>(OrigHeader->getTerminator());
596-
if (BI && !BI->isUnconditional() &&
597-
isa<SCEVCouldNotCompute>(SE->getExitCount(L, L->getLoopLatch())) &&
598-
!isa<SCEVCouldNotCompute>(SE->getExitCount(L, OrigHeader))) {
599-
LLVM_DEBUG(
600-
dbgs() << " Rotating loop to make the exit count computable.\n");
601-
SimplifyQuery SQ{OrigHeader->getDataLayout()};
602-
SQ.TLI = nullptr;
603-
SQ.DT = DT;
604-
SQ.AC = AC;
605-
if (llvm::LoopRotation(L, LI, TTI, AC, DT, SE,
606-
/*MemorySSAUpdater*/ nullptr, SQ,
607-
/*RotationOnly*/ false, /*Threshold*/ 16,
608-
/*IsUtilMode*/ false, /*PrepareForLTO*/ false,
609-
[](Loop *, ScalarEvolution *) { return true; }))
610-
Result = LoopReminderUnrollResult::Rotated;
611-
}
612-
}
613-
614589
// Make sure the loop is in canonical form.
615590
if (!L->isLoopSimplifyForm()) {
616591
LLVM_DEBUG(dbgs() << "Not in simplify form!\n");
617-
return Result;
592+
return false;
618593
}
619594

620595
// Guaranteed by LoopSimplifyForm.
@@ -628,7 +603,7 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
628603
LLVM_DEBUG(
629604
dbgs()
630605
<< "Loop latch not terminated by a conditional branch.\n");
631-
return Result;
606+
return false;
632607
}
633608

634609
unsigned ExitIndex = LatchBR->getSuccessor(0) == Header ? 1 : 0;
@@ -640,7 +615,7 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
640615
LLVM_DEBUG(
641616
dbgs()
642617
<< "One of the loop latch successors must be the exit block.\n");
643-
return Result;
618+
return false;
644619
}
645620

646621
// These are exit blocks other than the target of the latch exiting block.
@@ -652,12 +627,12 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
652627
// We rely on LCSSA form being preserved when the exit blocks are transformed.
653628
// (Note that only an off-by-default mode of the old PM disables PreserveLCCA.)
654629
if (!PreserveLCSSA)
655-
return Result;
630+
return false;
656631

657632
// Priority goes to UnrollRuntimeMultiExit if it's supplied.
658633
if (UnrollRuntimeMultiExit.getNumOccurrences()) {
659634
if (!UnrollRuntimeMultiExit)
660-
return Result;
635+
return false;
661636
} else {
662637
// Otherwise perform multi-exit unrolling, if either the target indicates
663638
// it is profitable or the general profitability heuristics apply.
@@ -666,14 +641,14 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
666641
UseEpilogRemainder)) {
667642
LLVM_DEBUG(dbgs() << "Multiple exit/exiting blocks in loop and "
668643
"multi-exit unrolling not enabled!\n");
669-
return Result;
644+
return false;
670645
}
671646
}
672647
}
673648
// Use Scalar Evolution to compute the trip count. This allows more loops to
674649
// be unrolled than relying on induction var simplification.
675650
if (!SE)
676-
return Result;
651+
return false;
677652

678653
// Only unroll loops with a computable trip count.
679654
// We calculate the backedge count by using getExitCount on the Latch block,
@@ -683,7 +658,7 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
683658
const SCEV *BECountSC = SE->getExitCount(L, Latch);
684659
if (isa<SCEVCouldNotCompute>(BECountSC)) {
685660
LLVM_DEBUG(dbgs() << "Could not compute exit block SCEV\n");
686-
return Result;
661+
return false;
687662
}
688663

689664
unsigned BEWidth = cast<IntegerType>(BECountSC->getType())->getBitWidth();
@@ -694,7 +669,7 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
694669
SE->getAddExpr(BECountSC, SE->getConstant(BECountSC->getType(), 1));
695670
if (isa<SCEVCouldNotCompute>(TripCountSC)) {
696671
LLVM_DEBUG(dbgs() << "Could not compute trip count SCEV.\n");
697-
return Result;
672+
return false;
698673
}
699674

700675
BasicBlock *PreHeader = L->getLoopPreheader();
@@ -705,7 +680,7 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
705680
Expander.isHighCostExpansion(TripCountSC, L, SCEVExpansionBudget, TTI,
706681
PreHeaderBR)) {
707682
LLVM_DEBUG(dbgs() << "High cost for expanding trip count scev!\n");
708-
return Result;
683+
return false;
709684
}
710685

711686
// This constraint lets us deal with an overflowing trip count easily; see the
@@ -714,7 +689,7 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
714689
LLVM_DEBUG(
715690
dbgs()
716691
<< "Count failed constraint on overflow trip count calculation.\n");
717-
return Result;
692+
return false;
718693
}
719694

720695
// Loop structure is the following:
@@ -1060,5 +1035,5 @@ LoopReminderUnrollResult llvm::UnrollRuntimeLoopRemainder(
10601035
if (ResultLoop && UnrollResult != LoopUnrollResult::FullyUnrolled)
10611036
*ResultLoop = remainderLoop;
10621037
NumRuntimeUnrolled++;
1063-
return LoopReminderUnrollResult::Unrolled;
1038+
return true;
10641039
}

0 commit comments

Comments
 (0)