llvm.org GIT mirror llvm / fbbb613
[LoopInfo] Introduce getUniqueNonLatchExitBlocks utility function Extract the code from LoopUnrollRuntime into utility function to re-use it in D63923. Reviewers: reames, mkuper Reviewed By: reames Subscribers: fhahn, hiraditya, zzheng, dmgreen, llvm-commits Differential Revision: https://reviews.llvm.org/D64548 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366040 91177308-0d34-0410-b5e6-96231b3b80d8 Serguei Katkov a month ago
4 changed file(s) with 87 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
272272 /// This assumes that loop exits are in canonical form, i.e. all exits are
273273 /// dedicated exits.
274274 void getUniqueExitBlocks(SmallVectorImpl &ExitBlocks) const;
275
276 /// Return all unique successor blocks of this loop except successors from
277 /// Latch block are not considered. If the exit comes from Latch has also
278 /// non Latch predecessor in a loop it will be added to ExitBlocks.
279 /// These are the blocks _outside of the current loop_ which are branched to.
280 /// This assumes that loop exits are in canonical form, i.e. all exits are
281 /// dedicated exits.
282 void getUniqueNonLatchExitBlocks(SmallVectorImpl &ExitBlocks) const;
275283
276284 /// If getUniqueExitBlocks would return exactly one block, return that block.
277285 /// Otherwise return null.
9494 return true;
9595 }
9696
97 template
98 void LoopBase::getUniqueExitBlocks(
99 SmallVectorImpl &ExitBlocks) const {
97 // Helper function to get unique loop exits. Pred is a predicate pointing to
98 // BasicBlocks in a loop which should be considered to find loop exits.
99 template
100 void getUniqueExitBlocksHelper(const LoopT *L,
101 SmallVectorImpl &ExitBlocks,
102 PredicateT Pred) {
100103 typedef GraphTraits BlockTraits;
101104 typedef GraphTraits> InvBlockTraits;
102105
103 assert(hasDedicatedExits() &&
106 assert(L->hasDedicatedExits() &&
104107 "getUniqueExitBlocks assumes the loop has canonical form exits!");
105108
106109 SmallVector SwitchExitBlocks;
107 for (BlockT *Block : this->blocks()) {
110 auto Filtered = make_filter_range(L->blocks(), Pred);
111 for (BlockT *Block : Filtered) {
108112 SwitchExitBlocks.clear();
109113 for (BlockT *Successor : children(Block)) {
110114 // If block is inside the loop then it is not an exit block.
111 if (contains(Successor))
115 if (L->contains(Successor))
112116 continue;
113117
114118 BlockT *FirstPred = *InvBlockTraits::child_begin(Successor);
137141 }
138142 }
139143 }
144 }
145
146 template
147 void LoopBase::getUniqueExitBlocks(
148 SmallVectorImpl &ExitBlocks) const {
149 getUniqueExitBlocksHelper(this, ExitBlocks,
150 [](const BlockT *BB) { return true; });
151 }
152
153 template
154 void LoopBase::getUniqueNonLatchExitBlocks(
155 SmallVectorImpl &ExitBlocks) const {
156 const BlockT *Latch = getLoopLatch();
157 assert(Latch && "Latch block must exists");
158 getUniqueExitBlocksHelper(this, ExitBlocks,
159 [Latch](const BlockT *BB) { return BB != Latch; });
140160 }
141161
142162 template
423423
424424 /// Returns true if we can safely unroll a multi-exit/exiting loop. OtherExits
425425 /// is populated with all the loop exit blocks other than the LatchExit block.
426 static bool
427 canSafelyUnrollMultiExitLoop(Loop *L, SmallVectorImpl &OtherExits,
428 BasicBlock *LatchExit, bool PreserveLCSSA,
429 bool UseEpilogRemainder) {
426 static bool canSafelyUnrollMultiExitLoop(Loop *L, BasicBlock *LatchExit,
427 bool PreserveLCSSA,
428 bool UseEpilogRemainder) {
430429
431430 // We currently have some correctness constrains in unrolling a multi-exit
432431 // loop. Check for these below.
434433 // We rely on LCSSA form being preserved when the exit blocks are transformed.
435434 if (!PreserveLCSSA)
436435 return false;
437 SmallVector Exits;
438 L->getUniqueExitBlocks(Exits);
439 for (auto *BB : Exits)
440 if (BB != LatchExit)
441 OtherExits.push_back(BB);
442436
443437 // TODO: Support multiple exiting blocks jumping to the `LatchExit` when
444438 // UnrollRuntimeMultiExit is true. This will need updating the logic in
468462 bool PreserveLCSSA, bool UseEpilogRemainder) {
469463
470464 #if !defined(NDEBUG)
471 SmallVector OtherExitsDummyCheck;
472 assert(canSafelyUnrollMultiExitLoop(L, OtherExitsDummyCheck, LatchExit,
473 PreserveLCSSA, UseEpilogRemainder) &&
465 assert(canSafelyUnrollMultiExitLoop(L, LatchExit, PreserveLCSSA,
466 UseEpilogRemainder) &&
474467 "Should be safe to unroll before checking profitability!");
475468 #endif
476469
594587
595588 // These are exit blocks other than the target of the latch exiting block.
596589 SmallVector OtherExits;
590 L->getUniqueNonLatchExitBlocks(OtherExits);
597591 bool isMultiExitUnrollingEnabled =
598 canSafelyUnrollMultiExitLoop(L, OtherExits, LatchExit, PreserveLCSSA,
592 canSafelyUnrollMultiExitLoop(L, LatchExit, PreserveLCSSA,
599593 UseEpilogRemainder) &&
600594 canProfitablyUnrollMultiExitLoop(L, OtherExits, LatchExit, PreserveLCSSA,
601595 UseEpilogRemainder);
11091109 L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE));
11101110 });
11111111 }
1112
1113 // Examine getUniqueExitBlocks/getUniqueNonLatchExitBlocks functions.
1114 TEST(LoopInfoTest, LoopUniqueExitBlocks) {
1115 const char *ModuleStr =
1116 "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
1117 "define void @foo(i32 %n, i1 %cond) {\n"
1118 "entry:\n"
1119 " br label %for.cond\n"
1120 "for.cond:\n"
1121 " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n"
1122 " %cmp = icmp slt i32 %i.0, %n\n"
1123 " br i1 %cond, label %for.inc, label %for.end1\n"
1124 "for.inc:\n"
1125 " %inc = add nsw i32 %i.0, 1\n"
1126 " br i1 %cmp, label %for.cond, label %for.end2, !llvm.loop !0\n"
1127 "for.end1:\n"
1128 " br label %for.end\n"
1129 "for.end2:\n"
1130 " br label %for.end\n"
1131 "for.end:\n"
1132 " ret void\n"
1133 "}\n"
1134 "!0 = distinct !{!0, !1}\n"
1135 "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n";
1136
1137 // Parse the module.
1138 LLVMContext Context;
1139 std::unique_ptr M = makeLLVMModule(Context, ModuleStr);
1140
1141 runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) {
1142 Function::iterator FI = F.begin();
1143 // First basic block is entry - skip it.
1144 BasicBlock *Header = &*(++FI);
1145 assert(Header->getName() == "for.cond");
1146 Loop *L = LI.getLoopFor(Header);
1147
1148 SmallVector Exits;
1149 // This loop has 2 unique exits.
1150 L->getUniqueExitBlocks(Exits);
1151 EXPECT_TRUE(Exits.size() == 2);
1152 // And one unique non latch exit.
1153 Exits.clear();
1154 L->getUniqueNonLatchExitBlocks(Exits);
1155 EXPECT_TRUE(Exits.size() == 1);
1156 });
1157 }