1 //===- BasicBlockUtils.cpp - Unit tests for BasicBlockUtils ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
10 #include "llvm/Analysis/AssumptionCache.h"
11 #include "llvm/Analysis/BasicAliasAnalysis.h"
12 #include "llvm/Analysis/BlockFrequencyInfo.h"
13 #include "llvm/Analysis/BranchProbabilityInfo.h"
14 #include "llvm/Analysis/CFG.h"
15 #include "llvm/Analysis/DomTreeUpdater.h"
16 #include "llvm/Analysis/LoopInfo.h"
17 #include "llvm/Analysis/MemorySSA.h"
18 #include "llvm/Analysis/MemorySSAUpdater.h"
19 #include "llvm/Analysis/PostDominators.h"
20 #include "llvm/Analysis/TargetLibraryInfo.h"
21 #include "llvm/AsmParser/Parser.h"
22 #include "llvm/IR/BasicBlock.h"
23 #include "llvm/IR/Dominators.h"
24 #include "llvm/IR/LLVMContext.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/Support/SourceMgr.h"
27 #include "gtest/gtest.h"
28
29 using namespace llvm;
30
parseIR(LLVMContext & C,const char * IR)31 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
32 SMDiagnostic Err;
33 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
34 if (!Mod)
35 Err.print("BasicBlockUtilsTests", errs());
36 return Mod;
37 }
38
getBasicBlockByName(Function & F,StringRef Name)39 static BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
40 for (BasicBlock &BB : F)
41 if (BB.getName() == Name)
42 return &BB;
43 llvm_unreachable("Expected to find basic block!");
44 }
45
TEST(BasicBlockUtils,EliminateUnreachableBlocks)46 TEST(BasicBlockUtils, EliminateUnreachableBlocks) {
47 LLVMContext C;
48 std::unique_ptr<Module> M = parseIR(C, R"IR(
49 define i32 @has_unreachable(i1 %cond) {
50 entry:
51 br i1 %cond, label %bb0, label %bb1
52 bb0:
53 br label %bb1
54 bb1:
55 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]
56 ret i32 %phi
57 bb2:
58 ret i32 42
59 }
60 )IR");
61 Function *F = M->getFunction("has_unreachable");
62 DominatorTree DT(*F);
63 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
64
65 EXPECT_EQ(F->size(), (size_t)4);
66 bool Result = EliminateUnreachableBlocks(*F, &DTU);
67 EXPECT_TRUE(Result);
68 EXPECT_EQ(F->size(), (size_t)3);
69 EXPECT_TRUE(DT.verify());
70 }
71
TEST(BasicBlockUtils,SplitEdge_ex1)72 TEST(BasicBlockUtils, SplitEdge_ex1) {
73 LLVMContext C;
74 std::unique_ptr<Module> M = parseIR(C, R"IR(
75 define void @foo(i1 %cond0) {
76 entry:
77 br i1 %cond0, label %bb0, label %bb1
78 bb0:
79 %0 = mul i32 1, 2
80 br label %bb1
81 bb1:
82 br label %bb2
83 bb2:
84 ret void
85 }
86 )IR");
87 Function *F = M->getFunction("foo");
88 DominatorTree DT(*F);
89 BasicBlock *SrcBlock;
90 BasicBlock *DestBlock;
91 BasicBlock *NewBB;
92
93 SrcBlock = getBasicBlockByName(*F, "entry");
94 DestBlock = getBasicBlockByName(*F, "bb0");
95 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr);
96
97 EXPECT_TRUE(DT.verify());
98 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);
99 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);
100 EXPECT_EQ(NewBB->getParent(), F);
101
102 bool BBFlag = false;
103 for (BasicBlock &BB : *F) {
104 if (BB.getName() == NewBB->getName()) {
105 BBFlag = true;
106 }
107 }
108 EXPECT_TRUE(BBFlag);
109 }
110
TEST(BasicBlockUtils,SplitEdge_ex2)111 TEST(BasicBlockUtils, SplitEdge_ex2) {
112 LLVMContext C;
113 std::unique_ptr<Module> M = parseIR(C, R"IR(
114 define void @foo() {
115 bb0:
116 br label %bb2
117 bb1:
118 br label %bb2
119 bb2:
120 ret void
121 }
122 )IR");
123 Function *F = M->getFunction("foo");
124 DominatorTree DT(*F);
125
126 BasicBlock *SrcBlock;
127 BasicBlock *DestBlock;
128 BasicBlock *NewBB;
129
130 SrcBlock = getBasicBlockByName(*F, "bb0");
131 DestBlock = getBasicBlockByName(*F, "bb2");
132 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr);
133
134 EXPECT_TRUE(DT.verify());
135 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);
136 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);
137 EXPECT_EQ(NewBB->getParent(), F);
138
139 bool BBFlag = false;
140 for (BasicBlock &BB : *F) {
141 if (BB.getName() == NewBB->getName()) {
142 BBFlag = true;
143 }
144 }
145 EXPECT_TRUE(BBFlag);
146 }
147
TEST(BasicBlockUtils,SplitEdge_ex3)148 TEST(BasicBlockUtils, SplitEdge_ex3) {
149 LLVMContext C;
150 std::unique_ptr<Module> M = parseIR(C, R"IR(
151 define i32 @foo(i32 %n) {
152 entry:
153 br label %header
154 header:
155 %sum.02 = phi i32 [ 0, %entry ], [ %sum.1, %bb3 ]
156 %0 = phi i32 [ 0, %entry ], [ %4, %bb3 ]
157 %1 = icmp slt i32 %0, %n
158 br i1 %1, label %bb0, label %bb1
159 bb0:
160 %2 = add nsw i32 %sum.02, 2
161 br label %bb2
162 bb1:
163 %3 = add nsw i32 %sum.02, 1
164 br label %bb2
165 bb2:
166 %sum.1 = phi i32 [ %2, %bb0 ], [ %3, %bb1 ]
167 br label %bb3
168 bb3:
169 %4 = add nsw i32 %0, 1
170 %5 = icmp slt i32 %4, 100
171 br i1 %5, label %header, label %bb4
172 bb4:
173 %sum.0.lcssa = phi i32 [ %sum.1, %bb3 ]
174 ret i32 %sum.0.lcssa
175 }
176 )IR");
177 Function *F = M->getFunction("foo");
178 DominatorTree DT(*F);
179
180 LoopInfo LI(DT);
181
182 DataLayout DL("e-i64:64-f80:128-n8:16:32:64-S128");
183 TargetLibraryInfoImpl TLII;
184 TargetLibraryInfo TLI(TLII);
185 AssumptionCache AC(*F);
186 AAResults AA(TLI);
187
188 BasicAAResult BAA(DL, *F, TLI, AC, &DT);
189 AA.addAAResult(BAA);
190
191 MemorySSA MSSA(*F, &AA, &DT);
192 MemorySSAUpdater Updater(&MSSA);
193
194 BasicBlock *SrcBlock;
195 BasicBlock *DestBlock;
196 BasicBlock *NewBB;
197
198 SrcBlock = getBasicBlockByName(*F, "header");
199 DestBlock = getBasicBlockByName(*F, "bb0");
200 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &Updater);
201
202 Updater.getMemorySSA()->verifyMemorySSA();
203 EXPECT_TRUE(DT.verify());
204 EXPECT_NE(LI.getLoopFor(SrcBlock), nullptr);
205 EXPECT_NE(LI.getLoopFor(DestBlock), nullptr);
206 EXPECT_NE(LI.getLoopFor(NewBB), nullptr);
207 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);
208 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);
209 EXPECT_EQ(NewBB->getParent(), F);
210
211 bool BBFlag = false;
212 for (BasicBlock &BB : *F) {
213 if (BB.getName() == NewBB->getName()) {
214 BBFlag = true;
215 }
216 }
217 EXPECT_TRUE(BBFlag);
218 }
219
TEST(BasicBlockUtils,SplitEdge_ex4)220 TEST(BasicBlockUtils, SplitEdge_ex4) {
221 LLVMContext C;
222 std::unique_ptr<Module> M = parseIR(C, R"IR(
223 define void @bar(i32 %cond) personality i8 0 {
224 entry:
225 switch i32 %cond, label %exit [
226 i32 -1, label %continue
227 i32 0, label %continue
228 i32 1, label %continue_alt
229 i32 2, label %continue_alt
230 ]
231 exit:
232 ret void
233 continue:
234 invoke void @sink() to label %normal unwind label %exception
235 continue_alt:
236 invoke void @sink_alt() to label %normal unwind label %exception
237 exception:
238 %cleanup = landingpad i8 cleanup
239 br label %trivial-eh-handler
240 trivial-eh-handler:
241 call void @sideeffect(i32 1)
242 br label %normal
243 normal:
244 call void @sideeffect(i32 0)
245 ret void
246 }
247
248 declare void @sideeffect(i32)
249 declare void @sink() cold
250 declare void @sink_alt() cold
251 )IR");
252 Function *F = M->getFunction("bar");
253
254 DominatorTree DT(*F);
255
256 LoopInfo LI(DT);
257
258 TargetLibraryInfoImpl TLII;
259 TargetLibraryInfo TLI(TLII);
260
261 AAResults AA(TLI);
262
263 MemorySSA MSSA(*F, &AA, &DT);
264 MemorySSAUpdater MSSAU(&MSSA);
265
266 BasicBlock *SrcBlock;
267 BasicBlock *DestBlock;
268
269 SrcBlock = getBasicBlockByName(*F, "continue");
270 DestBlock = getBasicBlockByName(*F, "exception");
271
272 unsigned SuccNum = GetSuccessorNumber(SrcBlock, DestBlock);
273 Instruction *LatchTerm = SrcBlock->getTerminator();
274
275 const CriticalEdgeSplittingOptions Options =
276 CriticalEdgeSplittingOptions(&DT, &LI, &MSSAU);
277
278 // Check that the following edge is both critical and the destination block is
279 // an exception block. These must be handled differently by SplitEdge
280 bool CriticalEdge =
281 isCriticalEdge(LatchTerm, SuccNum, Options.MergeIdenticalEdges);
282 EXPECT_TRUE(CriticalEdge);
283
284 bool Ehpad = DestBlock->isEHPad();
285 EXPECT_TRUE(Ehpad);
286
287 BasicBlock *NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &MSSAU, "");
288
289 MSSA.verifyMemorySSA();
290 EXPECT_TRUE(DT.verify());
291 EXPECT_NE(NewBB, nullptr);
292 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);
293 EXPECT_EQ(NewBB, SrcBlock->getTerminator()->getSuccessor(SuccNum));
294 EXPECT_EQ(NewBB->getParent(), F);
295
296 bool BBFlag = false;
297 for (BasicBlock &BB : *F) {
298 if (BB.getName() == NewBB->getName()) {
299 BBFlag = true;
300 break;
301 }
302 }
303 EXPECT_TRUE(BBFlag);
304 }
305
TEST(BasicBlockUtils,splitBasicBlockBefore_ex1)306 TEST(BasicBlockUtils, splitBasicBlockBefore_ex1) {
307 LLVMContext C;
308 std::unique_ptr<Module> M = parseIR(C, R"IR(
309 define void @foo() {
310 bb0:
311 %0 = mul i32 1, 2
312 br label %bb2
313 bb1:
314 br label %bb3
315 bb2:
316 %1 = phi i32 [ %0, %bb0 ]
317 br label %bb3
318 bb3:
319 ret void
320 }
321 )IR");
322 Function *F = M->getFunction("foo");
323 DominatorTree DT(*F);
324
325 BasicBlock *DestBlock;
326 BasicBlock *NewBB;
327
328 DestBlock = getBasicBlockByName(*F, "bb2");
329
330 NewBB = DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(),
331 "test");
332
333 PHINode *PN = dyn_cast<PHINode>(&(DestBlock->front()));
334 EXPECT_EQ(PN->getIncomingBlock(0), NewBB);
335 EXPECT_EQ(NewBB->getName(), "test");
336 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);
337 EXPECT_EQ(DestBlock->getSinglePredecessor(), NewBB);
338 }
339
340 #ifndef NDEBUG
TEST(BasicBlockUtils,splitBasicBlockBefore_ex2)341 TEST(BasicBlockUtils, splitBasicBlockBefore_ex2) {
342 LLVMContext C;
343 std::unique_ptr<Module> M = parseIR(C, R"IR(
344 define void @foo() {
345 bb0:
346 %0 = mul i32 1, 2
347 br label %bb2
348 bb1:
349 br label %bb2
350 bb2:
351 %1 = phi i32 [ %0, %bb0 ], [ 1, %bb1 ]
352 br label %bb3
353 bb3:
354 ret void
355 }
356 )IR");
357 Function *F = M->getFunction("foo");
358 DominatorTree DT(*F);
359
360 BasicBlock *DestBlock = getBasicBlockByName(*F, "bb2");
361
362 ASSERT_DEATH(
363 {
364 DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(),
365 "test");
366 },
367 "cannot split on multi incoming phis");
368 }
369 #endif
370
TEST(BasicBlockUtils,NoUnreachableBlocksToEliminate)371 TEST(BasicBlockUtils, NoUnreachableBlocksToEliminate) {
372 LLVMContext C;
373 std::unique_ptr<Module> M = parseIR(C, R"IR(
374 define i32 @no_unreachable(i1 %cond) {
375 entry:
376 br i1 %cond, label %bb0, label %bb1
377 bb0:
378 br label %bb1
379 bb1:
380 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]
381 ret i32 %phi
382 }
383 )IR");
384 Function *F = M->getFunction("no_unreachable");
385 DominatorTree DT(*F);
386 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
387
388 EXPECT_EQ(F->size(), (size_t)3);
389 bool Result = EliminateUnreachableBlocks(*F, &DTU);
390 EXPECT_FALSE(Result);
391 EXPECT_EQ(F->size(), (size_t)3);
392 EXPECT_TRUE(DT.verify());
393 }
394
TEST(BasicBlockUtils,SplitBlockPredecessors)395 TEST(BasicBlockUtils, SplitBlockPredecessors) {
396 LLVMContext C;
397 std::unique_ptr<Module> M = parseIR(C, R"IR(
398 define i32 @basic_func(i1 %cond) {
399 entry:
400 br i1 %cond, label %bb0, label %bb1
401 bb0:
402 br label %bb1
403 bb1:
404 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]
405 ret i32 %phi
406 }
407 )IR");
408 Function *F = M->getFunction("basic_func");
409 DominatorTree DT(*F);
410
411 // Make sure the dominator tree is properly updated if calling this on the
412 // entry block.
413 SplitBlockPredecessors(&F->getEntryBlock(), {}, "split.entry", &DT);
414 EXPECT_TRUE(DT.verify());
415 }
416
TEST(BasicBlockUtils,SplitCriticalEdge)417 TEST(BasicBlockUtils, SplitCriticalEdge) {
418 LLVMContext C;
419 std::unique_ptr<Module> M = parseIR(C, R"IR(
420 define void @crit_edge(i1 %cond0, i1 %cond1) {
421 entry:
422 br i1 %cond0, label %bb0, label %bb1
423 bb0:
424 br label %bb1
425 bb1:
426 br label %bb2
427 bb2:
428 ret void
429 }
430 )IR");
431 Function *F = M->getFunction("crit_edge");
432 DominatorTree DT(*F);
433 PostDominatorTree PDT(*F);
434
435 CriticalEdgeSplittingOptions CESO(&DT, nullptr, nullptr, &PDT);
436 EXPECT_EQ(1u, SplitAllCriticalEdges(*F, CESO));
437 EXPECT_TRUE(DT.verify());
438 EXPECT_TRUE(PDT.verify());
439 }
440
TEST(BasicBlockUtils,SplitIndirectBrCriticalEdgesIgnorePHIs)441 TEST(BasicBlockUtils, SplitIndirectBrCriticalEdgesIgnorePHIs) {
442 LLVMContext C;
443 std::unique_ptr<Module> M = parseIR(C, R"IR(
444 define void @crit_edge(i8* %tgt, i1 %cond0, i1 %cond1) {
445 entry:
446 indirectbr i8* %tgt, [label %bb0, label %bb1, label %bb2]
447 bb0:
448 br i1 %cond0, label %bb1, label %bb2
449 bb1:
450 %p = phi i32 [0, %bb0], [0, %entry]
451 br i1 %cond1, label %bb3, label %bb4
452 bb2:
453 ret void
454 bb3:
455 ret void
456 bb4:
457 ret void
458 }
459 )IR");
460 Function *F = M->getFunction("crit_edge");
461 DominatorTree DT(*F);
462 LoopInfo LI(DT);
463 BranchProbabilityInfo BPI(*F, LI);
464 BlockFrequencyInfo BFI(*F, BPI, LI);
465
466 ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/true,
467 &BPI, &BFI));
468
469 // Check that successors of the split block get their probability correct.
470 BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");
471 BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);
472 ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());
473 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));
474 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));
475
476 // bb2 has no PHI, so we shouldn't split bb0 -> bb2
477 BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
478 ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());
479 EXPECT_EQ(BB0->getTerminator()->getSuccessor(1),
480 getBasicBlockByName(*F, "bb2"));
481 }
482
TEST(BasicBlockUtils,SplitIndirectBrCriticalEdges)483 TEST(BasicBlockUtils, SplitIndirectBrCriticalEdges) {
484 LLVMContext C;
485 std::unique_ptr<Module> M = parseIR(C, R"IR(
486 define void @crit_edge(i8* %tgt, i1 %cond0, i1 %cond1) {
487 entry:
488 indirectbr i8* %tgt, [label %bb0, label %bb1, label %bb2]
489 bb0:
490 br i1 %cond0, label %bb1, label %bb2
491 bb1:
492 %p = phi i32 [0, %bb0], [0, %entry]
493 br i1 %cond1, label %bb3, label %bb4
494 bb2:
495 ret void
496 bb3:
497 ret void
498 bb4:
499 ret void
500 }
501 )IR");
502 Function *F = M->getFunction("crit_edge");
503 DominatorTree DT(*F);
504 LoopInfo LI(DT);
505 BranchProbabilityInfo BPI(*F, LI);
506 BlockFrequencyInfo BFI(*F, BPI, LI);
507
508 ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/false,
509 &BPI, &BFI));
510
511 // Check that successors of the split block get their probability correct.
512 BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");
513 BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);
514 ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());
515 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));
516 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));
517
518 // Should split, resulting in:
519 // bb0 -> bb2.clone; bb2 -> split1; bb2.clone -> split,
520 BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
521 ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());
522 BasicBlock *BB2Clone = BB0->getTerminator()->getSuccessor(1);
523 BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");
524 EXPECT_NE(BB2Clone, BB2);
525 ASSERT_EQ(1u, BB2->getTerminator()->getNumSuccessors());
526 ASSERT_EQ(1u, BB2Clone->getTerminator()->getNumSuccessors());
527 EXPECT_EQ(BB2->getTerminator()->getSuccessor(0),
528 BB2Clone->getTerminator()->getSuccessor(0));
529 }
530
TEST(BasicBlockUtils,SetEdgeProbability)531 TEST(BasicBlockUtils, SetEdgeProbability) {
532 LLVMContext C;
533 std::unique_ptr<Module> M = parseIR(C, R"IR(
534 define void @edge_probability(i32 %0) {
535 entry:
536 switch i32 %0, label %LD [
537 i32 700, label %L0
538 i32 701, label %L1
539 i32 702, label %L2
540 i32 703, label %L3
541 i32 704, label %L4
542 i32 705, label %L5
543 i32 706, label %L6
544 i32 707, label %L7
545 i32 708, label %L8
546 i32 709, label %L9
547 i32 710, label %L10
548 i32 711, label %L11
549 i32 712, label %L12
550 i32 713, label %L13
551 i32 714, label %L14
552 i32 715, label %L15
553 i32 716, label %L16
554 i32 717, label %L17
555 i32 718, label %L18
556 i32 719, label %L19
557 ], !prof !{!"branch_weights", i32 1, i32 1, i32 1, i32 1, i32 1, i32 451, i32 1,
558 i32 12, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1,
559 i32 1, i32 1, i32 1, i32 1, i32 1}
560 LD:
561 unreachable
562 L0:
563 ret void
564 L1:
565 ret void
566 L2:
567 ret void
568 L3:
569 ret void
570 L4:
571 ret void
572 L5:
573 ret void
574 L6:
575 ret void
576 L7:
577 ret void
578 L8:
579 ret void
580 L9:
581 ret void
582 L10:
583 ret void
584 L11:
585 ret void
586 L12:
587 ret void
588 L13:
589 ret void
590 L14:
591 ret void
592 L15:
593 ret void
594 L16:
595 ret void
596 L17:
597 ret void
598 L18:
599 ret void
600 L19:
601 ret void
602 }
603 )IR");
604 Function *F = M->getFunction("edge_probability");
605 DominatorTree DT(*F);
606 LoopInfo LI(DT);
607 BranchProbabilityInfo BPI(*F, LI);
608
609 // Check that the unreachable block has the minimal probability.
610 const BasicBlock *EntryBB = getBasicBlockByName(*F, "entry");
611 const BasicBlock *UnreachableBB = getBasicBlockByName(*F, "LD");
612 EXPECT_EQ(BranchProbability::getRaw(1),
613 BPI.getEdgeProbability(EntryBB, UnreachableBB));
614 }
615
TEST(BasicBlockUtils,IsPresplitCoroSuspendExitTest)616 TEST(BasicBlockUtils, IsPresplitCoroSuspendExitTest) {
617 LLVMContext C;
618 std::unique_ptr<Module> M = parseIR(C, R"IR(
619 define void @positive_case(i32 %0) #0 {
620 entry:
621 %save = call token @llvm.coro.save(ptr null)
622 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
623 switch i8 %suspend, label %exit [
624 i8 0, label %resume
625 i8 1, label %destroy
626 ]
627 resume:
628 ret void
629 destroy:
630 ret void
631 exit:
632 call i1 @llvm.coro.end(ptr null, i1 false, token none)
633 ret void
634 }
635
636 define void @notpresplit(i32 %0) {
637 entry:
638 %save = call token @llvm.coro.save(ptr null)
639 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
640 switch i8 %suspend, label %exit [
641 i8 0, label %resume
642 i8 1, label %destroy
643 ]
644 resume:
645 ret void
646 destroy:
647 ret void
648 exit:
649 call i1 @llvm.coro.end(ptr null, i1 false, token none)
650 ret void
651 }
652
653 declare token @llvm.coro.save(ptr)
654 declare i8 @llvm.coro.suspend(token, i1)
655 declare i1 @llvm.coro.end(ptr, i1, token)
656
657 attributes #0 = { presplitcoroutine }
658 )IR");
659
660 auto FindExit = [](const Function &F) -> const BasicBlock * {
661 for (const auto &BB : F)
662 if (BB.getName() == "exit")
663 return &BB;
664 return nullptr;
665 };
666 Function *P = M->getFunction("positive_case");
667 const auto &ExitP = *FindExit(*P);
668 EXPECT_TRUE(llvm::isPresplitCoroSuspendExitEdge(*ExitP.getSinglePredecessor(),
669 ExitP));
670
671 Function *N = M->getFunction("notpresplit");
672 const auto &ExitN = *FindExit(*N);
673 EXPECT_FALSE(llvm::isPresplitCoroSuspendExitEdge(
674 *ExitN.getSinglePredecessor(), ExitN));
675 }
676