xref: /llvm-project/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp (revision 4169338e75cdce73d34063532db598c95ee82ae4)
18267b333SNico Weber //===- BasicBlockUtils.cpp - Unit tests for BasicBlockUtils ---------------===//
28267b333SNico Weber //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68267b333SNico Weber //
78267b333SNico Weber //===----------------------------------------------------------------------===//
88267b333SNico Weber 
98267b333SNico Weber #include "llvm/Transforms/Utils/BasicBlockUtils.h"
102a814cd9SWhitney Tsang #include "llvm/Analysis/AssumptionCache.h"
112a814cd9SWhitney Tsang #include "llvm/Analysis/BasicAliasAnalysis.h"
12b921543cSYevgeny Rouban #include "llvm/Analysis/BlockFrequencyInfo.h"
13b921543cSYevgeny Rouban #include "llvm/Analysis/BranchProbabilityInfo.h"
14d81d9e8bSSidharth Baveja #include "llvm/Analysis/CFG.h"
15a494ae43Sserge-sans-paille #include "llvm/Analysis/DomTreeUpdater.h"
16b921543cSYevgeny Rouban #include "llvm/Analysis/LoopInfo.h"
172a814cd9SWhitney Tsang #include "llvm/Analysis/MemorySSA.h"
182a814cd9SWhitney Tsang #include "llvm/Analysis/MemorySSAUpdater.h"
1965b4ab99SMatt Arsenault #include "llvm/Analysis/PostDominators.h"
202a814cd9SWhitney Tsang #include "llvm/Analysis/TargetLibraryInfo.h"
218267b333SNico Weber #include "llvm/AsmParser/Parser.h"
228267b333SNico Weber #include "llvm/IR/BasicBlock.h"
238267b333SNico Weber #include "llvm/IR/Dominators.h"
248267b333SNico Weber #include "llvm/IR/LLVMContext.h"
25*4169338eSNikita Popov #include "llvm/IR/Module.h"
268267b333SNico Weber #include "llvm/Support/SourceMgr.h"
278267b333SNico Weber #include "gtest/gtest.h"
288267b333SNico Weber 
298267b333SNico Weber using namespace llvm;
308267b333SNico Weber 
parseIR(LLVMContext & C,const char * IR)318267b333SNico Weber static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
328267b333SNico Weber   SMDiagnostic Err;
338267b333SNico Weber   std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
348267b333SNico Weber   if (!Mod)
358267b333SNico Weber     Err.print("BasicBlockUtilsTests", errs());
368267b333SNico Weber   return Mod;
378267b333SNico Weber }
388267b333SNico Weber 
getBasicBlockByName(Function & F,StringRef Name)392a814cd9SWhitney Tsang static BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
402a814cd9SWhitney Tsang   for (BasicBlock &BB : F)
412a814cd9SWhitney Tsang     if (BB.getName() == Name)
422a814cd9SWhitney Tsang       return &BB;
432a814cd9SWhitney Tsang   llvm_unreachable("Expected to find basic block!");
442a814cd9SWhitney Tsang }
452a814cd9SWhitney Tsang 
TEST(BasicBlockUtils,EliminateUnreachableBlocks)464349dc76SBrian Gesiak TEST(BasicBlockUtils, EliminateUnreachableBlocks) {
474349dc76SBrian Gesiak   LLVMContext C;
48d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
49d7a30732SMatthias Braun define i32 @has_unreachable(i1 %cond) {
50d7a30732SMatthias Braun entry:
51d7a30732SMatthias Braun   br i1 %cond, label %bb0, label %bb1
52d7a30732SMatthias Braun bb0:
53d7a30732SMatthias Braun   br label %bb1
54d7a30732SMatthias Braun bb1:
55d7a30732SMatthias Braun   %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]
56d7a30732SMatthias Braun   ret i32 %phi
57d7a30732SMatthias Braun bb2:
58d7a30732SMatthias Braun   ret i32 42
59d7a30732SMatthias Braun }
60d7a30732SMatthias Braun )IR");
61d7a30732SMatthias Braun   Function *F = M->getFunction("has_unreachable");
624349dc76SBrian Gesiak   DominatorTree DT(*F);
634349dc76SBrian Gesiak   DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
644349dc76SBrian Gesiak 
654349dc76SBrian Gesiak   EXPECT_EQ(F->size(), (size_t)4);
664349dc76SBrian Gesiak   bool Result = EliminateUnreachableBlocks(*F, &DTU);
674349dc76SBrian Gesiak   EXPECT_TRUE(Result);
684349dc76SBrian Gesiak   EXPECT_EQ(F->size(), (size_t)3);
694349dc76SBrian Gesiak   EXPECT_TRUE(DT.verify());
704349dc76SBrian Gesiak }
714349dc76SBrian Gesiak 
TEST(BasicBlockUtils,SplitEdge_ex1)722a814cd9SWhitney Tsang TEST(BasicBlockUtils, SplitEdge_ex1) {
732a814cd9SWhitney Tsang   LLVMContext C;
74d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
75d7a30732SMatthias Braun define void @foo(i1 %cond0) {
76d7a30732SMatthias Braun entry:
77d7a30732SMatthias Braun   br i1 %cond0, label %bb0, label %bb1
78d7a30732SMatthias Braun bb0:
79d7a30732SMatthias Braun  %0 = mul i32 1, 2
80d7a30732SMatthias Braun   br label %bb1
81d7a30732SMatthias Braun bb1:
82d7a30732SMatthias Braun   br label %bb2
83d7a30732SMatthias Braun bb2:
84d7a30732SMatthias Braun   ret void
85d7a30732SMatthias Braun }
86d7a30732SMatthias Braun )IR");
872a814cd9SWhitney Tsang   Function *F = M->getFunction("foo");
882a814cd9SWhitney Tsang   DominatorTree DT(*F);
892a814cd9SWhitney Tsang   BasicBlock *SrcBlock;
902a814cd9SWhitney Tsang   BasicBlock *DestBlock;
912a814cd9SWhitney Tsang   BasicBlock *NewBB;
922a814cd9SWhitney Tsang 
932a814cd9SWhitney Tsang   SrcBlock = getBasicBlockByName(*F, "entry");
942a814cd9SWhitney Tsang   DestBlock = getBasicBlockByName(*F, "bb0");
952a814cd9SWhitney Tsang   NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr);
962a814cd9SWhitney Tsang 
972a814cd9SWhitney Tsang   EXPECT_TRUE(DT.verify());
982a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);
992a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);
1002a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getParent(), F);
1012a814cd9SWhitney Tsang 
1022a814cd9SWhitney Tsang   bool BBFlag = false;
1032a814cd9SWhitney Tsang   for (BasicBlock &BB : *F) {
1042a814cd9SWhitney Tsang     if (BB.getName() == NewBB->getName()) {
1052a814cd9SWhitney Tsang       BBFlag = true;
1062a814cd9SWhitney Tsang     }
1072a814cd9SWhitney Tsang   }
1082a814cd9SWhitney Tsang   EXPECT_TRUE(BBFlag);
1092a814cd9SWhitney Tsang }
1102a814cd9SWhitney Tsang 
TEST(BasicBlockUtils,SplitEdge_ex2)1112a814cd9SWhitney Tsang TEST(BasicBlockUtils, SplitEdge_ex2) {
1122a814cd9SWhitney Tsang   LLVMContext C;
113d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
114d7a30732SMatthias Braun define void @foo() {
115d7a30732SMatthias Braun bb0:
116d7a30732SMatthias Braun   br label %bb2
117d7a30732SMatthias Braun bb1:
118d7a30732SMatthias Braun   br label %bb2
119d7a30732SMatthias Braun bb2:
120d7a30732SMatthias Braun   ret void
121d7a30732SMatthias Braun }
122d7a30732SMatthias Braun )IR");
1232a814cd9SWhitney Tsang   Function *F = M->getFunction("foo");
1242a814cd9SWhitney Tsang   DominatorTree DT(*F);
1252a814cd9SWhitney Tsang 
1262a814cd9SWhitney Tsang   BasicBlock *SrcBlock;
1272a814cd9SWhitney Tsang   BasicBlock *DestBlock;
1282a814cd9SWhitney Tsang   BasicBlock *NewBB;
1292a814cd9SWhitney Tsang 
1302a814cd9SWhitney Tsang   SrcBlock = getBasicBlockByName(*F, "bb0");
1312a814cd9SWhitney Tsang   DestBlock = getBasicBlockByName(*F, "bb2");
1322a814cd9SWhitney Tsang   NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr);
1332a814cd9SWhitney Tsang 
1342a814cd9SWhitney Tsang   EXPECT_TRUE(DT.verify());
1352a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);
1362a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);
1372a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getParent(), F);
1382a814cd9SWhitney Tsang 
1392a814cd9SWhitney Tsang   bool BBFlag = false;
1402a814cd9SWhitney Tsang   for (BasicBlock &BB : *F) {
1412a814cd9SWhitney Tsang     if (BB.getName() == NewBB->getName()) {
1422a814cd9SWhitney Tsang       BBFlag = true;
1432a814cd9SWhitney Tsang     }
1442a814cd9SWhitney Tsang   }
1452a814cd9SWhitney Tsang   EXPECT_TRUE(BBFlag);
1462a814cd9SWhitney Tsang }
1472a814cd9SWhitney Tsang 
TEST(BasicBlockUtils,SplitEdge_ex3)1482a814cd9SWhitney Tsang TEST(BasicBlockUtils, SplitEdge_ex3) {
1492a814cd9SWhitney Tsang   LLVMContext C;
150d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
151d7a30732SMatthias Braun define i32 @foo(i32 %n) {
152d7a30732SMatthias Braun entry:
153d7a30732SMatthias Braun  br label %header
154d7a30732SMatthias Braun header:
155d7a30732SMatthias Braun  %sum.02 = phi i32 [ 0, %entry ], [ %sum.1, %bb3 ]
156d7a30732SMatthias Braun  %0 = phi i32 [ 0, %entry ], [ %4, %bb3 ]
157d7a30732SMatthias Braun  %1 = icmp slt i32 %0, %n
158d7a30732SMatthias Braun  br i1 %1, label %bb0, label %bb1
159d7a30732SMatthias Braun bb0:
160d7a30732SMatthias Braun   %2 = add nsw i32 %sum.02, 2
161d7a30732SMatthias Braun   br label %bb2
162d7a30732SMatthias Braun bb1:
163d7a30732SMatthias Braun   %3 = add nsw i32 %sum.02, 1
164d7a30732SMatthias Braun   br label %bb2
165d7a30732SMatthias Braun bb2:
166d7a30732SMatthias Braun   %sum.1 = phi i32 [ %2, %bb0 ], [ %3, %bb1 ]
167d7a30732SMatthias Braun   br label %bb3
168d7a30732SMatthias Braun bb3:
169d7a30732SMatthias Braun   %4 = add nsw i32 %0, 1
170d7a30732SMatthias Braun   %5 = icmp slt i32 %4, 100
171d7a30732SMatthias Braun   br i1 %5, label %header, label %bb4
172d7a30732SMatthias Braun bb4:
173d7a30732SMatthias Braun  %sum.0.lcssa = phi i32 [ %sum.1, %bb3 ]
174d7a30732SMatthias Braun  ret i32 %sum.0.lcssa
175d7a30732SMatthias Braun }
176d7a30732SMatthias Braun )IR");
1772a814cd9SWhitney Tsang   Function *F = M->getFunction("foo");
1782a814cd9SWhitney Tsang   DominatorTree DT(*F);
1792a814cd9SWhitney Tsang 
1802a814cd9SWhitney Tsang   LoopInfo LI(DT);
1812a814cd9SWhitney Tsang 
1822a814cd9SWhitney Tsang   DataLayout DL("e-i64:64-f80:128-n8:16:32:64-S128");
1832a814cd9SWhitney Tsang   TargetLibraryInfoImpl TLII;
1842a814cd9SWhitney Tsang   TargetLibraryInfo TLI(TLII);
1852a814cd9SWhitney Tsang   AssumptionCache AC(*F);
1862a814cd9SWhitney Tsang   AAResults AA(TLI);
1872a814cd9SWhitney Tsang 
1882a814cd9SWhitney Tsang   BasicAAResult BAA(DL, *F, TLI, AC, &DT);
1892a814cd9SWhitney Tsang   AA.addAAResult(BAA);
1902a814cd9SWhitney Tsang 
1912a814cd9SWhitney Tsang   MemorySSA MSSA(*F, &AA, &DT);
1922a814cd9SWhitney Tsang   MemorySSAUpdater Updater(&MSSA);
1932a814cd9SWhitney Tsang 
1942a814cd9SWhitney Tsang   BasicBlock *SrcBlock;
1952a814cd9SWhitney Tsang   BasicBlock *DestBlock;
1962a814cd9SWhitney Tsang   BasicBlock *NewBB;
1972a814cd9SWhitney Tsang 
1982a814cd9SWhitney Tsang   SrcBlock = getBasicBlockByName(*F, "header");
1992a814cd9SWhitney Tsang   DestBlock = getBasicBlockByName(*F, "bb0");
2002a814cd9SWhitney Tsang   NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &Updater);
2012a814cd9SWhitney Tsang 
2022a814cd9SWhitney Tsang   Updater.getMemorySSA()->verifyMemorySSA();
2032a814cd9SWhitney Tsang   EXPECT_TRUE(DT.verify());
2042a814cd9SWhitney Tsang   EXPECT_NE(LI.getLoopFor(SrcBlock), nullptr);
2052a814cd9SWhitney Tsang   EXPECT_NE(LI.getLoopFor(DestBlock), nullptr);
2062a814cd9SWhitney Tsang   EXPECT_NE(LI.getLoopFor(NewBB), nullptr);
2072a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);
2082a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);
2092a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getParent(), F);
2102a814cd9SWhitney Tsang 
2112a814cd9SWhitney Tsang   bool BBFlag = false;
2122a814cd9SWhitney Tsang   for (BasicBlock &BB : *F) {
2132a814cd9SWhitney Tsang     if (BB.getName() == NewBB->getName()) {
2142a814cd9SWhitney Tsang       BBFlag = true;
2152a814cd9SWhitney Tsang     }
2162a814cd9SWhitney Tsang   }
2172a814cd9SWhitney Tsang   EXPECT_TRUE(BBFlag);
2182a814cd9SWhitney Tsang }
2192a814cd9SWhitney Tsang 
TEST(BasicBlockUtils,SplitEdge_ex4)220d81d9e8bSSidharth Baveja TEST(BasicBlockUtils, SplitEdge_ex4) {
221d81d9e8bSSidharth Baveja   LLVMContext C;
222d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
223d7a30732SMatthias Braun define void @bar(i32 %cond) personality i8 0 {
224d7a30732SMatthias Braun entry:
225d7a30732SMatthias Braun   switch i32 %cond, label %exit [
226d7a30732SMatthias Braun     i32 -1, label %continue
227d7a30732SMatthias Braun     i32 0, label %continue
228d7a30732SMatthias Braun     i32 1, label %continue_alt
229d7a30732SMatthias Braun     i32 2, label %continue_alt
230d7a30732SMatthias Braun   ]
231d7a30732SMatthias Braun exit:
232d7a30732SMatthias Braun   ret void
233d7a30732SMatthias Braun continue:
234d7a30732SMatthias Braun   invoke void @sink() to label %normal unwind label %exception
235d7a30732SMatthias Braun continue_alt:
236d7a30732SMatthias Braun   invoke void @sink_alt() to label %normal unwind label %exception
237d7a30732SMatthias Braun exception:
238d7a30732SMatthias Braun   %cleanup = landingpad i8 cleanup
239d7a30732SMatthias Braun   br label %trivial-eh-handler
240d7a30732SMatthias Braun trivial-eh-handler:
241d7a30732SMatthias Braun   call void @sideeffect(i32 1)
242d7a30732SMatthias Braun   br label %normal
243d7a30732SMatthias Braun normal:
244d7a30732SMatthias Braun   call void @sideeffect(i32 0)
245d7a30732SMatthias Braun   ret void
246d7a30732SMatthias Braun }
247d81d9e8bSSidharth Baveja 
248d7a30732SMatthias Braun declare void @sideeffect(i32)
249d7a30732SMatthias Braun declare void @sink() cold
250d7a30732SMatthias Braun declare void @sink_alt() cold
251d7a30732SMatthias Braun )IR");
252d81d9e8bSSidharth Baveja   Function *F = M->getFunction("bar");
253d81d9e8bSSidharth Baveja 
254d81d9e8bSSidharth Baveja   DominatorTree DT(*F);
255d81d9e8bSSidharth Baveja 
256d81d9e8bSSidharth Baveja   LoopInfo LI(DT);
257d81d9e8bSSidharth Baveja 
258d81d9e8bSSidharth Baveja   TargetLibraryInfoImpl TLII;
259d81d9e8bSSidharth Baveja   TargetLibraryInfo TLI(TLII);
260d81d9e8bSSidharth Baveja 
261d81d9e8bSSidharth Baveja   AAResults AA(TLI);
262d81d9e8bSSidharth Baveja 
263d81d9e8bSSidharth Baveja   MemorySSA MSSA(*F, &AA, &DT);
264d81d9e8bSSidharth Baveja   MemorySSAUpdater MSSAU(&MSSA);
265d81d9e8bSSidharth Baveja 
266d81d9e8bSSidharth Baveja   BasicBlock *SrcBlock;
267d81d9e8bSSidharth Baveja   BasicBlock *DestBlock;
268d81d9e8bSSidharth Baveja 
269d81d9e8bSSidharth Baveja   SrcBlock = getBasicBlockByName(*F, "continue");
270d81d9e8bSSidharth Baveja   DestBlock = getBasicBlockByName(*F, "exception");
271d81d9e8bSSidharth Baveja 
272d81d9e8bSSidharth Baveja   unsigned SuccNum = GetSuccessorNumber(SrcBlock, DestBlock);
273d81d9e8bSSidharth Baveja   Instruction *LatchTerm = SrcBlock->getTerminator();
274d81d9e8bSSidharth Baveja 
275d81d9e8bSSidharth Baveja   const CriticalEdgeSplittingOptions Options =
276d81d9e8bSSidharth Baveja       CriticalEdgeSplittingOptions(&DT, &LI, &MSSAU);
277d81d9e8bSSidharth Baveja 
278d81d9e8bSSidharth Baveja   // Check that the following edge is both critical and the destination block is
279d81d9e8bSSidharth Baveja   // an exception block. These must be handled differently by SplitEdge
280d81d9e8bSSidharth Baveja   bool CriticalEdge =
281d81d9e8bSSidharth Baveja       isCriticalEdge(LatchTerm, SuccNum, Options.MergeIdenticalEdges);
282d81d9e8bSSidharth Baveja   EXPECT_TRUE(CriticalEdge);
283d81d9e8bSSidharth Baveja 
284d81d9e8bSSidharth Baveja   bool Ehpad = DestBlock->isEHPad();
285d81d9e8bSSidharth Baveja   EXPECT_TRUE(Ehpad);
286d81d9e8bSSidharth Baveja 
287d81d9e8bSSidharth Baveja   BasicBlock *NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &MSSAU, "");
288d81d9e8bSSidharth Baveja 
289d81d9e8bSSidharth Baveja   MSSA.verifyMemorySSA();
290d81d9e8bSSidharth Baveja   EXPECT_TRUE(DT.verify());
291d81d9e8bSSidharth Baveja   EXPECT_NE(NewBB, nullptr);
292d81d9e8bSSidharth Baveja   EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);
293d81d9e8bSSidharth Baveja   EXPECT_EQ(NewBB, SrcBlock->getTerminator()->getSuccessor(SuccNum));
294d81d9e8bSSidharth Baveja   EXPECT_EQ(NewBB->getParent(), F);
295d81d9e8bSSidharth Baveja 
296d81d9e8bSSidharth Baveja   bool BBFlag = false;
297d81d9e8bSSidharth Baveja   for (BasicBlock &BB : *F) {
298d81d9e8bSSidharth Baveja     if (BB.getName() == NewBB->getName()) {
299d81d9e8bSSidharth Baveja       BBFlag = true;
300d81d9e8bSSidharth Baveja       break;
301d81d9e8bSSidharth Baveja     }
302d81d9e8bSSidharth Baveja   }
303d81d9e8bSSidharth Baveja   EXPECT_TRUE(BBFlag);
304d81d9e8bSSidharth Baveja }
305d81d9e8bSSidharth Baveja 
TEST(BasicBlockUtils,splitBasicBlockBefore_ex1)3062a814cd9SWhitney Tsang TEST(BasicBlockUtils, splitBasicBlockBefore_ex1) {
3072a814cd9SWhitney Tsang   LLVMContext C;
308d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
309d7a30732SMatthias Braun define void @foo() {
310d7a30732SMatthias Braun bb0:
311d7a30732SMatthias Braun  %0 = mul i32 1, 2
312d7a30732SMatthias Braun   br label %bb2
313d7a30732SMatthias Braun bb1:
314d7a30732SMatthias Braun   br label %bb3
315d7a30732SMatthias Braun bb2:
316d7a30732SMatthias Braun   %1 = phi  i32 [ %0, %bb0 ]
317d7a30732SMatthias Braun   br label %bb3
318d7a30732SMatthias Braun bb3:
319d7a30732SMatthias Braun   ret void
320d7a30732SMatthias Braun }
321d7a30732SMatthias Braun )IR");
3222a814cd9SWhitney Tsang   Function *F = M->getFunction("foo");
3232a814cd9SWhitney Tsang   DominatorTree DT(*F);
3242a814cd9SWhitney Tsang 
3252a814cd9SWhitney Tsang   BasicBlock *DestBlock;
3262a814cd9SWhitney Tsang   BasicBlock *NewBB;
3272a814cd9SWhitney Tsang 
3282a814cd9SWhitney Tsang   DestBlock = getBasicBlockByName(*F, "bb2");
3292a814cd9SWhitney Tsang 
3302a814cd9SWhitney Tsang   NewBB = DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(),
3312a814cd9SWhitney Tsang                                            "test");
3322a814cd9SWhitney Tsang 
3332a814cd9SWhitney Tsang   PHINode *PN = dyn_cast<PHINode>(&(DestBlock->front()));
3342a814cd9SWhitney Tsang   EXPECT_EQ(PN->getIncomingBlock(0), NewBB);
3352a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getName(), "test");
3362a814cd9SWhitney Tsang   EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);
3372a814cd9SWhitney Tsang   EXPECT_EQ(DestBlock->getSinglePredecessor(), NewBB);
3382a814cd9SWhitney Tsang }
3392a814cd9SWhitney Tsang 
3402a814cd9SWhitney Tsang #ifndef NDEBUG
TEST(BasicBlockUtils,splitBasicBlockBefore_ex2)3412a814cd9SWhitney Tsang TEST(BasicBlockUtils, splitBasicBlockBefore_ex2) {
3422a814cd9SWhitney Tsang   LLVMContext C;
343d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
344d7a30732SMatthias Braun define void @foo() {
345d7a30732SMatthias Braun bb0:
346d7a30732SMatthias Braun  %0 = mul i32 1, 2
347d7a30732SMatthias Braun   br label %bb2
348d7a30732SMatthias Braun bb1:
349d7a30732SMatthias Braun   br label %bb2
350d7a30732SMatthias Braun bb2:
351d7a30732SMatthias Braun   %1 = phi  i32 [ %0, %bb0 ], [ 1, %bb1 ]
352d7a30732SMatthias Braun   br label %bb3
353d7a30732SMatthias Braun bb3:
354d7a30732SMatthias Braun   ret void
355d7a30732SMatthias Braun }
356d7a30732SMatthias Braun )IR");
3572a814cd9SWhitney Tsang   Function *F = M->getFunction("foo");
3582a814cd9SWhitney Tsang   DominatorTree DT(*F);
3592a814cd9SWhitney Tsang 
360d7a30732SMatthias Braun   BasicBlock *DestBlock = getBasicBlockByName(*F, "bb2");
3612a814cd9SWhitney Tsang 
3622a814cd9SWhitney Tsang   ASSERT_DEATH(
3632a814cd9SWhitney Tsang       {
3642a814cd9SWhitney Tsang         DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(),
3652a814cd9SWhitney Tsang                                          "test");
3662a814cd9SWhitney Tsang       },
3672a814cd9SWhitney Tsang       "cannot split on multi incoming phis");
3682a814cd9SWhitney Tsang }
3692a814cd9SWhitney Tsang #endif
3702a814cd9SWhitney Tsang 
TEST(BasicBlockUtils,NoUnreachableBlocksToEliminate)3714349dc76SBrian Gesiak TEST(BasicBlockUtils, NoUnreachableBlocksToEliminate) {
3724349dc76SBrian Gesiak   LLVMContext C;
373d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
374d7a30732SMatthias Braun define i32 @no_unreachable(i1 %cond) {
375d7a30732SMatthias Braun entry:
376d7a30732SMatthias Braun   br i1 %cond, label %bb0, label %bb1
377d7a30732SMatthias Braun bb0:
378d7a30732SMatthias Braun   br label %bb1
379d7a30732SMatthias Braun bb1:
380d7a30732SMatthias Braun   %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]
381d7a30732SMatthias Braun   ret i32 %phi
382d7a30732SMatthias Braun }
383d7a30732SMatthias Braun )IR");
384d7a30732SMatthias Braun   Function *F = M->getFunction("no_unreachable");
3854349dc76SBrian Gesiak   DominatorTree DT(*F);
3864349dc76SBrian Gesiak   DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
3874349dc76SBrian Gesiak 
3884349dc76SBrian Gesiak   EXPECT_EQ(F->size(), (size_t)3);
3894349dc76SBrian Gesiak   bool Result = EliminateUnreachableBlocks(*F, &DTU);
3904349dc76SBrian Gesiak   EXPECT_FALSE(Result);
3914349dc76SBrian Gesiak   EXPECT_EQ(F->size(), (size_t)3);
3924349dc76SBrian Gesiak   EXPECT_TRUE(DT.verify());
3934349dc76SBrian Gesiak }
3944349dc76SBrian Gesiak 
TEST(BasicBlockUtils,SplitBlockPredecessors)3958267b333SNico Weber TEST(BasicBlockUtils, SplitBlockPredecessors) {
3968267b333SNico Weber   LLVMContext C;
397d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
398d7a30732SMatthias Braun define i32 @basic_func(i1 %cond) {
399d7a30732SMatthias Braun entry:
400d7a30732SMatthias Braun   br i1 %cond, label %bb0, label %bb1
401d7a30732SMatthias Braun bb0:
402d7a30732SMatthias Braun   br label %bb1
403d7a30732SMatthias Braun bb1:
404d7a30732SMatthias Braun   %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]
405d7a30732SMatthias Braun   ret i32 %phi
406d7a30732SMatthias Braun }
407d7a30732SMatthias Braun )IR");
408d7a30732SMatthias Braun   Function *F = M->getFunction("basic_func");
4098267b333SNico Weber   DominatorTree DT(*F);
4108267b333SNico Weber 
4118267b333SNico Weber   // Make sure the dominator tree is properly updated if calling this on the
4128267b333SNico Weber   // entry block.
4138267b333SNico Weber   SplitBlockPredecessors(&F->getEntryBlock(), {}, "split.entry", &DT);
4148267b333SNico Weber   EXPECT_TRUE(DT.verify());
4158267b333SNico Weber }
41665b4ab99SMatt Arsenault 
TEST(BasicBlockUtils,SplitCriticalEdge)41765b4ab99SMatt Arsenault TEST(BasicBlockUtils, SplitCriticalEdge) {
41865b4ab99SMatt Arsenault   LLVMContext C;
419d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
420d7a30732SMatthias Braun define void @crit_edge(i1 %cond0, i1 %cond1) {
421d7a30732SMatthias Braun entry:
422d7a30732SMatthias Braun   br i1 %cond0, label %bb0, label %bb1
423d7a30732SMatthias Braun bb0:
424d7a30732SMatthias Braun   br label %bb1
425d7a30732SMatthias Braun bb1:
426d7a30732SMatthias Braun   br label %bb2
427d7a30732SMatthias Braun bb2:
428d7a30732SMatthias Braun   ret void
429d7a30732SMatthias Braun }
430d7a30732SMatthias Braun )IR");
431d7a30732SMatthias Braun   Function *F = M->getFunction("crit_edge");
43265b4ab99SMatt Arsenault   DominatorTree DT(*F);
43365b4ab99SMatt Arsenault   PostDominatorTree PDT(*F);
43465b4ab99SMatt Arsenault 
43565b4ab99SMatt Arsenault   CriticalEdgeSplittingOptions CESO(&DT, nullptr, nullptr, &PDT);
43665b4ab99SMatt Arsenault   EXPECT_EQ(1u, SplitAllCriticalEdges(*F, CESO));
43765b4ab99SMatt Arsenault   EXPECT_TRUE(DT.verify());
43865b4ab99SMatt Arsenault   EXPECT_TRUE(PDT.verify());
43965b4ab99SMatt Arsenault }
440b921543cSYevgeny Rouban 
TEST(BasicBlockUtils,SplitIndirectBrCriticalEdgesIgnorePHIs)4416a383369SMatthias Braun TEST(BasicBlockUtils, SplitIndirectBrCriticalEdgesIgnorePHIs) {
442b921543cSYevgeny Rouban   LLVMContext C;
443d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
4446a383369SMatthias Braun define void @crit_edge(i8* %tgt, i1 %cond0, i1 %cond1) {
445d7a30732SMatthias Braun entry:
4466a383369SMatthias Braun   indirectbr i8* %tgt, [label %bb0, label %bb1, label %bb2]
447d7a30732SMatthias Braun bb0:
4486a383369SMatthias Braun   br i1 %cond0, label %bb1, label %bb2
449d7a30732SMatthias Braun bb1:
450d7a30732SMatthias Braun   %p = phi i32 [0, %bb0], [0, %entry]
4516a383369SMatthias Braun   br i1 %cond1, label %bb3, label %bb4
452d7a30732SMatthias Braun bb2:
453d7a30732SMatthias Braun   ret void
454d7a30732SMatthias Braun bb3:
455d7a30732SMatthias Braun   ret void
4566a383369SMatthias Braun bb4:
4576a383369SMatthias Braun   ret void
458d7a30732SMatthias Braun }
459d7a30732SMatthias Braun )IR");
460d7a30732SMatthias Braun   Function *F = M->getFunction("crit_edge");
461b921543cSYevgeny Rouban   DominatorTree DT(*F);
462b921543cSYevgeny Rouban   LoopInfo LI(DT);
463b921543cSYevgeny Rouban   BranchProbabilityInfo BPI(*F, LI);
464b921543cSYevgeny Rouban   BlockFrequencyInfo BFI(*F, BPI, LI);
465b921543cSYevgeny Rouban 
4666a383369SMatthias Braun   ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/true,
4676a383369SMatthias Braun                                            &BPI, &BFI));
468b921543cSYevgeny Rouban 
469b921543cSYevgeny Rouban   // Check that successors of the split block get their probability correct.
470d7a30732SMatthias Braun   BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");
471d7a30732SMatthias Braun   BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);
4726a383369SMatthias Braun   ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());
473b921543cSYevgeny Rouban   EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));
474b921543cSYevgeny Rouban   EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));
4756a383369SMatthias Braun 
4766a383369SMatthias Braun   // bb2 has no PHI, so we shouldn't split bb0 -> bb2
4776a383369SMatthias Braun   BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
4786a383369SMatthias Braun   ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());
4796a383369SMatthias Braun   EXPECT_EQ(BB0->getTerminator()->getSuccessor(1),
4806a383369SMatthias Braun             getBasicBlockByName(*F, "bb2"));
4816a383369SMatthias Braun }
4826a383369SMatthias Braun 
TEST(BasicBlockUtils,SplitIndirectBrCriticalEdges)4836a383369SMatthias Braun TEST(BasicBlockUtils, SplitIndirectBrCriticalEdges) {
4846a383369SMatthias Braun   LLVMContext C;
4856a383369SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
4866a383369SMatthias Braun define void @crit_edge(i8* %tgt, i1 %cond0, i1 %cond1) {
4876a383369SMatthias Braun entry:
4886a383369SMatthias Braun   indirectbr i8* %tgt, [label %bb0, label %bb1, label %bb2]
4896a383369SMatthias Braun bb0:
4906a383369SMatthias Braun   br i1 %cond0, label %bb1, label %bb2
4916a383369SMatthias Braun bb1:
4926a383369SMatthias Braun   %p = phi i32 [0, %bb0], [0, %entry]
4936a383369SMatthias Braun   br i1 %cond1, label %bb3, label %bb4
4946a383369SMatthias Braun bb2:
4956a383369SMatthias Braun   ret void
4966a383369SMatthias Braun bb3:
4976a383369SMatthias Braun   ret void
4986a383369SMatthias Braun bb4:
4996a383369SMatthias Braun   ret void
5006a383369SMatthias Braun }
5016a383369SMatthias Braun )IR");
5026a383369SMatthias Braun   Function *F = M->getFunction("crit_edge");
5036a383369SMatthias Braun   DominatorTree DT(*F);
5046a383369SMatthias Braun   LoopInfo LI(DT);
5056a383369SMatthias Braun   BranchProbabilityInfo BPI(*F, LI);
5066a383369SMatthias Braun   BlockFrequencyInfo BFI(*F, BPI, LI);
5076a383369SMatthias Braun 
5086a383369SMatthias Braun   ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/false,
5096a383369SMatthias Braun                                            &BPI, &BFI));
5106a383369SMatthias Braun 
5116a383369SMatthias Braun   // Check that successors of the split block get their probability correct.
5126a383369SMatthias Braun   BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");
5136a383369SMatthias Braun   BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);
5146a383369SMatthias Braun   ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());
5156a383369SMatthias Braun   EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));
5166a383369SMatthias Braun   EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));
5176a383369SMatthias Braun 
5186a383369SMatthias Braun   // Should split, resulting in:
5196a383369SMatthias Braun   //   bb0 -> bb2.clone; bb2 -> split1; bb2.clone -> split,
5206a383369SMatthias Braun   BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
5216a383369SMatthias Braun   ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());
5226a383369SMatthias Braun   BasicBlock *BB2Clone = BB0->getTerminator()->getSuccessor(1);
5236a383369SMatthias Braun   BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");
5246a383369SMatthias Braun   EXPECT_NE(BB2Clone, BB2);
5256a383369SMatthias Braun   ASSERT_EQ(1u, BB2->getTerminator()->getNumSuccessors());
5266a383369SMatthias Braun   ASSERT_EQ(1u, BB2Clone->getTerminator()->getNumSuccessors());
5276a383369SMatthias Braun   EXPECT_EQ(BB2->getTerminator()->getSuccessor(0),
5286a383369SMatthias Braun             BB2Clone->getTerminator()->getSuccessor(0));
529b921543cSYevgeny Rouban }
53081384874SYevgeny Rouban 
TEST(BasicBlockUtils,SetEdgeProbability)53181384874SYevgeny Rouban TEST(BasicBlockUtils, SetEdgeProbability) {
53281384874SYevgeny Rouban   LLVMContext C;
533d7a30732SMatthias Braun   std::unique_ptr<Module> M = parseIR(C, R"IR(
534d7a30732SMatthias Braun define void @edge_probability(i32 %0) {
535d7a30732SMatthias Braun entry:
536d7a30732SMatthias Braun switch i32 %0, label %LD [
537d7a30732SMatthias Braun   i32 700, label %L0
538d7a30732SMatthias Braun   i32 701, label %L1
539d7a30732SMatthias Braun   i32 702, label %L2
540d7a30732SMatthias Braun   i32 703, label %L3
541d7a30732SMatthias Braun   i32 704, label %L4
542d7a30732SMatthias Braun   i32 705, label %L5
543d7a30732SMatthias Braun   i32 706, label %L6
544d7a30732SMatthias Braun   i32 707, label %L7
545d7a30732SMatthias Braun   i32 708, label %L8
546d7a30732SMatthias Braun   i32 709, label %L9
547d7a30732SMatthias Braun   i32 710, label %L10
548d7a30732SMatthias Braun   i32 711, label %L11
549d7a30732SMatthias Braun   i32 712, label %L12
550d7a30732SMatthias Braun   i32 713, label %L13
551d7a30732SMatthias Braun   i32 714, label %L14
552d7a30732SMatthias Braun   i32 715, label %L15
553d7a30732SMatthias Braun   i32 716, label %L16
554d7a30732SMatthias Braun   i32 717, label %L17
555d7a30732SMatthias Braun   i32 718, label %L18
556d7a30732SMatthias Braun   i32 719, label %L19
557d7a30732SMatthias Braun ], !prof !{!"branch_weights", i32 1, i32 1, i32 1, i32 1, i32 1, i32 451, i32 1,
558d7a30732SMatthias Braun            i32 12, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1,
559d7a30732SMatthias Braun            i32 1, i32 1, i32 1, i32 1, i32 1}
560d7a30732SMatthias Braun LD:
561d7a30732SMatthias Braun   unreachable
562d7a30732SMatthias Braun L0:
563d7a30732SMatthias Braun   ret void
564d7a30732SMatthias Braun L1:
565d7a30732SMatthias Braun   ret void
566d7a30732SMatthias Braun L2:
567d7a30732SMatthias Braun   ret void
568d7a30732SMatthias Braun L3:
569d7a30732SMatthias Braun   ret void
570d7a30732SMatthias Braun L4:
571d7a30732SMatthias Braun   ret void
572d7a30732SMatthias Braun L5:
573d7a30732SMatthias Braun   ret void
574d7a30732SMatthias Braun L6:
575d7a30732SMatthias Braun   ret void
576d7a30732SMatthias Braun L7:
577d7a30732SMatthias Braun   ret void
578d7a30732SMatthias Braun L8:
579d7a30732SMatthias Braun   ret void
580d7a30732SMatthias Braun L9:
581d7a30732SMatthias Braun   ret void
582d7a30732SMatthias Braun L10:
583d7a30732SMatthias Braun   ret void
584d7a30732SMatthias Braun L11:
585d7a30732SMatthias Braun   ret void
586d7a30732SMatthias Braun L12:
587d7a30732SMatthias Braun   ret void
588d7a30732SMatthias Braun L13:
589d7a30732SMatthias Braun   ret void
590d7a30732SMatthias Braun L14:
591d7a30732SMatthias Braun   ret void
592d7a30732SMatthias Braun L15:
593d7a30732SMatthias Braun   ret void
594d7a30732SMatthias Braun L16:
595d7a30732SMatthias Braun   ret void
596d7a30732SMatthias Braun L17:
597d7a30732SMatthias Braun   ret void
598d7a30732SMatthias Braun L18:
599d7a30732SMatthias Braun   ret void
600d7a30732SMatthias Braun L19:
601d7a30732SMatthias Braun   ret void
602d7a30732SMatthias Braun }
603d7a30732SMatthias Braun )IR");
604d7a30732SMatthias Braun   Function *F = M->getFunction("edge_probability");
60581384874SYevgeny Rouban   DominatorTree DT(*F);
60681384874SYevgeny Rouban   LoopInfo LI(DT);
60781384874SYevgeny Rouban   BranchProbabilityInfo BPI(*F, LI);
60881384874SYevgeny Rouban 
60981384874SYevgeny Rouban   // Check that the unreachable block has the minimal probability.
610d7a30732SMatthias Braun   const BasicBlock *EntryBB = getBasicBlockByName(*F, "entry");
611d7a30732SMatthias Braun   const BasicBlock *UnreachableBB = getBasicBlockByName(*F, "LD");
61281384874SYevgeny Rouban   EXPECT_EQ(BranchProbability::getRaw(1),
613d7a30732SMatthias Braun             BPI.getEdgeProbability(EntryBB, UnreachableBB));
61481384874SYevgeny Rouban }
615284da049SMircea Trofin 
TEST(BasicBlockUtils,IsPresplitCoroSuspendExitTest)616284da049SMircea Trofin TEST(BasicBlockUtils, IsPresplitCoroSuspendExitTest) {
617284da049SMircea Trofin   LLVMContext C;
618284da049SMircea Trofin   std::unique_ptr<Module> M = parseIR(C, R"IR(
619284da049SMircea Trofin define void @positive_case(i32 %0) #0 {
620284da049SMircea Trofin entry:
621284da049SMircea Trofin   %save = call token @llvm.coro.save(ptr null)
622284da049SMircea Trofin   %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
623284da049SMircea Trofin   switch i8 %suspend, label %exit [
624284da049SMircea Trofin     i8 0, label %resume
625284da049SMircea Trofin     i8 1, label %destroy
626284da049SMircea Trofin   ]
627284da049SMircea Trofin resume:
628284da049SMircea Trofin   ret void
629284da049SMircea Trofin destroy:
630284da049SMircea Trofin   ret void
631284da049SMircea Trofin exit:
632284da049SMircea Trofin   call i1 @llvm.coro.end(ptr null, i1 false, token none)
633284da049SMircea Trofin   ret void
634284da049SMircea Trofin }
635284da049SMircea Trofin 
636284da049SMircea Trofin define void @notpresplit(i32 %0) {
637284da049SMircea Trofin entry:
638284da049SMircea Trofin   %save = call token @llvm.coro.save(ptr null)
639284da049SMircea Trofin   %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
640284da049SMircea Trofin   switch i8 %suspend, label %exit [
641284da049SMircea Trofin     i8 0, label %resume
642284da049SMircea Trofin     i8 1, label %destroy
643284da049SMircea Trofin   ]
644284da049SMircea Trofin resume:
645284da049SMircea Trofin   ret void
646284da049SMircea Trofin destroy:
647284da049SMircea Trofin   ret void
648284da049SMircea Trofin exit:
649284da049SMircea Trofin   call i1 @llvm.coro.end(ptr null, i1 false, token none)
650284da049SMircea Trofin   ret void
651284da049SMircea Trofin }
652284da049SMircea Trofin 
653284da049SMircea Trofin declare token @llvm.coro.save(ptr)
654284da049SMircea Trofin declare i8 @llvm.coro.suspend(token, i1)
655284da049SMircea Trofin declare i1 @llvm.coro.end(ptr, i1, token)
656284da049SMircea Trofin 
657284da049SMircea Trofin attributes #0 = { presplitcoroutine }
658284da049SMircea Trofin )IR");
659284da049SMircea Trofin 
660284da049SMircea Trofin   auto FindExit = [](const Function &F) -> const BasicBlock * {
661284da049SMircea Trofin     for (const auto &BB : F)
662284da049SMircea Trofin       if (BB.getName() == "exit")
663284da049SMircea Trofin         return &BB;
664284da049SMircea Trofin     return nullptr;
665284da049SMircea Trofin   };
666284da049SMircea Trofin   Function *P = M->getFunction("positive_case");
667284da049SMircea Trofin   const auto &ExitP = *FindExit(*P);
668284da049SMircea Trofin   EXPECT_TRUE(llvm::isPresplitCoroSuspendExitEdge(*ExitP.getSinglePredecessor(),
669284da049SMircea Trofin                                                   ExitP));
670284da049SMircea Trofin 
671284da049SMircea Trofin   Function *N = M->getFunction("notpresplit");
672284da049SMircea Trofin   const auto &ExitN = *FindExit(*N);
673284da049SMircea Trofin   EXPECT_FALSE(llvm::isPresplitCoroSuspendExitEdge(
674284da049SMircea Trofin       *ExitN.getSinglePredecessor(), ExitN));
675284da049SMircea Trofin }
676