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"
13*c1b96725SBill Wendling #include "llvm/IR/Constants.h"
148267b333SNico Weber #include "llvm/IR/Dominators.h"
15d129569eSVedant Kumar #include "llvm/IR/Instructions.h"
168267b333SNico Weber #include "llvm/IR/LLVMContext.h"
178267b333SNico Weber #include "llvm/IR/Module.h"
188267b333SNico Weber #include "llvm/IR/Verifier.h"
198267b333SNico Weber #include "llvm/IRReader/IRReader.h"
208267b333SNico Weber #include "llvm/Support/SourceMgr.h"
218267b333SNico Weber #include "gtest/gtest.h"
228267b333SNico Weber
238267b333SNico Weber using namespace llvm;
248267b333SNico Weber
258267b333SNico Weber namespace {
getBlockByName(Function * F,StringRef name)26d129569eSVedant Kumar BasicBlock *getBlockByName(Function *F, StringRef name) {
27d129569eSVedant Kumar for (auto &BB : *F)
28d129569eSVedant Kumar if (BB.getName() == name)
29d129569eSVedant Kumar return &BB;
30d129569eSVedant Kumar return nullptr;
31d129569eSVedant Kumar }
32d129569eSVedant Kumar
TEST(CodeExtractor,ExitStub)33d129569eSVedant Kumar TEST(CodeExtractor, ExitStub) {
348267b333SNico Weber LLVMContext Ctx;
358267b333SNico Weber SMDiagnostic Err;
368267b333SNico Weber std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
378267b333SNico Weber define i32 @foo(i32 %x, i32 %y, i32 %z) {
388267b333SNico Weber header:
398267b333SNico Weber %0 = icmp ugt i32 %x, %y
408267b333SNico Weber br i1 %0, label %body1, label %body2
418267b333SNico Weber
428267b333SNico Weber body1:
438267b333SNico Weber %1 = add i32 %z, 2
448267b333SNico Weber br label %notExtracted
458267b333SNico Weber
468267b333SNico Weber body2:
478267b333SNico Weber %2 = mul i32 %z, 7
488267b333SNico Weber br label %notExtracted
498267b333SNico Weber
508267b333SNico Weber notExtracted:
518267b333SNico Weber %3 = phi i32 [ %1, %body1 ], [ %2, %body2 ]
528267b333SNico Weber %4 = add i32 %3, %x
538267b333SNico Weber ret i32 %4
548267b333SNico Weber }
558267b333SNico Weber )invalid",
568267b333SNico Weber Err, Ctx));
578267b333SNico Weber
588267b333SNico Weber Function *Func = M->getFunction("foo");
59d129569eSVedant Kumar SmallVector<BasicBlock *, 3> Candidates{ getBlockByName(Func, "header"),
60d129569eSVedant Kumar getBlockByName(Func, "body1"),
61d129569eSVedant Kumar getBlockByName(Func, "body2") };
628267b333SNico Weber
630e5dd512SVedant Kumar CodeExtractor CE(Candidates);
648267b333SNico Weber EXPECT_TRUE(CE.isEligible());
658267b333SNico Weber
669852699dSVedant Kumar CodeExtractorAnalysisCache CEAC(*Func);
679852699dSVedant Kumar Function *Outlined = CE.extractCodeRegion(CEAC);
688267b333SNico Weber EXPECT_TRUE(Outlined);
69d129569eSVedant Kumar BasicBlock *Exit = getBlockByName(Func, "notExtracted");
70d129569eSVedant Kumar BasicBlock *ExitSplit = getBlockByName(Outlined, "notExtracted.split");
71d129569eSVedant Kumar // Ensure that PHI in exit block has only one incoming value (from code
72d129569eSVedant Kumar // replacer block).
73d129569eSVedant Kumar EXPECT_TRUE(Exit && cast<PHINode>(Exit->front()).getNumIncomingValues() == 1);
74d129569eSVedant Kumar // Ensure that there is a PHI in outlined function with 2 incoming values.
75d129569eSVedant Kumar EXPECT_TRUE(ExitSplit &&
76d129569eSVedant Kumar cast<PHINode>(ExitSplit->front()).getNumIncomingValues() == 2);
778267b333SNico Weber EXPECT_FALSE(verifyFunction(*Outlined));
78d129569eSVedant Kumar EXPECT_FALSE(verifyFunction(*Func));
79d129569eSVedant Kumar }
80d129569eSVedant Kumar
TEST(CodeExtractor,InputOutputMonitoring)819d2c859eSAndrew Litteken TEST(CodeExtractor, InputOutputMonitoring) {
829d2c859eSAndrew Litteken LLVMContext Ctx;
839d2c859eSAndrew Litteken SMDiagnostic Err;
849d2c859eSAndrew Litteken std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
859d2c859eSAndrew Litteken define i32 @foo(i32 %x, i32 %y, i32 %z) {
869d2c859eSAndrew Litteken header:
879d2c859eSAndrew Litteken %0 = icmp ugt i32 %x, %y
889d2c859eSAndrew Litteken br i1 %0, label %body1, label %body2
899d2c859eSAndrew Litteken
909d2c859eSAndrew Litteken body1:
919d2c859eSAndrew Litteken %1 = add i32 %z, 2
929d2c859eSAndrew Litteken br label %notExtracted
939d2c859eSAndrew Litteken
949d2c859eSAndrew Litteken body2:
959d2c859eSAndrew Litteken %2 = mul i32 %z, 7
969d2c859eSAndrew Litteken br label %notExtracted
979d2c859eSAndrew Litteken
989d2c859eSAndrew Litteken notExtracted:
999d2c859eSAndrew Litteken %3 = phi i32 [ %1, %body1 ], [ %2, %body2 ]
1009d2c859eSAndrew Litteken %4 = add i32 %3, %x
1019d2c859eSAndrew Litteken ret i32 %4
1029d2c859eSAndrew Litteken }
1039d2c859eSAndrew Litteken )invalid",
1049d2c859eSAndrew Litteken Err, Ctx));
1059d2c859eSAndrew Litteken
1069d2c859eSAndrew Litteken Function *Func = M->getFunction("foo");
1079d2c859eSAndrew Litteken SmallVector<BasicBlock *, 3> Candidates{getBlockByName(Func, "header"),
1089d2c859eSAndrew Litteken getBlockByName(Func, "body1"),
1099d2c859eSAndrew Litteken getBlockByName(Func, "body2")};
1109d2c859eSAndrew Litteken
1119d2c859eSAndrew Litteken CodeExtractor CE(Candidates);
1129d2c859eSAndrew Litteken EXPECT_TRUE(CE.isEligible());
1139d2c859eSAndrew Litteken
1149d2c859eSAndrew Litteken CodeExtractorAnalysisCache CEAC(*Func);
1159d2c859eSAndrew Litteken SetVector<Value *> Inputs, Outputs;
1169d2c859eSAndrew Litteken Function *Outlined = CE.extractCodeRegion(CEAC, Inputs, Outputs);
1179d2c859eSAndrew Litteken EXPECT_TRUE(Outlined);
1189d2c859eSAndrew Litteken
1199d2c859eSAndrew Litteken EXPECT_EQ(Inputs.size(), 3u);
1209d2c859eSAndrew Litteken EXPECT_EQ(Inputs[0], Func->getArg(2));
1219d2c859eSAndrew Litteken EXPECT_EQ(Inputs[1], Func->getArg(0));
1229d2c859eSAndrew Litteken EXPECT_EQ(Inputs[2], Func->getArg(1));
1239d2c859eSAndrew Litteken EXPECT_EQ(Outputs.size(), 1u);
1249d2c859eSAndrew Litteken StoreInst *SI = cast<StoreInst>(Outlined->getArg(3)->user_back());
1259d2c859eSAndrew Litteken Value *OutputVal = SI->getValueOperand();
1269d2c859eSAndrew Litteken EXPECT_EQ(Outputs[0], OutputVal);
1279d2c859eSAndrew Litteken BasicBlock *Exit = getBlockByName(Func, "notExtracted");
1289d2c859eSAndrew Litteken BasicBlock *ExitSplit = getBlockByName(Outlined, "notExtracted.split");
1299d2c859eSAndrew Litteken // Ensure that PHI in exit block has only one incoming value (from code
1309d2c859eSAndrew Litteken // replacer block).
1319d2c859eSAndrew Litteken EXPECT_TRUE(Exit && cast<PHINode>(Exit->front()).getNumIncomingValues() == 1);
1329d2c859eSAndrew Litteken // Ensure that there is a PHI in outlined function with 2 incoming values.
1339d2c859eSAndrew Litteken EXPECT_TRUE(ExitSplit &&
1349d2c859eSAndrew Litteken cast<PHINode>(ExitSplit->front()).getNumIncomingValues() == 2);
1359d2c859eSAndrew Litteken EXPECT_FALSE(verifyFunction(*Outlined));
1369d2c859eSAndrew Litteken EXPECT_FALSE(verifyFunction(*Func));
1379d2c859eSAndrew Litteken }
1389d2c859eSAndrew Litteken
TEST(CodeExtractor,ExitBlockOrderingPhis)139144cd22bSAndrew Litteken TEST(CodeExtractor, ExitBlockOrderingPhis) {
140144cd22bSAndrew Litteken LLVMContext Ctx;
141144cd22bSAndrew Litteken SMDiagnostic Err;
142144cd22bSAndrew Litteken std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
143144cd22bSAndrew Litteken define void @foo(i32 %a, i32 %b) {
144144cd22bSAndrew Litteken entry:
145144cd22bSAndrew Litteken %0 = alloca i32, align 4
146144cd22bSAndrew Litteken br label %test0
147144cd22bSAndrew Litteken test0:
148144cd22bSAndrew Litteken %c = load i32, i32* %0, align 4
149144cd22bSAndrew Litteken br label %test1
150144cd22bSAndrew Litteken test1:
151144cd22bSAndrew Litteken %e = load i32, i32* %0, align 4
152144cd22bSAndrew Litteken br i1 true, label %first, label %test
153144cd22bSAndrew Litteken test:
154144cd22bSAndrew Litteken %d = load i32, i32* %0, align 4
155144cd22bSAndrew Litteken br i1 true, label %first, label %next
156144cd22bSAndrew Litteken first:
157144cd22bSAndrew Litteken %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
158144cd22bSAndrew Litteken ret void
159144cd22bSAndrew Litteken next:
160144cd22bSAndrew Litteken %2 = add i32 %d, 1
161144cd22bSAndrew Litteken %3 = add i32 %e, 1
162144cd22bSAndrew Litteken ret void
163144cd22bSAndrew Litteken }
164144cd22bSAndrew Litteken )invalid",
165144cd22bSAndrew Litteken Err, Ctx));
166144cd22bSAndrew Litteken Function *Func = M->getFunction("foo");
167144cd22bSAndrew Litteken SmallVector<BasicBlock *, 3> Candidates{ getBlockByName(Func, "test0"),
168144cd22bSAndrew Litteken getBlockByName(Func, "test1"),
169144cd22bSAndrew Litteken getBlockByName(Func, "test") };
170144cd22bSAndrew Litteken
171144cd22bSAndrew Litteken CodeExtractor CE(Candidates);
172144cd22bSAndrew Litteken EXPECT_TRUE(CE.isEligible());
173144cd22bSAndrew Litteken
174144cd22bSAndrew Litteken CodeExtractorAnalysisCache CEAC(*Func);
175144cd22bSAndrew Litteken Function *Outlined = CE.extractCodeRegion(CEAC);
176144cd22bSAndrew Litteken EXPECT_TRUE(Outlined);
177144cd22bSAndrew Litteken
178144cd22bSAndrew Litteken BasicBlock *FirstExitStub = getBlockByName(Outlined, "first.exitStub");
179144cd22bSAndrew Litteken BasicBlock *NextExitStub = getBlockByName(Outlined, "next.exitStub");
180144cd22bSAndrew Litteken
181144cd22bSAndrew Litteken Instruction *FirstTerm = FirstExitStub->getTerminator();
182144cd22bSAndrew Litteken ReturnInst *FirstReturn = dyn_cast<ReturnInst>(FirstTerm);
183144cd22bSAndrew Litteken EXPECT_TRUE(FirstReturn);
184144cd22bSAndrew Litteken ConstantInt *CIFirst = dyn_cast<ConstantInt>(FirstReturn->getReturnValue());
185144cd22bSAndrew Litteken EXPECT_TRUE(CIFirst->getLimitedValue() == 1u);
186144cd22bSAndrew Litteken
187144cd22bSAndrew Litteken Instruction *NextTerm = NextExitStub->getTerminator();
188144cd22bSAndrew Litteken ReturnInst *NextReturn = dyn_cast<ReturnInst>(NextTerm);
189144cd22bSAndrew Litteken EXPECT_TRUE(NextReturn);
190144cd22bSAndrew Litteken ConstantInt *CINext = dyn_cast<ConstantInt>(NextReturn->getReturnValue());
191144cd22bSAndrew Litteken EXPECT_TRUE(CINext->getLimitedValue() == 0u);
192144cd22bSAndrew Litteken
193144cd22bSAndrew Litteken EXPECT_FALSE(verifyFunction(*Outlined));
194144cd22bSAndrew Litteken EXPECT_FALSE(verifyFunction(*Func));
195144cd22bSAndrew Litteken }
196144cd22bSAndrew Litteken
TEST(CodeExtractor,ExitBlockOrdering)197144cd22bSAndrew Litteken TEST(CodeExtractor, ExitBlockOrdering) {
198144cd22bSAndrew Litteken LLVMContext Ctx;
199144cd22bSAndrew Litteken SMDiagnostic Err;
200144cd22bSAndrew Litteken std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
201144cd22bSAndrew Litteken define void @foo(i32 %a, i32 %b) {
202144cd22bSAndrew Litteken entry:
203144cd22bSAndrew Litteken %0 = alloca i32, align 4
204144cd22bSAndrew Litteken br label %test0
205144cd22bSAndrew Litteken test0:
206144cd22bSAndrew Litteken %c = load i32, i32* %0, align 4
207144cd22bSAndrew Litteken br label %test1
208144cd22bSAndrew Litteken test1:
209144cd22bSAndrew Litteken %e = load i32, i32* %0, align 4
210144cd22bSAndrew Litteken br i1 true, label %first, label %test
211144cd22bSAndrew Litteken test:
212144cd22bSAndrew Litteken %d = load i32, i32* %0, align 4
213144cd22bSAndrew Litteken br i1 true, label %first, label %next
214144cd22bSAndrew Litteken first:
215144cd22bSAndrew Litteken ret void
216144cd22bSAndrew Litteken next:
217144cd22bSAndrew Litteken %1 = add i32 %d, 1
218144cd22bSAndrew Litteken %2 = add i32 %e, 1
219144cd22bSAndrew Litteken ret void
220144cd22bSAndrew Litteken }
221144cd22bSAndrew Litteken )invalid",
222144cd22bSAndrew Litteken Err, Ctx));
223144cd22bSAndrew Litteken Function *Func = M->getFunction("foo");
224144cd22bSAndrew Litteken SmallVector<BasicBlock *, 3> Candidates{ getBlockByName(Func, "test0"),
225144cd22bSAndrew Litteken getBlockByName(Func, "test1"),
226144cd22bSAndrew Litteken getBlockByName(Func, "test") };
227144cd22bSAndrew Litteken
228144cd22bSAndrew Litteken CodeExtractor CE(Candidates);
229144cd22bSAndrew Litteken EXPECT_TRUE(CE.isEligible());
230144cd22bSAndrew Litteken
231144cd22bSAndrew Litteken CodeExtractorAnalysisCache CEAC(*Func);
232144cd22bSAndrew Litteken Function *Outlined = CE.extractCodeRegion(CEAC);
233144cd22bSAndrew Litteken EXPECT_TRUE(Outlined);
234144cd22bSAndrew Litteken
235144cd22bSAndrew Litteken BasicBlock *FirstExitStub = getBlockByName(Outlined, "first.exitStub");
236144cd22bSAndrew Litteken BasicBlock *NextExitStub = getBlockByName(Outlined, "next.exitStub");
237144cd22bSAndrew Litteken
238144cd22bSAndrew Litteken Instruction *FirstTerm = FirstExitStub->getTerminator();
239144cd22bSAndrew Litteken ReturnInst *FirstReturn = dyn_cast<ReturnInst>(FirstTerm);
240144cd22bSAndrew Litteken EXPECT_TRUE(FirstReturn);
241144cd22bSAndrew Litteken ConstantInt *CIFirst = dyn_cast<ConstantInt>(FirstReturn->getReturnValue());
242144cd22bSAndrew Litteken EXPECT_TRUE(CIFirst->getLimitedValue() == 1u);
243144cd22bSAndrew Litteken
244144cd22bSAndrew Litteken Instruction *NextTerm = NextExitStub->getTerminator();
245144cd22bSAndrew Litteken ReturnInst *NextReturn = dyn_cast<ReturnInst>(NextTerm);
246144cd22bSAndrew Litteken EXPECT_TRUE(NextReturn);
247144cd22bSAndrew Litteken ConstantInt *CINext = dyn_cast<ConstantInt>(NextReturn->getReturnValue());
248144cd22bSAndrew Litteken EXPECT_TRUE(CINext->getLimitedValue() == 0u);
249144cd22bSAndrew Litteken
250144cd22bSAndrew Litteken EXPECT_FALSE(verifyFunction(*Outlined));
251144cd22bSAndrew Litteken EXPECT_FALSE(verifyFunction(*Func));
252144cd22bSAndrew Litteken }
253144cd22bSAndrew Litteken
TEST(CodeExtractor,ExitPHIOnePredFromRegion)254d129569eSVedant Kumar TEST(CodeExtractor, ExitPHIOnePredFromRegion) {
255d129569eSVedant Kumar LLVMContext Ctx;
256d129569eSVedant Kumar SMDiagnostic Err;
257d129569eSVedant Kumar std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
258d129569eSVedant Kumar define i32 @foo() {
259d129569eSVedant Kumar header:
260d129569eSVedant Kumar br i1 undef, label %extracted1, label %pred
261d129569eSVedant Kumar
262d129569eSVedant Kumar pred:
263d129569eSVedant Kumar br i1 undef, label %exit1, label %exit2
264d129569eSVedant Kumar
265d129569eSVedant Kumar extracted1:
266d129569eSVedant Kumar br i1 undef, label %extracted2, label %exit1
267d129569eSVedant Kumar
268d129569eSVedant Kumar extracted2:
269d129569eSVedant Kumar br label %exit2
270d129569eSVedant Kumar
271d129569eSVedant Kumar exit1:
272d129569eSVedant Kumar %0 = phi i32 [ 1, %extracted1 ], [ 2, %pred ]
273d129569eSVedant Kumar ret i32 %0
274d129569eSVedant Kumar
275d129569eSVedant Kumar exit2:
276d129569eSVedant Kumar %1 = phi i32 [ 3, %extracted2 ], [ 4, %pred ]
277d129569eSVedant Kumar ret i32 %1
278d129569eSVedant Kumar }
279d129569eSVedant Kumar )invalid", Err, Ctx));
280d129569eSVedant Kumar
281d129569eSVedant Kumar Function *Func = M->getFunction("foo");
282d129569eSVedant Kumar SmallVector<BasicBlock *, 2> ExtractedBlocks{
283d129569eSVedant Kumar getBlockByName(Func, "extracted1"),
284d129569eSVedant Kumar getBlockByName(Func, "extracted2")
285d129569eSVedant Kumar };
286d129569eSVedant Kumar
2870e5dd512SVedant Kumar CodeExtractor CE(ExtractedBlocks);
288d129569eSVedant Kumar EXPECT_TRUE(CE.isEligible());
289d129569eSVedant Kumar
2909852699dSVedant Kumar CodeExtractorAnalysisCache CEAC(*Func);
2919852699dSVedant Kumar Function *Outlined = CE.extractCodeRegion(CEAC);
292d129569eSVedant Kumar EXPECT_TRUE(Outlined);
293d129569eSVedant Kumar BasicBlock *Exit1 = getBlockByName(Func, "exit1");
294d129569eSVedant Kumar BasicBlock *Exit2 = getBlockByName(Func, "exit2");
295d129569eSVedant Kumar // Ensure that PHIs in exits are not splitted (since that they have only one
296d129569eSVedant Kumar // incoming value from extracted region).
297d129569eSVedant Kumar EXPECT_TRUE(Exit1 &&
298d129569eSVedant Kumar cast<PHINode>(Exit1->front()).getNumIncomingValues() == 2);
299d129569eSVedant Kumar EXPECT_TRUE(Exit2 &&
300d129569eSVedant Kumar cast<PHINode>(Exit2->front()).getNumIncomingValues() == 2);
301d129569eSVedant Kumar EXPECT_FALSE(verifyFunction(*Outlined));
302d129569eSVedant Kumar EXPECT_FALSE(verifyFunction(*Func));
3038267b333SNico Weber }
304b2a6f8e5SVedant Kumar
TEST(CodeExtractor,StoreOutputInvokeResultAfterEHPad)305b2a6f8e5SVedant Kumar TEST(CodeExtractor, StoreOutputInvokeResultAfterEHPad) {
306b2a6f8e5SVedant Kumar LLVMContext Ctx;
307b2a6f8e5SVedant Kumar SMDiagnostic Err;
308b2a6f8e5SVedant Kumar std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
309b2a6f8e5SVedant Kumar declare i8 @hoge()
310b2a6f8e5SVedant Kumar
311b2a6f8e5SVedant Kumar define i32 @foo() personality i8* null {
312b2a6f8e5SVedant Kumar entry:
313b2a6f8e5SVedant Kumar %call = invoke i8 @hoge()
314b2a6f8e5SVedant Kumar to label %invoke.cont unwind label %lpad
315b2a6f8e5SVedant Kumar
316b2a6f8e5SVedant Kumar invoke.cont: ; preds = %entry
317b2a6f8e5SVedant Kumar unreachable
318b2a6f8e5SVedant Kumar
319b2a6f8e5SVedant Kumar lpad: ; preds = %entry
320b2a6f8e5SVedant Kumar %0 = landingpad { i8*, i32 }
321b2a6f8e5SVedant Kumar catch i8* null
322b2a6f8e5SVedant Kumar br i1 undef, label %catch, label %finally.catchall
323b2a6f8e5SVedant Kumar
324b2a6f8e5SVedant Kumar catch: ; preds = %lpad
325b2a6f8e5SVedant Kumar %call2 = invoke i8 @hoge()
326b2a6f8e5SVedant Kumar to label %invoke.cont2 unwind label %lpad2
327b2a6f8e5SVedant Kumar
328b2a6f8e5SVedant Kumar invoke.cont2: ; preds = %catch
329b2a6f8e5SVedant Kumar %call3 = invoke i8 @hoge()
330b2a6f8e5SVedant Kumar to label %invoke.cont3 unwind label %lpad2
331b2a6f8e5SVedant Kumar
332b2a6f8e5SVedant Kumar invoke.cont3: ; preds = %invoke.cont2
333b2a6f8e5SVedant Kumar unreachable
334b2a6f8e5SVedant Kumar
335b2a6f8e5SVedant Kumar lpad2: ; preds = %invoke.cont2, %catch
336b2a6f8e5SVedant Kumar %ex.1 = phi i8* [ undef, %invoke.cont2 ], [ null, %catch ]
337b2a6f8e5SVedant Kumar %1 = landingpad { i8*, i32 }
338b2a6f8e5SVedant Kumar catch i8* null
339b2a6f8e5SVedant Kumar br label %finally.catchall
340b2a6f8e5SVedant Kumar
341b2a6f8e5SVedant Kumar finally.catchall: ; preds = %lpad33, %lpad
342b2a6f8e5SVedant Kumar %ex.2 = phi i8* [ %ex.1, %lpad2 ], [ null, %lpad ]
343b2a6f8e5SVedant Kumar unreachable
344b2a6f8e5SVedant Kumar }
345b2a6f8e5SVedant Kumar )invalid", Err, Ctx));
346b2a6f8e5SVedant Kumar
347b2a6f8e5SVedant Kumar if (!M) {
348b2a6f8e5SVedant Kumar Err.print("unit", errs());
349b2a6f8e5SVedant Kumar exit(1);
350b2a6f8e5SVedant Kumar }
351b2a6f8e5SVedant Kumar
352b2a6f8e5SVedant Kumar Function *Func = M->getFunction("foo");
353b2a6f8e5SVedant Kumar EXPECT_FALSE(verifyFunction(*Func, &errs()));
354b2a6f8e5SVedant Kumar
355b2a6f8e5SVedant Kumar SmallVector<BasicBlock *, 2> ExtractedBlocks{
356b2a6f8e5SVedant Kumar getBlockByName(Func, "catch"),
357b2a6f8e5SVedant Kumar getBlockByName(Func, "invoke.cont2"),
358b2a6f8e5SVedant Kumar getBlockByName(Func, "invoke.cont3"),
359b2a6f8e5SVedant Kumar getBlockByName(Func, "lpad2")
360b2a6f8e5SVedant Kumar };
361b2a6f8e5SVedant Kumar
3620e5dd512SVedant Kumar CodeExtractor CE(ExtractedBlocks);
363b2a6f8e5SVedant Kumar EXPECT_TRUE(CE.isEligible());
364b2a6f8e5SVedant Kumar
3659852699dSVedant Kumar CodeExtractorAnalysisCache CEAC(*Func);
3669852699dSVedant Kumar Function *Outlined = CE.extractCodeRegion(CEAC);
367b2a6f8e5SVedant Kumar EXPECT_TRUE(Outlined);
368b2a6f8e5SVedant Kumar EXPECT_FALSE(verifyFunction(*Outlined, &errs()));
369b2a6f8e5SVedant Kumar EXPECT_FALSE(verifyFunction(*Func, &errs()));
370b2a6f8e5SVedant Kumar }
371b2a6f8e5SVedant Kumar
TEST(CodeExtractor,StoreOutputInvokeResultInExitStub)3720e5dd512SVedant Kumar TEST(CodeExtractor, StoreOutputInvokeResultInExitStub) {
3730e5dd512SVedant Kumar LLVMContext Ctx;
3740e5dd512SVedant Kumar SMDiagnostic Err;
3750e5dd512SVedant Kumar std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
3760e5dd512SVedant Kumar declare i32 @bar()
3770e5dd512SVedant Kumar
3780e5dd512SVedant Kumar define i32 @foo() personality i8* null {
3790e5dd512SVedant Kumar entry:
3800e5dd512SVedant Kumar %0 = invoke i32 @bar() to label %exit unwind label %lpad
3810e5dd512SVedant Kumar
3820e5dd512SVedant Kumar exit:
3830e5dd512SVedant Kumar ret i32 %0
3840e5dd512SVedant Kumar
3850e5dd512SVedant Kumar lpad:
3860e5dd512SVedant Kumar %1 = landingpad { i8*, i32 }
3870e5dd512SVedant Kumar cleanup
3880e5dd512SVedant Kumar resume { i8*, i32 } %1
3890e5dd512SVedant Kumar }
3900e5dd512SVedant Kumar )invalid",
3910e5dd512SVedant Kumar Err, Ctx));
3920e5dd512SVedant Kumar
3930e5dd512SVedant Kumar Function *Func = M->getFunction("foo");
3940e5dd512SVedant Kumar SmallVector<BasicBlock *, 1> Blocks{ getBlockByName(Func, "entry"),
3950e5dd512SVedant Kumar getBlockByName(Func, "lpad") };
3960e5dd512SVedant Kumar
3970e5dd512SVedant Kumar CodeExtractor CE(Blocks);
3980e5dd512SVedant Kumar EXPECT_TRUE(CE.isEligible());
3990e5dd512SVedant Kumar
4009852699dSVedant Kumar CodeExtractorAnalysisCache CEAC(*Func);
4019852699dSVedant Kumar Function *Outlined = CE.extractCodeRegion(CEAC);
4020e5dd512SVedant Kumar EXPECT_TRUE(Outlined);
4030e5dd512SVedant Kumar EXPECT_FALSE(verifyFunction(*Outlined));
4040e5dd512SVedant Kumar EXPECT_FALSE(verifyFunction(*Func));
4050e5dd512SVedant Kumar }
4060e5dd512SVedant Kumar
TEST(CodeExtractor,ExtractAndInvalidateAssumptionCache)40750afaa9dSAditya Kumar TEST(CodeExtractor, ExtractAndInvalidateAssumptionCache) {
40850afaa9dSAditya Kumar LLVMContext Ctx;
40950afaa9dSAditya Kumar SMDiagnostic Err;
41050afaa9dSAditya Kumar std::unique_ptr<Module> M(parseAssemblyString(R"ir(
41150afaa9dSAditya Kumar target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
41250afaa9dSAditya Kumar target triple = "aarch64"
41350afaa9dSAditya Kumar
41450afaa9dSAditya Kumar %b = type { i64 }
41550afaa9dSAditya Kumar declare void @g(i8*)
41650afaa9dSAditya Kumar
41750afaa9dSAditya Kumar declare void @llvm.assume(i1) #0
41850afaa9dSAditya Kumar
41950afaa9dSAditya Kumar define void @test() {
42050afaa9dSAditya Kumar entry:
42150afaa9dSAditya Kumar br label %label
42250afaa9dSAditya Kumar
42350afaa9dSAditya Kumar label:
42450afaa9dSAditya Kumar %0 = load %b*, %b** inttoptr (i64 8 to %b**), align 8
42550afaa9dSAditya Kumar %1 = getelementptr inbounds %b, %b* %0, i64 undef, i32 0
42650afaa9dSAditya Kumar %2 = load i64, i64* %1, align 8
42750afaa9dSAditya Kumar %3 = icmp ugt i64 %2, 1
42850afaa9dSAditya Kumar br i1 %3, label %if.then, label %if.else
42950afaa9dSAditya Kumar
43050afaa9dSAditya Kumar if.then:
43150afaa9dSAditya Kumar unreachable
43250afaa9dSAditya Kumar
43350afaa9dSAditya Kumar if.else:
43450afaa9dSAditya Kumar call void @g(i8* undef)
43550afaa9dSAditya Kumar store i64 undef, i64* null, align 536870912
43650afaa9dSAditya Kumar %4 = icmp eq i64 %2, 0
43750afaa9dSAditya Kumar call void @llvm.assume(i1 %4)
43850afaa9dSAditya Kumar unreachable
43950afaa9dSAditya Kumar }
44050afaa9dSAditya Kumar
44150afaa9dSAditya Kumar attributes #0 = { nounwind willreturn }
44250afaa9dSAditya Kumar )ir",
44350afaa9dSAditya Kumar Err, Ctx));
44450afaa9dSAditya Kumar
44550afaa9dSAditya Kumar assert(M && "Could not parse module?");
44650afaa9dSAditya Kumar Function *Func = M->getFunction("test");
44750afaa9dSAditya Kumar SmallVector<BasicBlock *, 1> Blocks{ getBlockByName(Func, "if.else") };
44850afaa9dSAditya Kumar AssumptionCache AC(*Func);
44950afaa9dSAditya Kumar CodeExtractor CE(Blocks, nullptr, false, nullptr, nullptr, &AC);
45050afaa9dSAditya Kumar EXPECT_TRUE(CE.isEligible());
45150afaa9dSAditya Kumar
4529852699dSVedant Kumar CodeExtractorAnalysisCache CEAC(*Func);
4539852699dSVedant Kumar Function *Outlined = CE.extractCodeRegion(CEAC);
45450afaa9dSAditya Kumar EXPECT_TRUE(Outlined);
45550afaa9dSAditya Kumar EXPECT_FALSE(verifyFunction(*Outlined));
45650afaa9dSAditya Kumar EXPECT_FALSE(verifyFunction(*Func));
4578359511cSVedant Kumar EXPECT_FALSE(CE.verifyAssumptionCache(*Func, *Outlined, &AC));
45850afaa9dSAditya Kumar }
459700d2417SGiorgis Georgakoudis
TEST(CodeExtractor,RemoveBitcastUsesFromOuterLifetimeMarkers)460700d2417SGiorgis Georgakoudis TEST(CodeExtractor, RemoveBitcastUsesFromOuterLifetimeMarkers) {
461700d2417SGiorgis Georgakoudis LLVMContext Ctx;
462700d2417SGiorgis Georgakoudis SMDiagnostic Err;
463700d2417SGiorgis Georgakoudis std::unique_ptr<Module> M(parseAssemblyString(R"ir(
464700d2417SGiorgis Georgakoudis target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
465700d2417SGiorgis Georgakoudis target triple = "x86_64-unknown-linux-gnu"
466700d2417SGiorgis Georgakoudis
467700d2417SGiorgis Georgakoudis declare void @use(i32*)
468700d2417SGiorgis Georgakoudis declare void @llvm.lifetime.start.p0i8(i64, i8*)
469700d2417SGiorgis Georgakoudis declare void @llvm.lifetime.end.p0i8(i64, i8*)
470700d2417SGiorgis Georgakoudis
471700d2417SGiorgis Georgakoudis define void @foo() {
472700d2417SGiorgis Georgakoudis entry:
473700d2417SGiorgis Georgakoudis %0 = alloca i32
474700d2417SGiorgis Georgakoudis br label %extract
475700d2417SGiorgis Georgakoudis
476700d2417SGiorgis Georgakoudis extract:
477700d2417SGiorgis Georgakoudis %1 = bitcast i32* %0 to i8*
478700d2417SGiorgis Georgakoudis call void @llvm.lifetime.start.p0i8(i64 4, i8* %1)
479700d2417SGiorgis Georgakoudis call void @use(i32* %0)
480700d2417SGiorgis Georgakoudis br label %exit
481700d2417SGiorgis Georgakoudis
482700d2417SGiorgis Georgakoudis exit:
483700d2417SGiorgis Georgakoudis call void @use(i32* %0)
484700d2417SGiorgis Georgakoudis call void @llvm.lifetime.end.p0i8(i64 4, i8* %1)
485700d2417SGiorgis Georgakoudis ret void
486700d2417SGiorgis Georgakoudis }
487700d2417SGiorgis Georgakoudis )ir",
488700d2417SGiorgis Georgakoudis Err, Ctx));
489700d2417SGiorgis Georgakoudis
490700d2417SGiorgis Georgakoudis Function *Func = M->getFunction("foo");
491700d2417SGiorgis Georgakoudis SmallVector<BasicBlock *, 1> Blocks{getBlockByName(Func, "extract")};
492700d2417SGiorgis Georgakoudis
493700d2417SGiorgis Georgakoudis CodeExtractor CE(Blocks);
494700d2417SGiorgis Georgakoudis EXPECT_TRUE(CE.isEligible());
495700d2417SGiorgis Georgakoudis
496700d2417SGiorgis Georgakoudis CodeExtractorAnalysisCache CEAC(*Func);
497700d2417SGiorgis Georgakoudis SetVector<Value *> Inputs, Outputs, SinkingCands, HoistingCands;
498700d2417SGiorgis Georgakoudis BasicBlock *CommonExit = nullptr;
499700d2417SGiorgis Georgakoudis CE.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
500700d2417SGiorgis Georgakoudis CE.findInputsOutputs(Inputs, Outputs, SinkingCands);
501700d2417SGiorgis Georgakoudis EXPECT_EQ(Outputs.size(), 0U);
502700d2417SGiorgis Georgakoudis
503700d2417SGiorgis Georgakoudis Function *Outlined = CE.extractCodeRegion(CEAC);
504700d2417SGiorgis Georgakoudis EXPECT_TRUE(Outlined);
50595b981caSGiorgis Georgakoudis EXPECT_FALSE(verifyFunction(*Outlined));
50695b981caSGiorgis Georgakoudis EXPECT_FALSE(verifyFunction(*Func));
50795b981caSGiorgis Georgakoudis }
50895b981caSGiorgis Georgakoudis
TEST(CodeExtractor,PartialAggregateArgs)50995b981caSGiorgis Georgakoudis TEST(CodeExtractor, PartialAggregateArgs) {
51095b981caSGiorgis Georgakoudis LLVMContext Ctx;
51195b981caSGiorgis Georgakoudis SMDiagnostic Err;
51295b981caSGiorgis Georgakoudis std::unique_ptr<Module> M(parseAssemblyString(R"ir(
51395b981caSGiorgis Georgakoudis target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
51495b981caSGiorgis Georgakoudis target triple = "x86_64-unknown-linux-gnu"
51595b981caSGiorgis Georgakoudis
51695b981caSGiorgis Georgakoudis declare void @use(i32)
51795b981caSGiorgis Georgakoudis
51895b981caSGiorgis Georgakoudis define void @foo(i32 %a, i32 %b, i32 %c) {
51995b981caSGiorgis Georgakoudis entry:
52095b981caSGiorgis Georgakoudis br label %extract
52195b981caSGiorgis Georgakoudis
52295b981caSGiorgis Georgakoudis extract:
52395b981caSGiorgis Georgakoudis call void @use(i32 %a)
52495b981caSGiorgis Georgakoudis call void @use(i32 %b)
52595b981caSGiorgis Georgakoudis call void @use(i32 %c)
52695b981caSGiorgis Georgakoudis br label %exit
52795b981caSGiorgis Georgakoudis
52895b981caSGiorgis Georgakoudis exit:
52995b981caSGiorgis Georgakoudis ret void
53095b981caSGiorgis Georgakoudis }
53195b981caSGiorgis Georgakoudis )ir",
53295b981caSGiorgis Georgakoudis Err, Ctx));
53395b981caSGiorgis Georgakoudis
53495b981caSGiorgis Georgakoudis Function *Func = M->getFunction("foo");
53595b981caSGiorgis Georgakoudis SmallVector<BasicBlock *, 1> Blocks{getBlockByName(Func, "extract")};
53695b981caSGiorgis Georgakoudis
53795b981caSGiorgis Georgakoudis // Create the CodeExtractor with arguments aggregation enabled.
53895b981caSGiorgis Georgakoudis CodeExtractor CE(Blocks, /* DominatorTree */ nullptr,
53995b981caSGiorgis Georgakoudis /* AggregateArgs */ true);
54095b981caSGiorgis Georgakoudis EXPECT_TRUE(CE.isEligible());
54195b981caSGiorgis Georgakoudis
54295b981caSGiorgis Georgakoudis CodeExtractorAnalysisCache CEAC(*Func);
54395b981caSGiorgis Georgakoudis SetVector<Value *> Inputs, Outputs, SinkingCands, HoistingCands;
54495b981caSGiorgis Georgakoudis BasicBlock *CommonExit = nullptr;
54595b981caSGiorgis Georgakoudis CE.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
54695b981caSGiorgis Georgakoudis CE.findInputsOutputs(Inputs, Outputs, SinkingCands);
54795b981caSGiorgis Georgakoudis // Exclude the first input from the argument aggregate.
54895b981caSGiorgis Georgakoudis CE.excludeArgFromAggregate(Inputs[0]);
54995b981caSGiorgis Georgakoudis
55095b981caSGiorgis Georgakoudis Function *Outlined = CE.extractCodeRegion(CEAC, Inputs, Outputs);
55195b981caSGiorgis Georgakoudis EXPECT_TRUE(Outlined);
55295b981caSGiorgis Georgakoudis // Expect 2 arguments in the outlined function: the excluded input and the
55395b981caSGiorgis Georgakoudis // struct aggregate for the remaining inputs.
55495b981caSGiorgis Georgakoudis EXPECT_EQ(Outlined->arg_size(), 2U);
555700d2417SGiorgis Georgakoudis EXPECT_FALSE(verifyFunction(*Outlined));
556700d2417SGiorgis Georgakoudis EXPECT_FALSE(verifyFunction(*Func));
557700d2417SGiorgis Georgakoudis }
5588267b333SNico Weber } // end anonymous namespace
559