1 //===- llvm/unittest/Transforms/Vectorize/VPlanHCFGTest.cpp ---------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "../lib/Transforms/Vectorize/VPlan.h" 11 #include "../lib/Transforms/Vectorize/VPlanHCFGBuilder.h" 12 #include "../lib/Transforms/Vectorize/VPlanHCFGTransforms.h" 13 #include "llvm/AsmParser/Parser.h" 14 #include "llvm/IR/Dominators.h" 15 #include "gtest/gtest.h" 16 17 namespace llvm { 18 namespace { 19 20 class VPlanHCFGTest : public testing::Test { 21 protected: 22 std::unique_ptr<DominatorTree> DT; 23 std::unique_ptr<LoopInfo> LI; 24 25 VPlanHCFGTest() {} 26 27 VPlanPtr doBuildPlan(BasicBlock *LoopHeader) { 28 DT.reset(new DominatorTree(*LoopHeader->getParent())); 29 LI.reset(new LoopInfo(*DT)); 30 31 auto Plan = llvm::make_unique<VPlan>(); 32 VPlanHCFGBuilder HCFGBuilder(LI->getLoopFor(LoopHeader), LI.get()); 33 HCFGBuilder.buildHierarchicalCFG(*Plan.get()); 34 return Plan; 35 } 36 }; 37 38 TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) { 39 LLVMContext Ctx; 40 const char *ModuleString = 41 "define void @f(i32* %A, i64 %N) {\n" 42 "entry:\n" 43 " br label %for.body\n" 44 "for.body:\n" 45 " %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n" 46 " %arr.idx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n" 47 " %l1 = load i32, i32* %arr.idx, align 4\n" 48 " %res = add i32 %l1, 10\n" 49 " store i32 %res, i32* %arr.idx, align 4\n" 50 " %indvars.iv.next = add i64 %indvars.iv, 1\n" 51 " %exitcond = icmp ne i64 %indvars.iv.next, %N\n" 52 " br i1 %exitcond, label %for.body, label %for.end\n" 53 "for.end:\n" 54 " ret void\n" 55 "}\n"; 56 57 SMDiagnostic Err; 58 std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, Ctx); 59 60 Function *F = M->getFunction("f"); 61 BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor(); 62 auto Plan = doBuildPlan(LoopHeader); 63 64 VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock(); 65 EXPECT_NE(nullptr, Entry->getSingleSuccessor()); 66 EXPECT_EQ(0u, Entry->getNumPredecessors()); 67 EXPECT_EQ(1u, Entry->getNumSuccessors()); 68 69 VPBasicBlock *VecBB = Entry->getSingleSuccessor()->getEntryBasicBlock(); 70 EXPECT_EQ(7u, VecBB->size()); 71 EXPECT_EQ(2u, VecBB->getNumPredecessors()); 72 EXPECT_EQ(2u, VecBB->getNumSuccessors()); 73 74 auto Iter = VecBB->begin(); 75 VPInstruction *Phi = dyn_cast<VPInstruction>(&*Iter++); 76 EXPECT_EQ(Instruction::PHI, Phi->getOpcode()); 77 78 VPInstruction *Idx = dyn_cast<VPInstruction>(&*Iter++); 79 EXPECT_EQ(Instruction::GetElementPtr, Idx->getOpcode()); 80 EXPECT_EQ(2u, Idx->getNumOperands()); 81 EXPECT_EQ(Phi, Idx->getOperand(1)); 82 83 VPInstruction *Load = dyn_cast<VPInstruction>(&*Iter++); 84 EXPECT_EQ(Instruction::Load, Load->getOpcode()); 85 EXPECT_EQ(1u, Load->getNumOperands()); 86 EXPECT_EQ(Idx, Load->getOperand(0)); 87 88 VPInstruction *Add = dyn_cast<VPInstruction>(&*Iter++); 89 EXPECT_EQ(Instruction::Add, Add->getOpcode()); 90 EXPECT_EQ(2u, Add->getNumOperands()); 91 EXPECT_EQ(Load, Add->getOperand(0)); 92 93 VPInstruction *Store = dyn_cast<VPInstruction>(&*Iter++); 94 EXPECT_EQ(Instruction::Store, Store->getOpcode()); 95 EXPECT_EQ(2u, Store->getNumOperands()); 96 EXPECT_EQ(Add, Store->getOperand(0)); 97 EXPECT_EQ(Idx, Store->getOperand(1)); 98 99 VPInstruction *IndvarAdd = dyn_cast<VPInstruction>(&*Iter++); 100 EXPECT_EQ(Instruction::Add, IndvarAdd->getOpcode()); 101 EXPECT_EQ(2u, IndvarAdd->getNumOperands()); 102 EXPECT_EQ(Phi, IndvarAdd->getOperand(0)); 103 104 VPInstruction *ICmp = dyn_cast<VPInstruction>(&*Iter++); 105 EXPECT_EQ(Instruction::ICmp, ICmp->getOpcode()); 106 EXPECT_EQ(2u, ICmp->getNumOperands()); 107 EXPECT_EQ(IndvarAdd, ICmp->getOperand(0)); 108 109 LoopVectorizationLegality::InductionList Inductions; 110 SmallPtrSet<Instruction *, 1> DeadInstructions; 111 VPlanHCFGTransforms::VPInstructionsToVPRecipes(Plan, &Inductions, 112 DeadInstructions); 113 } 114 115 TEST_F(VPlanHCFGTest, testVPInstructionToVPRecipesInner) { 116 LLVMContext Ctx; 117 const char *ModuleString = 118 "define void @f(i32* %A, i64 %N) {\n" 119 "entry:\n" 120 " br label %for.body\n" 121 "for.body:\n" 122 " %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n" 123 " %arr.idx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n" 124 " %l1 = load i32, i32* %arr.idx, align 4\n" 125 " %res = add i32 %l1, 10\n" 126 " store i32 %res, i32* %arr.idx, align 4\n" 127 " %indvars.iv.next = add i64 %indvars.iv, 1\n" 128 " %exitcond = icmp ne i64 %indvars.iv.next, %N\n" 129 " br i1 %exitcond, label %for.body, label %for.end\n" 130 "for.end:\n" 131 " ret void\n" 132 "}\n"; 133 134 SMDiagnostic Err; 135 std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, Ctx); 136 137 Function *F = M->getFunction("f"); 138 BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor(); 139 auto Plan = doBuildPlan(LoopHeader); 140 141 LoopVectorizationLegality::InductionList Inductions; 142 SmallPtrSet<Instruction *, 1> DeadInstructions; 143 VPlanHCFGTransforms::VPInstructionsToVPRecipes(Plan, &Inductions, 144 DeadInstructions); 145 146 VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock(); 147 EXPECT_NE(nullptr, Entry->getSingleSuccessor()); 148 EXPECT_EQ(0u, Entry->getNumPredecessors()); 149 EXPECT_EQ(1u, Entry->getNumSuccessors()); 150 151 VPBasicBlock *VecBB = Entry->getSingleSuccessor()->getEntryBasicBlock(); 152 EXPECT_EQ(6u, VecBB->size()); 153 EXPECT_EQ(2u, VecBB->getNumPredecessors()); 154 EXPECT_EQ(2u, VecBB->getNumSuccessors()); 155 156 auto Iter = VecBB->begin(); 157 auto *Phi = dyn_cast<VPWidenPHIRecipe>(&*Iter++); 158 EXPECT_NE(nullptr, Phi); 159 160 auto *Idx = dyn_cast<VPWidenRecipe>(&*Iter++); 161 EXPECT_NE(nullptr, Idx); 162 163 auto *Load = dyn_cast<VPWidenMemoryInstructionRecipe>(&*Iter++); 164 EXPECT_NE(nullptr, Load); 165 166 auto *Add = dyn_cast<VPWidenRecipe>(&*Iter++); 167 EXPECT_NE(nullptr, Add); 168 169 auto *Store = dyn_cast<VPWidenMemoryInstructionRecipe>(&*Iter++); 170 EXPECT_NE(nullptr, Store); 171 172 auto *LastWiden = dyn_cast<VPWidenRecipe>(&*Iter++); 173 EXPECT_NE(nullptr, LastWiden); 174 EXPECT_EQ(VecBB->end(), Iter); 175 } 176 177 } // namespace 178 } // namespace llvm 179