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