llvm.org GIT mirror llvm / 1a57475
[LoopInfo] Fix getUniqueNonLatchExitBlocks It is possible that exit block has two predecessors and one of them is a latch block while another is not. Current algorithm is based on the assumption that all exits are dedicated and therefore we can check only first predecessor of loop exit to find all unique exits. However if we do not consider latch block and it is first predecessor of some exit then this exit will be found. Regression test is added. As a side effect of algorithm re-writing, the restriction that all exits are dedicated is eliminated. Reviewers: reames, fhahn, efriedma Reviewed By: efriedma Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D64787 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366294 91177308-0d34-0410-b5e6-96231b3b80d8 Serguei Katkov a month ago
3 changed file(s) with 50 addition(s) and 44 deletion(s). Raw diff Collapse all Expand all
269269
270270 /// Return all unique successor blocks of this loop.
271271 /// These are the blocks _outside of the current loop_ which are branched to.
272 /// This assumes that loop exits are in canonical form, i.e. all exits are
273 /// dedicated exits.
274272 void getUniqueExitBlocks(SmallVectorImpl &ExitBlocks) const;
275273
276274 /// Return all unique successor blocks of this loop except successors from
277275 /// Latch block are not considered. If the exit comes from Latch has also
278276 /// non Latch predecessor in a loop it will be added to ExitBlocks.
279277 /// 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.
282278 void getUniqueNonLatchExitBlocks(SmallVectorImpl &ExitBlocks) const;
283279
284280 /// If getUniqueExitBlocks would return exactly one block, return that block.
100100 void getUniqueExitBlocksHelper(const LoopT *L,
101101 SmallVectorImpl &ExitBlocks,
102102 PredicateT Pred) {
103 typedef GraphTraits BlockTraits;
104 typedef GraphTraits> InvBlockTraits;
105
106 assert(L->hasDedicatedExits() &&
107 "getUniqueExitBlocks assumes the loop has canonical form exits!");
108
109 SmallVector SwitchExitBlocks;
103 assert(!L->isInvalid() && "Loop not in a valid state!");
104 SmallPtrSet Visited;
110105 auto Filtered = make_filter_range(L->blocks(), Pred);
111 for (BlockT *Block : Filtered) {
112 SwitchExitBlocks.clear();
113 for (BlockT *Successor : children(Block)) {
114 // If block is inside the loop then it is not an exit block.
115 if (L->contains(Successor))
116 continue;
117
118 BlockT *FirstPred = *InvBlockTraits::child_begin(Successor);
119
120 // If current basic block is this exit block's first predecessor then only
121 // insert exit block in to the output ExitBlocks vector. This ensures that
122 // same exit block is not inserted twice into ExitBlocks vector.
123 if (Block != FirstPred)
124 continue;
125
126 // If a terminator has more then two successors, for example SwitchInst,
127 // then it is possible that there are multiple edges from current block to
128 // one exit block.
129 if (std::distance(BlockTraits::child_begin(Block),
130 BlockTraits::child_end(Block)) <= 2) {
131 ExitBlocks.push_back(Successor);
132 continue;
133 }
134
135 // In case of multiple edges from current block to exit block, collect
136 // only one edge in ExitBlocks. Use switchExitBlocks to keep track of
137 // duplicate edges.
138 if (!is_contained(SwitchExitBlocks, Successor)) {
139 SwitchExitBlocks.push_back(Successor);
140 ExitBlocks.push_back(Successor);
141 }
142 }
143 }
106 for (BlockT *BB : Filtered)
107 for (BlockT *Successor : children(BB))
108 if (!L->contains(Successor))
109 if (Visited.insert(Successor).second)
110 ExitBlocks.push_back(Successor);
144111 }
145112
146113 template
11551155 EXPECT_TRUE(Exits.size() == 1);
11561156 });
11571157 }
1158
1159 // Regression test for getUniqueNonLatchExitBlocks functions.
1160 // It should detect the exit if it comes from both latch and non-latch blocks.
1161 TEST(LoopInfoTest, LoopNonLatchUniqueExitBlocks) {
1162 const char *ModuleStr =
1163 "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
1164 "define void @foo(i32 %n, i1 %cond) {\n"
1165 "entry:\n"
1166 " br label %for.cond\n"
1167 "for.cond:\n"
1168 " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n"
1169 " %cmp = icmp slt i32 %i.0, %n\n"
1170 " br i1 %cond, label %for.inc, label %for.end\n"
1171 "for.inc:\n"
1172 " %inc = add nsw i32 %i.0, 1\n"
1173 " br i1 %cmp, label %for.cond, label %for.end, !llvm.loop !0\n"
1174 "for.end:\n"
1175 " ret void\n"
1176 "}\n"
1177 "!0 = distinct !{!0, !1}\n"
1178 "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n";
1179
1180 // Parse the module.
1181 LLVMContext Context;
1182 std::unique_ptr M = makeLLVMModule(Context, ModuleStr);
1183
1184 runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) {
1185 Function::iterator FI = F.begin();
1186 // First basic block is entry - skip it.
1187 BasicBlock *Header = &*(++FI);
1188 assert(Header->getName() == "for.cond");
1189 Loop *L = LI.getLoopFor(Header);
1190
1191 SmallVector Exits;
1192 // This loop has 1 unique exit.
1193 L->getUniqueExitBlocks(Exits);
1194 EXPECT_TRUE(Exits.size() == 1);
1195 // And one unique non latch exit.
1196 Exits.clear();
1197 L->getUniqueNonLatchExitBlocks(Exits);
1198 EXPECT_TRUE(Exits.size() == 1);
1199 });
1200 }