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/VPlanHCFGTransforms.h" 12 #include "VPlanTestBase.h" 13 #include "gtest/gtest.h" 14 15 namespace llvm { 16 namespace { 17 18 class VPlanHCFGTest : public VPlanTestBase {}; 19 20 TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) { 21 const char *ModuleString = 22 "define void @f(i32* %A, i64 %N) {\n" 23 "entry:\n" 24 " br label %for.body\n" 25 "for.body:\n" 26 " %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n" 27 " %arr.idx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n" 28 " %l1 = load i32, i32* %arr.idx, align 4\n" 29 " %res = add i32 %l1, 10\n" 30 " store i32 %res, i32* %arr.idx, align 4\n" 31 " %indvars.iv.next = add i64 %indvars.iv, 1\n" 32 " %exitcond = icmp ne i64 %indvars.iv.next, %N\n" 33 " br i1 %exitcond, label %for.body, label %for.end\n" 34 "for.end:\n" 35 " ret void\n" 36 "}\n"; 37 38 Module &M = parseModule(ModuleString); 39 40 Function *F = M.getFunction("f"); 41 BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor(); 42 auto Plan = buildHCFG(LoopHeader); 43 44 VPBasicBlock *Entry = Plan->getEntry()->getEntryBasicBlock(); 45 EXPECT_NE(nullptr, Entry->getSingleSuccessor()); 46 EXPECT_EQ(0u, Entry->getNumPredecessors()); 47 EXPECT_EQ(1u, Entry->getNumSuccessors()); 48 EXPECT_EQ(nullptr, Entry->getCondBit()); 49 50 VPBasicBlock *VecBB = Entry->getSingleSuccessor()->getEntryBasicBlock(); 51 EXPECT_EQ(7u, VecBB->size()); 52 EXPECT_EQ(2u, VecBB->getNumPredecessors()); 53 EXPECT_EQ(2u, VecBB->getNumSuccessors()); 54 55 auto Iter = VecBB->begin(); 56 VPInstruction *Phi = dyn_cast<VPInstruction>(&*Iter++); 57 EXPECT_EQ(Instruction::PHI, Phi->getOpcode()); 58 59 VPInstruction *Idx = dyn_cast<VPInstruction>(&*Iter++); 60 EXPECT_EQ(Instruction::GetElementPtr, Idx->getOpcode()); 61 EXPECT_EQ(2u, Idx->getNumOperands()); 62 EXPECT_EQ(Phi, Idx->getOperand(1)); 63 64 VPInstruction *Load = dyn_cast<VPInstruction>(&*Iter++); 65 EXPECT_EQ(Instruction::Load, Load->getOpcode()); 66 EXPECT_EQ(1u, Load->getNumOperands()); 67 EXPECT_EQ(Idx, Load->getOperand(0)); 68 69 VPInstruction *Add = dyn_cast<VPInstruction>(&*Iter++); 70 EXPECT_EQ(Instruction::Add, Add->getOpcode()); 71 EXPECT_EQ(2u, Add->getNumOperands()); 72 EXPECT_EQ(Load, Add->getOperand(0)); 73 74 VPInstruction *Store = dyn_cast<VPInstruction>(&*Iter++); 75 EXPECT_EQ(Instruction::Store, Store->getOpcode()); 76 EXPECT_EQ(2u, Store->getNumOperands()); 77 EXPECT_EQ(Add, Store->getOperand(0)); 78 EXPECT_EQ(Idx, Store->getOperand(1)); 79 80 VPInstruction *IndvarAdd = dyn_cast<VPInstruction>(&*Iter++); 81 EXPECT_EQ(Instruction::Add, IndvarAdd->getOpcode()); 82 EXPECT_EQ(2u, IndvarAdd->getNumOperands()); 83 EXPECT_EQ(Phi, IndvarAdd->getOperand(0)); 84 85 VPInstruction *ICmp = dyn_cast<VPInstruction>(&*Iter++); 86 EXPECT_EQ(Instruction::ICmp, ICmp->getOpcode()); 87 EXPECT_EQ(2u, ICmp->getNumOperands()); 88 EXPECT_EQ(IndvarAdd, ICmp->getOperand(0)); 89 EXPECT_EQ(VecBB->getCondBit(), ICmp); 90 91 LoopVectorizationLegality::InductionList Inductions; 92 SmallPtrSet<Instruction *, 1> DeadInstructions; 93 VPlanHCFGTransforms::VPInstructionsToVPRecipes(Plan, &Inductions, 94 DeadInstructions); 95 } 96 97 TEST_F(VPlanHCFGTest, testVPInstructionToVPRecipesInner) { 98 const char *ModuleString = 99 "define void @f(i32* %A, i64 %N) {\n" 100 "entry:\n" 101 " br label %for.body\n" 102 "for.body:\n" 103 " %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n" 104 " %arr.idx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n" 105 " %l1 = load i32, i32* %arr.idx, align 4\n" 106 " %res = add i32 %l1, 10\n" 107 " store i32 %res, i32* %arr.idx, align 4\n" 108 " %indvars.iv.next = add i64 %indvars.iv, 1\n" 109 " %exitcond = icmp ne i64 %indvars.iv.next, %N\n" 110 " br i1 %exitcond, label %for.body, label %for.end\n" 111 "for.end:\n" 112 " ret void\n" 113 "}\n"; 114 115 Module &M = parseModule(ModuleString); 116 117 Function *F = M.getFunction("f"); 118 BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor(); 119 auto Plan = buildHCFG(LoopHeader); 120 121 LoopVectorizationLegality::InductionList Inductions; 122 SmallPtrSet<Instruction *, 1> DeadInstructions; 123 VPlanHCFGTransforms::VPInstructionsToVPRecipes(Plan, &Inductions, 124 DeadInstructions); 125 126 VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock(); 127 EXPECT_NE(nullptr, Entry->getSingleSuccessor()); 128 EXPECT_EQ(0u, Entry->getNumPredecessors()); 129 EXPECT_EQ(1u, Entry->getNumSuccessors()); 130 131 VPBasicBlock *VecBB = Entry->getSingleSuccessor()->getEntryBasicBlock(); 132 EXPECT_EQ(6u, VecBB->size()); 133 EXPECT_EQ(2u, VecBB->getNumPredecessors()); 134 EXPECT_EQ(2u, VecBB->getNumSuccessors()); 135 136 auto Iter = VecBB->begin(); 137 auto *Phi = dyn_cast<VPWidenPHIRecipe>(&*Iter++); 138 EXPECT_NE(nullptr, Phi); 139 140 auto *Idx = dyn_cast<VPWidenRecipe>(&*Iter++); 141 EXPECT_NE(nullptr, Idx); 142 143 auto *Load = dyn_cast<VPWidenMemoryInstructionRecipe>(&*Iter++); 144 EXPECT_NE(nullptr, Load); 145 146 auto *Add = dyn_cast<VPWidenRecipe>(&*Iter++); 147 EXPECT_NE(nullptr, Add); 148 149 auto *Store = dyn_cast<VPWidenMemoryInstructionRecipe>(&*Iter++); 150 EXPECT_NE(nullptr, Store); 151 152 auto *LastWiden = dyn_cast<VPWidenRecipe>(&*Iter++); 153 EXPECT_NE(nullptr, LastWiden); 154 EXPECT_EQ(VecBB->end(), Iter); 155 } 156 157 } // namespace 158 } // namespace llvm 159