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