18267b333SNico Weber //===- CodeExtractor.cpp - Unit tests for CodeExtractor -------------------===//
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/CodeExtractor.h"
108267b333SNico Weber #include "llvm/AsmParser/Parser.h"
1150afaa9dSAditya Kumar #include "llvm/Analysis/AssumptionCache.h"
128267b333SNico Weber #include "llvm/IR/BasicBlock.h"
138267b333SNico Weber #include "llvm/IR/Dominators.h"
14d129569eSVedant Kumar #include "llvm/IR/Instructions.h"
158267b333SNico Weber #include "llvm/IR/LLVMContext.h"
168267b333SNico Weber #include "llvm/IR/Module.h"
178267b333SNico Weber #include "llvm/IR/Verifier.h"
188267b333SNico Weber #include "llvm/IRReader/IRReader.h"
198267b333SNico Weber #include "llvm/Support/SourceMgr.h"
208267b333SNico Weber #include "gtest/gtest.h"
218267b333SNico Weber 
228267b333SNico Weber using namespace llvm;
238267b333SNico Weber 
248267b333SNico Weber namespace {
25d129569eSVedant Kumar BasicBlock *getBlockByName(Function *F, StringRef name) {
26d129569eSVedant Kumar   for (auto &BB : *F)
27d129569eSVedant Kumar     if (BB.getName() == name)
28d129569eSVedant Kumar       return &BB;
29d129569eSVedant Kumar   return nullptr;
30d129569eSVedant Kumar }
31d129569eSVedant Kumar 
32d129569eSVedant Kumar TEST(CodeExtractor, ExitStub) {
338267b333SNico Weber   LLVMContext Ctx;
348267b333SNico Weber   SMDiagnostic Err;
358267b333SNico Weber   std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
368267b333SNico Weber     define i32 @foo(i32 %x, i32 %y, i32 %z) {
378267b333SNico Weber     header:
388267b333SNico Weber       %0 = icmp ugt i32 %x, %y
398267b333SNico Weber       br i1 %0, label %body1, label %body2
408267b333SNico Weber 
418267b333SNico Weber     body1:
428267b333SNico Weber       %1 = add i32 %z, 2
438267b333SNico Weber       br label %notExtracted
448267b333SNico Weber 
458267b333SNico Weber     body2:
468267b333SNico Weber       %2 = mul i32 %z, 7
478267b333SNico Weber       br label %notExtracted
488267b333SNico Weber 
498267b333SNico Weber     notExtracted:
508267b333SNico Weber       %3 = phi i32 [ %1, %body1 ], [ %2, %body2 ]
518267b333SNico Weber       %4 = add i32 %3, %x
528267b333SNico Weber       ret i32 %4
538267b333SNico Weber     }
548267b333SNico Weber   )invalid",
558267b333SNico Weber                                                 Err, Ctx));
568267b333SNico Weber 
578267b333SNico Weber   Function *Func = M->getFunction("foo");
58d129569eSVedant Kumar   SmallVector<BasicBlock *, 3> Candidates{ getBlockByName(Func, "header"),
59d129569eSVedant Kumar                                            getBlockByName(Func, "body1"),
60d129569eSVedant Kumar                                            getBlockByName(Func, "body2") };
618267b333SNico Weber 
620e5dd512SVedant Kumar   CodeExtractor CE(Candidates);
638267b333SNico Weber   EXPECT_TRUE(CE.isEligible());
648267b333SNico Weber 
659852699dSVedant Kumar   CodeExtractorAnalysisCache CEAC(*Func);
669852699dSVedant Kumar   Function *Outlined = CE.extractCodeRegion(CEAC);
678267b333SNico Weber   EXPECT_TRUE(Outlined);
68d129569eSVedant Kumar   BasicBlock *Exit = getBlockByName(Func, "notExtracted");
69d129569eSVedant Kumar   BasicBlock *ExitSplit = getBlockByName(Outlined, "notExtracted.split");
70d129569eSVedant Kumar   // Ensure that PHI in exit block has only one incoming value (from code
71d129569eSVedant Kumar   // replacer block).
72d129569eSVedant Kumar   EXPECT_TRUE(Exit && cast<PHINode>(Exit->front()).getNumIncomingValues() == 1);
73d129569eSVedant Kumar   // Ensure that there is a PHI in outlined function with 2 incoming values.
74d129569eSVedant Kumar   EXPECT_TRUE(ExitSplit &&
75d129569eSVedant Kumar               cast<PHINode>(ExitSplit->front()).getNumIncomingValues() == 2);
768267b333SNico Weber   EXPECT_FALSE(verifyFunction(*Outlined));
77d129569eSVedant Kumar   EXPECT_FALSE(verifyFunction(*Func));
78d129569eSVedant Kumar }
79d129569eSVedant Kumar 
809d2c859eSAndrew Litteken TEST(CodeExtractor, InputOutputMonitoring) {
819d2c859eSAndrew Litteken   LLVMContext Ctx;
829d2c859eSAndrew Litteken   SMDiagnostic Err;
839d2c859eSAndrew Litteken   std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
849d2c859eSAndrew Litteken     define i32 @foo(i32 %x, i32 %y, i32 %z) {
859d2c859eSAndrew Litteken     header:
869d2c859eSAndrew Litteken       %0 = icmp ugt i32 %x, %y
879d2c859eSAndrew Litteken       br i1 %0, label %body1, label %body2
889d2c859eSAndrew Litteken 
899d2c859eSAndrew Litteken     body1:
909d2c859eSAndrew Litteken       %1 = add i32 %z, 2
919d2c859eSAndrew Litteken       br label %notExtracted
929d2c859eSAndrew Litteken 
939d2c859eSAndrew Litteken     body2:
949d2c859eSAndrew Litteken       %2 = mul i32 %z, 7
959d2c859eSAndrew Litteken       br label %notExtracted
969d2c859eSAndrew Litteken 
979d2c859eSAndrew Litteken     notExtracted:
989d2c859eSAndrew Litteken       %3 = phi i32 [ %1, %body1 ], [ %2, %body2 ]
999d2c859eSAndrew Litteken       %4 = add i32 %3, %x
1009d2c859eSAndrew Litteken       ret i32 %4
1019d2c859eSAndrew Litteken     }
1029d2c859eSAndrew Litteken   )invalid",
1039d2c859eSAndrew Litteken                                                 Err, Ctx));
1049d2c859eSAndrew Litteken 
1059d2c859eSAndrew Litteken   Function *Func = M->getFunction("foo");
1069d2c859eSAndrew Litteken   SmallVector<BasicBlock *, 3> Candidates{getBlockByName(Func, "header"),
1079d2c859eSAndrew Litteken                                           getBlockByName(Func, "body1"),
1089d2c859eSAndrew Litteken                                           getBlockByName(Func, "body2")};
1099d2c859eSAndrew Litteken 
1109d2c859eSAndrew Litteken   CodeExtractor CE(Candidates);
1119d2c859eSAndrew Litteken   EXPECT_TRUE(CE.isEligible());
1129d2c859eSAndrew Litteken 
1139d2c859eSAndrew Litteken   CodeExtractorAnalysisCache CEAC(*Func);
1149d2c859eSAndrew Litteken   SetVector<Value *> Inputs, Outputs;
1159d2c859eSAndrew Litteken   Function *Outlined = CE.extractCodeRegion(CEAC, Inputs, Outputs);
1169d2c859eSAndrew Litteken   EXPECT_TRUE(Outlined);
1179d2c859eSAndrew Litteken 
1189d2c859eSAndrew Litteken   EXPECT_EQ(Inputs.size(), 3u);
1199d2c859eSAndrew Litteken   EXPECT_EQ(Inputs[0], Func->getArg(2));
1209d2c859eSAndrew Litteken   EXPECT_EQ(Inputs[1], Func->getArg(0));
1219d2c859eSAndrew Litteken   EXPECT_EQ(Inputs[2], Func->getArg(1));
1229d2c859eSAndrew Litteken   EXPECT_EQ(Outputs.size(), 1u);
1239d2c859eSAndrew Litteken   StoreInst *SI = cast<StoreInst>(Outlined->getArg(3)->user_back());
1249d2c859eSAndrew Litteken   Value *OutputVal = SI->getValueOperand();
1259d2c859eSAndrew Litteken   EXPECT_EQ(Outputs[0], OutputVal);
1269d2c859eSAndrew Litteken   BasicBlock *Exit = getBlockByName(Func, "notExtracted");
1279d2c859eSAndrew Litteken   BasicBlock *ExitSplit = getBlockByName(Outlined, "notExtracted.split");
1289d2c859eSAndrew Litteken   // Ensure that PHI in exit block has only one incoming value (from code
1299d2c859eSAndrew Litteken   // replacer block).
1309d2c859eSAndrew Litteken   EXPECT_TRUE(Exit && cast<PHINode>(Exit->front()).getNumIncomingValues() == 1);
1319d2c859eSAndrew Litteken   // Ensure that there is a PHI in outlined function with 2 incoming values.
1329d2c859eSAndrew Litteken   EXPECT_TRUE(ExitSplit &&
1339d2c859eSAndrew Litteken               cast<PHINode>(ExitSplit->front()).getNumIncomingValues() == 2);
1349d2c859eSAndrew Litteken   EXPECT_FALSE(verifyFunction(*Outlined));
1359d2c859eSAndrew Litteken   EXPECT_FALSE(verifyFunction(*Func));
1369d2c859eSAndrew Litteken }
1379d2c859eSAndrew Litteken 
138*144cd22bSAndrew Litteken TEST(CodeExtractor, ExitBlockOrderingPhis) {
139*144cd22bSAndrew Litteken   LLVMContext Ctx;
140*144cd22bSAndrew Litteken   SMDiagnostic Err;
141*144cd22bSAndrew Litteken   std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
142*144cd22bSAndrew Litteken     define void @foo(i32 %a, i32 %b) {
143*144cd22bSAndrew Litteken     entry:
144*144cd22bSAndrew Litteken       %0 = alloca i32, align 4
145*144cd22bSAndrew Litteken       br label %test0
146*144cd22bSAndrew Litteken     test0:
147*144cd22bSAndrew Litteken       %c = load i32, i32* %0, align 4
148*144cd22bSAndrew Litteken       br label %test1
149*144cd22bSAndrew Litteken     test1:
150*144cd22bSAndrew Litteken       %e = load i32, i32* %0, align 4
151*144cd22bSAndrew Litteken       br i1 true, label %first, label %test
152*144cd22bSAndrew Litteken     test:
153*144cd22bSAndrew Litteken       %d = load i32, i32* %0, align 4
154*144cd22bSAndrew Litteken       br i1 true, label %first, label %next
155*144cd22bSAndrew Litteken     first:
156*144cd22bSAndrew Litteken       %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
157*144cd22bSAndrew Litteken       ret void
158*144cd22bSAndrew Litteken     next:
159*144cd22bSAndrew Litteken       %2 = add i32 %d, 1
160*144cd22bSAndrew Litteken       %3 = add i32 %e, 1
161*144cd22bSAndrew Litteken       ret void
162*144cd22bSAndrew Litteken     }
163*144cd22bSAndrew Litteken   )invalid",
164*144cd22bSAndrew Litteken                                                 Err, Ctx));
165*144cd22bSAndrew Litteken   Function *Func = M->getFunction("foo");
166*144cd22bSAndrew Litteken   SmallVector<BasicBlock *, 3> Candidates{ getBlockByName(Func, "test0"),
167*144cd22bSAndrew Litteken                                            getBlockByName(Func, "test1"),
168*144cd22bSAndrew Litteken                                            getBlockByName(Func, "test") };
169*144cd22bSAndrew Litteken 
170*144cd22bSAndrew Litteken   CodeExtractor CE(Candidates);
171*144cd22bSAndrew Litteken   EXPECT_TRUE(CE.isEligible());
172*144cd22bSAndrew Litteken 
173*144cd22bSAndrew Litteken   CodeExtractorAnalysisCache CEAC(*Func);
174*144cd22bSAndrew Litteken   Function *Outlined = CE.extractCodeRegion(CEAC);
175*144cd22bSAndrew Litteken   EXPECT_TRUE(Outlined);
176*144cd22bSAndrew Litteken 
177*144cd22bSAndrew Litteken   BasicBlock *FirstExitStub = getBlockByName(Outlined, "first.exitStub");
178*144cd22bSAndrew Litteken   BasicBlock *NextExitStub = getBlockByName(Outlined, "next.exitStub");
179*144cd22bSAndrew Litteken 
180*144cd22bSAndrew Litteken   Instruction *FirstTerm = FirstExitStub->getTerminator();
181*144cd22bSAndrew Litteken   ReturnInst *FirstReturn = dyn_cast<ReturnInst>(FirstTerm);
182*144cd22bSAndrew Litteken   EXPECT_TRUE(FirstReturn);
183*144cd22bSAndrew Litteken   ConstantInt *CIFirst = dyn_cast<ConstantInt>(FirstReturn->getReturnValue());
184*144cd22bSAndrew Litteken   EXPECT_TRUE(CIFirst->getLimitedValue() == 1u);
185*144cd22bSAndrew Litteken 
186*144cd22bSAndrew Litteken   Instruction *NextTerm = NextExitStub->getTerminator();
187*144cd22bSAndrew Litteken   ReturnInst *NextReturn = dyn_cast<ReturnInst>(NextTerm);
188*144cd22bSAndrew Litteken   EXPECT_TRUE(NextReturn);
189*144cd22bSAndrew Litteken   ConstantInt *CINext = dyn_cast<ConstantInt>(NextReturn->getReturnValue());
190*144cd22bSAndrew Litteken   EXPECT_TRUE(CINext->getLimitedValue() == 0u);
191*144cd22bSAndrew Litteken 
192*144cd22bSAndrew Litteken   EXPECT_FALSE(verifyFunction(*Outlined));
193*144cd22bSAndrew Litteken   EXPECT_FALSE(verifyFunction(*Func));
194*144cd22bSAndrew Litteken }
195*144cd22bSAndrew Litteken 
196*144cd22bSAndrew Litteken TEST(CodeExtractor, ExitBlockOrdering) {
197*144cd22bSAndrew Litteken   LLVMContext Ctx;
198*144cd22bSAndrew Litteken   SMDiagnostic Err;
199*144cd22bSAndrew Litteken   std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
200*144cd22bSAndrew Litteken     define void @foo(i32 %a, i32 %b) {
201*144cd22bSAndrew Litteken     entry:
202*144cd22bSAndrew Litteken       %0 = alloca i32, align 4
203*144cd22bSAndrew Litteken       br label %test0
204*144cd22bSAndrew Litteken     test0:
205*144cd22bSAndrew Litteken       %c = load i32, i32* %0, align 4
206*144cd22bSAndrew Litteken       br label %test1
207*144cd22bSAndrew Litteken     test1:
208*144cd22bSAndrew Litteken       %e = load i32, i32* %0, align 4
209*144cd22bSAndrew Litteken       br i1 true, label %first, label %test
210*144cd22bSAndrew Litteken     test:
211*144cd22bSAndrew Litteken       %d = load i32, i32* %0, align 4
212*144cd22bSAndrew Litteken       br i1 true, label %first, label %next
213*144cd22bSAndrew Litteken     first:
214*144cd22bSAndrew Litteken       ret void
215*144cd22bSAndrew Litteken     next:
216*144cd22bSAndrew Litteken       %1 = add i32 %d, 1
217*144cd22bSAndrew Litteken       %2 = add i32 %e, 1
218*144cd22bSAndrew Litteken       ret void
219*144cd22bSAndrew Litteken     }
220*144cd22bSAndrew Litteken   )invalid",
221*144cd22bSAndrew Litteken                                                 Err, Ctx));
222*144cd22bSAndrew Litteken   Function *Func = M->getFunction("foo");
223*144cd22bSAndrew Litteken   SmallVector<BasicBlock *, 3> Candidates{ getBlockByName(Func, "test0"),
224*144cd22bSAndrew Litteken                                            getBlockByName(Func, "test1"),
225*144cd22bSAndrew Litteken                                            getBlockByName(Func, "test") };
226*144cd22bSAndrew Litteken 
227*144cd22bSAndrew Litteken   CodeExtractor CE(Candidates);
228*144cd22bSAndrew Litteken   EXPECT_TRUE(CE.isEligible());
229*144cd22bSAndrew Litteken 
230*144cd22bSAndrew Litteken   CodeExtractorAnalysisCache CEAC(*Func);
231*144cd22bSAndrew Litteken   Function *Outlined = CE.extractCodeRegion(CEAC);
232*144cd22bSAndrew Litteken   EXPECT_TRUE(Outlined);
233*144cd22bSAndrew Litteken 
234*144cd22bSAndrew Litteken   BasicBlock *FirstExitStub = getBlockByName(Outlined, "first.exitStub");
235*144cd22bSAndrew Litteken   BasicBlock *NextExitStub = getBlockByName(Outlined, "next.exitStub");
236*144cd22bSAndrew Litteken 
237*144cd22bSAndrew Litteken   Instruction *FirstTerm = FirstExitStub->getTerminator();
238*144cd22bSAndrew Litteken   ReturnInst *FirstReturn = dyn_cast<ReturnInst>(FirstTerm);
239*144cd22bSAndrew Litteken   EXPECT_TRUE(FirstReturn);
240*144cd22bSAndrew Litteken   ConstantInt *CIFirst = dyn_cast<ConstantInt>(FirstReturn->getReturnValue());
241*144cd22bSAndrew Litteken   EXPECT_TRUE(CIFirst->getLimitedValue() == 1u);
242*144cd22bSAndrew Litteken 
243*144cd22bSAndrew Litteken   Instruction *NextTerm = NextExitStub->getTerminator();
244*144cd22bSAndrew Litteken   ReturnInst *NextReturn = dyn_cast<ReturnInst>(NextTerm);
245*144cd22bSAndrew Litteken   EXPECT_TRUE(NextReturn);
246*144cd22bSAndrew Litteken   ConstantInt *CINext = dyn_cast<ConstantInt>(NextReturn->getReturnValue());
247*144cd22bSAndrew Litteken   EXPECT_TRUE(CINext->getLimitedValue() == 0u);
248*144cd22bSAndrew Litteken 
249*144cd22bSAndrew Litteken   EXPECT_FALSE(verifyFunction(*Outlined));
250*144cd22bSAndrew Litteken   EXPECT_FALSE(verifyFunction(*Func));
251*144cd22bSAndrew Litteken }
252*144cd22bSAndrew Litteken 
253d129569eSVedant Kumar TEST(CodeExtractor, ExitPHIOnePredFromRegion) {
254d129569eSVedant Kumar   LLVMContext Ctx;
255d129569eSVedant Kumar   SMDiagnostic Err;
256d129569eSVedant Kumar   std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
257d129569eSVedant Kumar     define i32 @foo() {
258d129569eSVedant Kumar     header:
259d129569eSVedant Kumar       br i1 undef, label %extracted1, label %pred
260d129569eSVedant Kumar 
261d129569eSVedant Kumar     pred:
262d129569eSVedant Kumar       br i1 undef, label %exit1, label %exit2
263d129569eSVedant Kumar 
264d129569eSVedant Kumar     extracted1:
265d129569eSVedant Kumar       br i1 undef, label %extracted2, label %exit1
266d129569eSVedant Kumar 
267d129569eSVedant Kumar     extracted2:
268d129569eSVedant Kumar       br label %exit2
269d129569eSVedant Kumar 
270d129569eSVedant Kumar     exit1:
271d129569eSVedant Kumar       %0 = phi i32 [ 1, %extracted1 ], [ 2, %pred ]
272d129569eSVedant Kumar       ret i32 %0
273d129569eSVedant Kumar 
274d129569eSVedant Kumar     exit2:
275d129569eSVedant Kumar       %1 = phi i32 [ 3, %extracted2 ], [ 4, %pred ]
276d129569eSVedant Kumar       ret i32 %1
277d129569eSVedant Kumar     }
278d129569eSVedant Kumar   )invalid", Err, Ctx));
279d129569eSVedant Kumar 
280d129569eSVedant Kumar   Function *Func = M->getFunction("foo");
281d129569eSVedant Kumar   SmallVector<BasicBlock *, 2> ExtractedBlocks{
282d129569eSVedant Kumar     getBlockByName(Func, "extracted1"),
283d129569eSVedant Kumar     getBlockByName(Func, "extracted2")
284d129569eSVedant Kumar   };
285d129569eSVedant Kumar 
2860e5dd512SVedant Kumar   CodeExtractor CE(ExtractedBlocks);
287d129569eSVedant Kumar   EXPECT_TRUE(CE.isEligible());
288d129569eSVedant Kumar 
2899852699dSVedant Kumar   CodeExtractorAnalysisCache CEAC(*Func);
2909852699dSVedant Kumar   Function *Outlined = CE.extractCodeRegion(CEAC);
291d129569eSVedant Kumar   EXPECT_TRUE(Outlined);
292d129569eSVedant Kumar   BasicBlock *Exit1 = getBlockByName(Func, "exit1");
293d129569eSVedant Kumar   BasicBlock *Exit2 = getBlockByName(Func, "exit2");
294d129569eSVedant Kumar   // Ensure that PHIs in exits are not splitted (since that they have only one
295d129569eSVedant Kumar   // incoming value from extracted region).
296d129569eSVedant Kumar   EXPECT_TRUE(Exit1 &&
297d129569eSVedant Kumar           cast<PHINode>(Exit1->front()).getNumIncomingValues() == 2);
298d129569eSVedant Kumar   EXPECT_TRUE(Exit2 &&
299d129569eSVedant Kumar           cast<PHINode>(Exit2->front()).getNumIncomingValues() == 2);
300d129569eSVedant Kumar   EXPECT_FALSE(verifyFunction(*Outlined));
301d129569eSVedant Kumar   EXPECT_FALSE(verifyFunction(*Func));
3028267b333SNico Weber }
303b2a6f8e5SVedant Kumar 
304b2a6f8e5SVedant Kumar TEST(CodeExtractor, StoreOutputInvokeResultAfterEHPad) {
305b2a6f8e5SVedant Kumar   LLVMContext Ctx;
306b2a6f8e5SVedant Kumar   SMDiagnostic Err;
307b2a6f8e5SVedant Kumar   std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
308b2a6f8e5SVedant Kumar     declare i8 @hoge()
309b2a6f8e5SVedant Kumar 
310b2a6f8e5SVedant Kumar     define i32 @foo() personality i8* null {
311b2a6f8e5SVedant Kumar       entry:
312b2a6f8e5SVedant Kumar         %call = invoke i8 @hoge()
313b2a6f8e5SVedant Kumar                 to label %invoke.cont unwind label %lpad
314b2a6f8e5SVedant Kumar 
315b2a6f8e5SVedant Kumar       invoke.cont:                                      ; preds = %entry
316b2a6f8e5SVedant Kumar         unreachable
317b2a6f8e5SVedant Kumar 
318b2a6f8e5SVedant Kumar       lpad:                                             ; preds = %entry
319b2a6f8e5SVedant Kumar         %0 = landingpad { i8*, i32 }
320b2a6f8e5SVedant Kumar                 catch i8* null
321b2a6f8e5SVedant Kumar         br i1 undef, label %catch, label %finally.catchall
322b2a6f8e5SVedant Kumar 
323b2a6f8e5SVedant Kumar       catch:                                            ; preds = %lpad
324b2a6f8e5SVedant Kumar         %call2 = invoke i8 @hoge()
325b2a6f8e5SVedant Kumar                 to label %invoke.cont2 unwind label %lpad2
326b2a6f8e5SVedant Kumar 
327b2a6f8e5SVedant Kumar       invoke.cont2:                                    ; preds = %catch
328b2a6f8e5SVedant Kumar         %call3 = invoke i8 @hoge()
329b2a6f8e5SVedant Kumar                 to label %invoke.cont3 unwind label %lpad2
330b2a6f8e5SVedant Kumar 
331b2a6f8e5SVedant Kumar       invoke.cont3:                                    ; preds = %invoke.cont2
332b2a6f8e5SVedant Kumar         unreachable
333b2a6f8e5SVedant Kumar 
334b2a6f8e5SVedant Kumar       lpad2:                                           ; preds = %invoke.cont2, %catch
335b2a6f8e5SVedant Kumar         %ex.1 = phi i8* [ undef, %invoke.cont2 ], [ null, %catch ]
336b2a6f8e5SVedant Kumar         %1 = landingpad { i8*, i32 }
337b2a6f8e5SVedant Kumar                 catch i8* null
338b2a6f8e5SVedant Kumar         br label %finally.catchall
339b2a6f8e5SVedant Kumar 
340b2a6f8e5SVedant Kumar       finally.catchall:                                 ; preds = %lpad33, %lpad
341b2a6f8e5SVedant Kumar         %ex.2 = phi i8* [ %ex.1, %lpad2 ], [ null, %lpad ]
342b2a6f8e5SVedant Kumar         unreachable
343b2a6f8e5SVedant Kumar     }
344b2a6f8e5SVedant Kumar   )invalid", Err, Ctx));
345b2a6f8e5SVedant Kumar 
346b2a6f8e5SVedant Kumar 	if (!M) {
347b2a6f8e5SVedant Kumar     Err.print("unit", errs());
348b2a6f8e5SVedant Kumar     exit(1);
349b2a6f8e5SVedant Kumar   }
350b2a6f8e5SVedant Kumar 
351b2a6f8e5SVedant Kumar   Function *Func = M->getFunction("foo");
352b2a6f8e5SVedant Kumar   EXPECT_FALSE(verifyFunction(*Func, &errs()));
353b2a6f8e5SVedant Kumar 
354b2a6f8e5SVedant Kumar   SmallVector<BasicBlock *, 2> ExtractedBlocks{
355b2a6f8e5SVedant Kumar     getBlockByName(Func, "catch"),
356b2a6f8e5SVedant Kumar     getBlockByName(Func, "invoke.cont2"),
357b2a6f8e5SVedant Kumar     getBlockByName(Func, "invoke.cont3"),
358b2a6f8e5SVedant Kumar     getBlockByName(Func, "lpad2")
359b2a6f8e5SVedant Kumar   };
360b2a6f8e5SVedant Kumar 
3610e5dd512SVedant Kumar   CodeExtractor CE(ExtractedBlocks);
362b2a6f8e5SVedant Kumar   EXPECT_TRUE(CE.isEligible());
363b2a6f8e5SVedant Kumar 
3649852699dSVedant Kumar   CodeExtractorAnalysisCache CEAC(*Func);
3659852699dSVedant Kumar   Function *Outlined = CE.extractCodeRegion(CEAC);
366b2a6f8e5SVedant Kumar   EXPECT_TRUE(Outlined);
367b2a6f8e5SVedant Kumar   EXPECT_FALSE(verifyFunction(*Outlined, &errs()));
368b2a6f8e5SVedant Kumar   EXPECT_FALSE(verifyFunction(*Func, &errs()));
369b2a6f8e5SVedant Kumar }
370b2a6f8e5SVedant Kumar 
3710e5dd512SVedant Kumar TEST(CodeExtractor, StoreOutputInvokeResultInExitStub) {
3720e5dd512SVedant Kumar   LLVMContext Ctx;
3730e5dd512SVedant Kumar   SMDiagnostic Err;
3740e5dd512SVedant Kumar   std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
3750e5dd512SVedant Kumar     declare i32 @bar()
3760e5dd512SVedant Kumar 
3770e5dd512SVedant Kumar     define i32 @foo() personality i8* null {
3780e5dd512SVedant Kumar     entry:
3790e5dd512SVedant Kumar       %0 = invoke i32 @bar() to label %exit unwind label %lpad
3800e5dd512SVedant Kumar 
3810e5dd512SVedant Kumar     exit:
3820e5dd512SVedant Kumar       ret i32 %0
3830e5dd512SVedant Kumar 
3840e5dd512SVedant Kumar     lpad:
3850e5dd512SVedant Kumar       %1 = landingpad { i8*, i32 }
3860e5dd512SVedant Kumar               cleanup
3870e5dd512SVedant Kumar       resume { i8*, i32 } %1
3880e5dd512SVedant Kumar     }
3890e5dd512SVedant Kumar   )invalid",
3900e5dd512SVedant Kumar                                                 Err, Ctx));
3910e5dd512SVedant Kumar 
3920e5dd512SVedant Kumar   Function *Func = M->getFunction("foo");
3930e5dd512SVedant Kumar   SmallVector<BasicBlock *, 1> Blocks{ getBlockByName(Func, "entry"),
3940e5dd512SVedant Kumar                                        getBlockByName(Func, "lpad") };
3950e5dd512SVedant Kumar 
3960e5dd512SVedant Kumar   CodeExtractor CE(Blocks);
3970e5dd512SVedant Kumar   EXPECT_TRUE(CE.isEligible());
3980e5dd512SVedant Kumar 
3999852699dSVedant Kumar   CodeExtractorAnalysisCache CEAC(*Func);
4009852699dSVedant Kumar   Function *Outlined = CE.extractCodeRegion(CEAC);
4010e5dd512SVedant Kumar   EXPECT_TRUE(Outlined);
4020e5dd512SVedant Kumar   EXPECT_FALSE(verifyFunction(*Outlined));
4030e5dd512SVedant Kumar   EXPECT_FALSE(verifyFunction(*Func));
4040e5dd512SVedant Kumar }
4050e5dd512SVedant Kumar 
40650afaa9dSAditya Kumar TEST(CodeExtractor, ExtractAndInvalidateAssumptionCache) {
40750afaa9dSAditya Kumar   LLVMContext Ctx;
40850afaa9dSAditya Kumar   SMDiagnostic Err;
40950afaa9dSAditya Kumar   std::unique_ptr<Module> M(parseAssemblyString(R"ir(
41050afaa9dSAditya Kumar         target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
41150afaa9dSAditya Kumar         target triple = "aarch64"
41250afaa9dSAditya Kumar 
41350afaa9dSAditya Kumar         %b = type { i64 }
41450afaa9dSAditya Kumar         declare void @g(i8*)
41550afaa9dSAditya Kumar 
41650afaa9dSAditya Kumar         declare void @llvm.assume(i1) #0
41750afaa9dSAditya Kumar 
41850afaa9dSAditya Kumar         define void @test() {
41950afaa9dSAditya Kumar         entry:
42050afaa9dSAditya Kumar           br label %label
42150afaa9dSAditya Kumar 
42250afaa9dSAditya Kumar         label:
42350afaa9dSAditya Kumar           %0 = load %b*, %b** inttoptr (i64 8 to %b**), align 8
42450afaa9dSAditya Kumar           %1 = getelementptr inbounds %b, %b* %0, i64 undef, i32 0
42550afaa9dSAditya Kumar           %2 = load i64, i64* %1, align 8
42650afaa9dSAditya Kumar           %3 = icmp ugt i64 %2, 1
42750afaa9dSAditya Kumar           br i1 %3, label %if.then, label %if.else
42850afaa9dSAditya Kumar 
42950afaa9dSAditya Kumar         if.then:
43050afaa9dSAditya Kumar           unreachable
43150afaa9dSAditya Kumar 
43250afaa9dSAditya Kumar         if.else:
43350afaa9dSAditya Kumar           call void @g(i8* undef)
43450afaa9dSAditya Kumar           store i64 undef, i64* null, align 536870912
43550afaa9dSAditya Kumar           %4 = icmp eq i64 %2, 0
43650afaa9dSAditya Kumar           call void @llvm.assume(i1 %4)
43750afaa9dSAditya Kumar           unreachable
43850afaa9dSAditya Kumar         }
43950afaa9dSAditya Kumar 
44050afaa9dSAditya Kumar         attributes #0 = { nounwind willreturn }
44150afaa9dSAditya Kumar   )ir",
44250afaa9dSAditya Kumar                                                 Err, Ctx));
44350afaa9dSAditya Kumar 
44450afaa9dSAditya Kumar   assert(M && "Could not parse module?");
44550afaa9dSAditya Kumar   Function *Func = M->getFunction("test");
44650afaa9dSAditya Kumar   SmallVector<BasicBlock *, 1> Blocks{ getBlockByName(Func, "if.else") };
44750afaa9dSAditya Kumar   AssumptionCache AC(*Func);
44850afaa9dSAditya Kumar   CodeExtractor CE(Blocks, nullptr, false, nullptr, nullptr, &AC);
44950afaa9dSAditya Kumar   EXPECT_TRUE(CE.isEligible());
45050afaa9dSAditya Kumar 
4519852699dSVedant Kumar   CodeExtractorAnalysisCache CEAC(*Func);
4529852699dSVedant Kumar   Function *Outlined = CE.extractCodeRegion(CEAC);
45350afaa9dSAditya Kumar   EXPECT_TRUE(Outlined);
45450afaa9dSAditya Kumar   EXPECT_FALSE(verifyFunction(*Outlined));
45550afaa9dSAditya Kumar   EXPECT_FALSE(verifyFunction(*Func));
4568359511cSVedant Kumar   EXPECT_FALSE(CE.verifyAssumptionCache(*Func, *Outlined, &AC));
45750afaa9dSAditya Kumar }
458700d2417SGiorgis Georgakoudis 
459700d2417SGiorgis Georgakoudis TEST(CodeExtractor, RemoveBitcastUsesFromOuterLifetimeMarkers) {
460700d2417SGiorgis Georgakoudis   LLVMContext Ctx;
461700d2417SGiorgis Georgakoudis   SMDiagnostic Err;
462700d2417SGiorgis Georgakoudis   std::unique_ptr<Module> M(parseAssemblyString(R"ir(
463700d2417SGiorgis Georgakoudis     target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
464700d2417SGiorgis Georgakoudis     target triple = "x86_64-unknown-linux-gnu"
465700d2417SGiorgis Georgakoudis 
466700d2417SGiorgis Georgakoudis     declare void @use(i32*)
467700d2417SGiorgis Georgakoudis     declare void @llvm.lifetime.start.p0i8(i64, i8*)
468700d2417SGiorgis Georgakoudis     declare void @llvm.lifetime.end.p0i8(i64, i8*)
469700d2417SGiorgis Georgakoudis 
470700d2417SGiorgis Georgakoudis     define void @foo() {
471700d2417SGiorgis Georgakoudis     entry:
472700d2417SGiorgis Georgakoudis       %0 = alloca i32
473700d2417SGiorgis Georgakoudis       br label %extract
474700d2417SGiorgis Georgakoudis 
475700d2417SGiorgis Georgakoudis     extract:
476700d2417SGiorgis Georgakoudis       %1 = bitcast i32* %0 to i8*
477700d2417SGiorgis Georgakoudis       call void @llvm.lifetime.start.p0i8(i64 4, i8* %1)
478700d2417SGiorgis Georgakoudis       call void @use(i32* %0)
479700d2417SGiorgis Georgakoudis       br label %exit
480700d2417SGiorgis Georgakoudis 
481700d2417SGiorgis Georgakoudis     exit:
482700d2417SGiorgis Georgakoudis       call void @use(i32* %0)
483700d2417SGiorgis Georgakoudis       call void @llvm.lifetime.end.p0i8(i64 4, i8* %1)
484700d2417SGiorgis Georgakoudis       ret void
485700d2417SGiorgis Georgakoudis     }
486700d2417SGiorgis Georgakoudis   )ir",
487700d2417SGiorgis Georgakoudis                                                 Err, Ctx));
488700d2417SGiorgis Georgakoudis 
489700d2417SGiorgis Georgakoudis   Function *Func = M->getFunction("foo");
490700d2417SGiorgis Georgakoudis   SmallVector<BasicBlock *, 1> Blocks{getBlockByName(Func, "extract")};
491700d2417SGiorgis Georgakoudis 
492700d2417SGiorgis Georgakoudis   CodeExtractor CE(Blocks);
493700d2417SGiorgis Georgakoudis   EXPECT_TRUE(CE.isEligible());
494700d2417SGiorgis Georgakoudis 
495700d2417SGiorgis Georgakoudis   CodeExtractorAnalysisCache CEAC(*Func);
496700d2417SGiorgis Georgakoudis   SetVector<Value *> Inputs, Outputs, SinkingCands, HoistingCands;
497700d2417SGiorgis Georgakoudis   BasicBlock *CommonExit = nullptr;
498700d2417SGiorgis Georgakoudis   CE.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
499700d2417SGiorgis Georgakoudis   CE.findInputsOutputs(Inputs, Outputs, SinkingCands);
500700d2417SGiorgis Georgakoudis   EXPECT_EQ(Outputs.size(), 0U);
501700d2417SGiorgis Georgakoudis 
502700d2417SGiorgis Georgakoudis   Function *Outlined = CE.extractCodeRegion(CEAC);
503700d2417SGiorgis Georgakoudis   EXPECT_TRUE(Outlined);
504700d2417SGiorgis Georgakoudis   EXPECT_FALSE(verifyFunction(*Outlined));
505700d2417SGiorgis Georgakoudis   EXPECT_FALSE(verifyFunction(*Func));
506700d2417SGiorgis Georgakoudis }
5078267b333SNico Weber } // end anonymous namespace
508