1 //===- CodeExtractor.cpp - Unit tests for CodeExtractor -------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/Utils/CodeExtractor.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/BasicBlock.h"
12 #include "llvm/IR/Dominators.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/LLVMContext.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/IR/Verifier.h"
17 #include "llvm/IRReader/IRReader.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "gtest/gtest.h"
24 BasicBlock
*getBlockByName(Function
*F
, StringRef name
) {
26 if (BB
.getName() == name
)
31 TEST(CodeExtractor
, ExitStub
) {
34 std::unique_ptr
<Module
> M(parseAssemblyString(R
"invalid(
35 define i32 @foo(i32 %x, i32 %y, i32 %z) {
37 %0 = icmp ugt i32 %x, %y
38 br i1 %0, label %body1, label %body2
42 br label %notExtracted
46 br label %notExtracted
49 %3 = phi i32 [ %1, %body1 ], [ %2, %body2 ]
56 Function
*Func
= M
->getFunction("foo");
57 SmallVector
<BasicBlock
*, 3> Candidates
{ getBlockByName(Func
, "header"),
58 getBlockByName(Func
, "body1"),
59 getBlockByName(Func
, "body2") };
61 CodeExtractor
CE(Candidates
);
62 EXPECT_TRUE(CE
.isEligible());
64 Function
*Outlined
= CE
.extractCodeRegion();
65 EXPECT_TRUE(Outlined
);
66 BasicBlock
*Exit
= getBlockByName(Func
, "notExtracted");
67 BasicBlock
*ExitSplit
= getBlockByName(Outlined
, "notExtracted.split");
68 // Ensure that PHI in exit block has only one incoming value (from code
70 EXPECT_TRUE(Exit
&& cast
<PHINode
>(Exit
->front()).getNumIncomingValues() == 1);
71 // Ensure that there is a PHI in outlined function with 2 incoming values.
72 EXPECT_TRUE(ExitSplit
&&
73 cast
<PHINode
>(ExitSplit
->front()).getNumIncomingValues() == 2);
74 EXPECT_FALSE(verifyFunction(*Outlined
));
75 EXPECT_FALSE(verifyFunction(*Func
));
78 TEST(CodeExtractor
, ExitPHIOnePredFromRegion
) {
81 std::unique_ptr
<Module
> M(parseAssemblyString(R
"invalid(
84 br i1 undef, label %extracted1, label %pred
87 br i1 undef, label %exit1, label %exit2
90 br i1 undef, label %extracted2, label %exit1
96 %0 = phi i32 [ 1, %extracted1 ], [ 2, %pred ]
100 %1 = phi i32 [ 3, %extracted2 ], [ 4, %pred ]
103 )invalid", Err
, Ctx
));
105 Function
*Func
= M
->getFunction("foo");
106 SmallVector
<BasicBlock
*, 2> ExtractedBlocks
{
107 getBlockByName(Func
, "extracted1"),
108 getBlockByName(Func
, "extracted2")
111 CodeExtractor
CE(ExtractedBlocks
);
112 EXPECT_TRUE(CE
.isEligible());
114 Function
*Outlined
= CE
.extractCodeRegion();
115 EXPECT_TRUE(Outlined
);
116 BasicBlock
*Exit1
= getBlockByName(Func
, "exit1");
117 BasicBlock
*Exit2
= getBlockByName(Func
, "exit2");
118 // Ensure that PHIs in exits are not splitted (since that they have only one
119 // incoming value from extracted region).
121 cast
<PHINode
>(Exit1
->front()).getNumIncomingValues() == 2);
123 cast
<PHINode
>(Exit2
->front()).getNumIncomingValues() == 2);
124 EXPECT_FALSE(verifyFunction(*Outlined
));
125 EXPECT_FALSE(verifyFunction(*Func
));
128 TEST(CodeExtractor
, StoreOutputInvokeResultAfterEHPad
) {
131 std::unique_ptr
<Module
> M(parseAssemblyString(R
"invalid(
134 define i32 @foo() personality i8* null {
136 %call = invoke i8 @hoge()
137 to label %invoke.cont unwind label %lpad
139 invoke.cont: ; preds = %entry
142 lpad: ; preds = %entry
143 %0 = landingpad { i8*, i32 }
145 br i1 undef, label %catch, label %finally.catchall
147 catch: ; preds = %lpad
148 %call2 = invoke i8 @hoge()
149 to label %invoke.cont2 unwind label %lpad2
151 invoke.cont2: ; preds = %catch
152 %call3 = invoke i8 @hoge()
153 to label %invoke.cont3 unwind label %lpad2
155 invoke.cont3: ; preds = %invoke.cont2
158 lpad2: ; preds = %invoke.cont2, %catch
159 %ex.1 = phi i8* [ undef, %invoke.cont2 ], [ null, %catch ]
160 %1 = landingpad { i8*, i32 }
162 br label %finally.catchall
164 finally.catchall: ; preds = %lpad33, %lpad
165 %ex.2 = phi i8* [ %ex.1, %lpad2 ], [ null, %lpad ]
168 )invalid", Err
, Ctx
));
171 Err
.print("unit", errs());
175 Function
*Func
= M
->getFunction("foo");
176 EXPECT_FALSE(verifyFunction(*Func
, &errs()));
178 SmallVector
<BasicBlock
*, 2> ExtractedBlocks
{
179 getBlockByName(Func
, "catch"),
180 getBlockByName(Func
, "invoke.cont2"),
181 getBlockByName(Func
, "invoke.cont3"),
182 getBlockByName(Func
, "lpad2")
185 CodeExtractor
CE(ExtractedBlocks
);
186 EXPECT_TRUE(CE
.isEligible());
188 Function
*Outlined
= CE
.extractCodeRegion();
189 EXPECT_TRUE(Outlined
);
190 EXPECT_FALSE(verifyFunction(*Outlined
, &errs()));
191 EXPECT_FALSE(verifyFunction(*Func
, &errs()));
194 TEST(CodeExtractor
, StoreOutputInvokeResultInExitStub
) {
197 std::unique_ptr
<Module
> M(parseAssemblyString(R
"invalid(
200 define i32 @foo() personality i8* null {
202 %0 = invoke i32 @bar() to label %exit unwind label %lpad
208 %1 = landingpad { i8*, i32 }
210 resume { i8*, i32 } %1
215 Function
*Func
= M
->getFunction("foo");
216 SmallVector
<BasicBlock
*, 1> Blocks
{ getBlockByName(Func
, "entry"),
217 getBlockByName(Func
, "lpad") };
219 CodeExtractor
CE(Blocks
);
220 EXPECT_TRUE(CE
.isEligible());
222 Function
*Outlined
= CE
.extractCodeRegion();
223 EXPECT_TRUE(Outlined
);
224 EXPECT_FALSE(verifyFunction(*Outlined
));
225 EXPECT_FALSE(verifyFunction(*Func
));
228 } // end anonymous namespace