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