18267b333SNico Weber //===- CodeExtractor.cpp - Unit tests for CodeExtractor -------------------===// 28267b333SNico Weber // 38267b333SNico Weber // The LLVM Compiler Infrastructure 48267b333SNico Weber // 58267b333SNico Weber // This file is distributed under the University of Illinois Open Source 68267b333SNico Weber // License. See LICENSE.TXT for details. 78267b333SNico Weber // 88267b333SNico Weber //===----------------------------------------------------------------------===// 98267b333SNico Weber 108267b333SNico Weber #include "llvm/Transforms/Utils/CodeExtractor.h" 118267b333SNico Weber #include "llvm/AsmParser/Parser.h" 128267b333SNico Weber #include "llvm/IR/BasicBlock.h" 138267b333SNico Weber #include "llvm/IR/Dominators.h" 14*d129569eSVedant 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 { 25*d129569eSVedant Kumar BasicBlock *getBlockByName(Function *F, StringRef name) { 26*d129569eSVedant Kumar for (auto &BB : *F) 27*d129569eSVedant Kumar if (BB.getName() == name) 28*d129569eSVedant Kumar return &BB; 29*d129569eSVedant Kumar return nullptr; 30*d129569eSVedant Kumar } 31*d129569eSVedant Kumar 32*d129569eSVedant 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"); 58*d129569eSVedant Kumar SmallVector<BasicBlock *, 3> Candidates{ getBlockByName(Func, "header"), 59*d129569eSVedant Kumar getBlockByName(Func, "body1"), 60*d129569eSVedant Kumar getBlockByName(Func, "body2") }; 618267b333SNico Weber 628267b333SNico Weber DominatorTree DT(*Func); 638267b333SNico Weber CodeExtractor CE(Candidates, &DT); 648267b333SNico Weber EXPECT_TRUE(CE.isEligible()); 658267b333SNico Weber 668267b333SNico Weber Function *Outlined = CE.extractCodeRegion(); 678267b333SNico Weber EXPECT_TRUE(Outlined); 68*d129569eSVedant Kumar BasicBlock *Exit = getBlockByName(Func, "notExtracted"); 69*d129569eSVedant Kumar BasicBlock *ExitSplit = getBlockByName(Outlined, "notExtracted.split"); 70*d129569eSVedant Kumar // Ensure that PHI in exit block has only one incoming value (from code 71*d129569eSVedant Kumar // replacer block). 72*d129569eSVedant Kumar EXPECT_TRUE(Exit && cast<PHINode>(Exit->front()).getNumIncomingValues() == 1); 73*d129569eSVedant Kumar // Ensure that there is a PHI in outlined function with 2 incoming values. 74*d129569eSVedant Kumar EXPECT_TRUE(ExitSplit && 75*d129569eSVedant Kumar cast<PHINode>(ExitSplit->front()).getNumIncomingValues() == 2); 768267b333SNico Weber EXPECT_FALSE(verifyFunction(*Outlined)); 77*d129569eSVedant Kumar EXPECT_FALSE(verifyFunction(*Func)); 78*d129569eSVedant Kumar } 79*d129569eSVedant Kumar 80*d129569eSVedant Kumar TEST(CodeExtractor, ExitPHIOnePredFromRegion) { 81*d129569eSVedant Kumar LLVMContext Ctx; 82*d129569eSVedant Kumar SMDiagnostic Err; 83*d129569eSVedant Kumar std::unique_ptr<Module> M(parseAssemblyString(R"invalid( 84*d129569eSVedant Kumar define i32 @foo() { 85*d129569eSVedant Kumar header: 86*d129569eSVedant Kumar br i1 undef, label %extracted1, label %pred 87*d129569eSVedant Kumar 88*d129569eSVedant Kumar pred: 89*d129569eSVedant Kumar br i1 undef, label %exit1, label %exit2 90*d129569eSVedant Kumar 91*d129569eSVedant Kumar extracted1: 92*d129569eSVedant Kumar br i1 undef, label %extracted2, label %exit1 93*d129569eSVedant Kumar 94*d129569eSVedant Kumar extracted2: 95*d129569eSVedant Kumar br label %exit2 96*d129569eSVedant Kumar 97*d129569eSVedant Kumar exit1: 98*d129569eSVedant Kumar %0 = phi i32 [ 1, %extracted1 ], [ 2, %pred ] 99*d129569eSVedant Kumar ret i32 %0 100*d129569eSVedant Kumar 101*d129569eSVedant Kumar exit2: 102*d129569eSVedant Kumar %1 = phi i32 [ 3, %extracted2 ], [ 4, %pred ] 103*d129569eSVedant Kumar ret i32 %1 104*d129569eSVedant Kumar } 105*d129569eSVedant Kumar )invalid", Err, Ctx)); 106*d129569eSVedant Kumar 107*d129569eSVedant Kumar Function *Func = M->getFunction("foo"); 108*d129569eSVedant Kumar SmallVector<BasicBlock *, 2> ExtractedBlocks{ 109*d129569eSVedant Kumar getBlockByName(Func, "extracted1"), 110*d129569eSVedant Kumar getBlockByName(Func, "extracted2") 111*d129569eSVedant Kumar }; 112*d129569eSVedant Kumar 113*d129569eSVedant Kumar DominatorTree DT(*Func); 114*d129569eSVedant Kumar CodeExtractor CE(ExtractedBlocks, &DT); 115*d129569eSVedant Kumar EXPECT_TRUE(CE.isEligible()); 116*d129569eSVedant Kumar 117*d129569eSVedant Kumar Function *Outlined = CE.extractCodeRegion(); 118*d129569eSVedant Kumar EXPECT_TRUE(Outlined); 119*d129569eSVedant Kumar BasicBlock *Exit1 = getBlockByName(Func, "exit1"); 120*d129569eSVedant Kumar BasicBlock *Exit2 = getBlockByName(Func, "exit2"); 121*d129569eSVedant Kumar // Ensure that PHIs in exits are not splitted (since that they have only one 122*d129569eSVedant Kumar // incoming value from extracted region). 123*d129569eSVedant Kumar EXPECT_TRUE(Exit1 && 124*d129569eSVedant Kumar cast<PHINode>(Exit1->front()).getNumIncomingValues() == 2); 125*d129569eSVedant Kumar EXPECT_TRUE(Exit2 && 126*d129569eSVedant Kumar cast<PHINode>(Exit2->front()).getNumIncomingValues() == 2); 127*d129569eSVedant Kumar EXPECT_FALSE(verifyFunction(*Outlined)); 128*d129569eSVedant Kumar EXPECT_FALSE(verifyFunction(*Func)); 1298267b333SNico Weber } 1308267b333SNico Weber } // end anonymous namespace 131