1 //===- llvm/unittest/Transforms/Vectorize/VPlanHCFGTest.cpp ---------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "../lib/Transforms/Vectorize/VPlan.h"
10 #include "../lib/Transforms/Vectorize/VPlanHCFGTransforms.h"
11 #include "VPlanTestBase.h"
12 #include "gtest/gtest.h"
17 class VPlanHCFGTest
: public VPlanTestBase
{};
19 TEST_F(VPlanHCFGTest
, testBuildHCFGInnerLoop
) {
20 const char *ModuleString
=
21 "define void @f(i32* %A, i64 %N) {\n"
23 " br label %for.body\n"
25 " %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
26 " %arr.idx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n"
27 " %l1 = load i32, i32* %arr.idx, align 4\n"
28 " %res = add i32 %l1, 10\n"
29 " store i32 %res, i32* %arr.idx, align 4\n"
30 " %indvars.iv.next = add i64 %indvars.iv, 1\n"
31 " %exitcond = icmp ne i64 %indvars.iv.next, %N\n"
32 " br i1 %exitcond, label %for.body, label %for.end\n"
37 Module
&M
= parseModule(ModuleString
);
39 Function
*F
= M
.getFunction("f");
40 BasicBlock
*LoopHeader
= F
->getEntryBlock().getSingleSuccessor();
41 auto Plan
= buildHCFG(LoopHeader
);
43 VPBasicBlock
*Entry
= Plan
->getEntry()->getEntryBasicBlock();
44 EXPECT_NE(nullptr, Entry
->getSingleSuccessor());
45 EXPECT_EQ(0u, Entry
->getNumPredecessors());
46 EXPECT_EQ(1u, Entry
->getNumSuccessors());
47 EXPECT_EQ(nullptr, Entry
->getCondBit());
49 VPBasicBlock
*VecBB
= Entry
->getSingleSuccessor()->getEntryBasicBlock();
50 EXPECT_EQ(7u, VecBB
->size());
51 EXPECT_EQ(2u, VecBB
->getNumPredecessors());
52 EXPECT_EQ(2u, VecBB
->getNumSuccessors());
54 auto Iter
= VecBB
->begin();
55 VPInstruction
*Phi
= dyn_cast
<VPInstruction
>(&*Iter
++);
56 EXPECT_EQ(Instruction::PHI
, Phi
->getOpcode());
58 VPInstruction
*Idx
= dyn_cast
<VPInstruction
>(&*Iter
++);
59 EXPECT_EQ(Instruction::GetElementPtr
, Idx
->getOpcode());
60 EXPECT_EQ(2u, Idx
->getNumOperands());
61 EXPECT_EQ(Phi
, Idx
->getOperand(1));
63 VPInstruction
*Load
= dyn_cast
<VPInstruction
>(&*Iter
++);
64 EXPECT_EQ(Instruction::Load
, Load
->getOpcode());
65 EXPECT_EQ(1u, Load
->getNumOperands());
66 EXPECT_EQ(Idx
, Load
->getOperand(0));
68 VPInstruction
*Add
= dyn_cast
<VPInstruction
>(&*Iter
++);
69 EXPECT_EQ(Instruction::Add
, Add
->getOpcode());
70 EXPECT_EQ(2u, Add
->getNumOperands());
71 EXPECT_EQ(Load
, Add
->getOperand(0));
73 VPInstruction
*Store
= dyn_cast
<VPInstruction
>(&*Iter
++);
74 EXPECT_EQ(Instruction::Store
, Store
->getOpcode());
75 EXPECT_EQ(2u, Store
->getNumOperands());
76 EXPECT_EQ(Add
, Store
->getOperand(0));
77 EXPECT_EQ(Idx
, Store
->getOperand(1));
79 VPInstruction
*IndvarAdd
= dyn_cast
<VPInstruction
>(&*Iter
++);
80 EXPECT_EQ(Instruction::Add
, IndvarAdd
->getOpcode());
81 EXPECT_EQ(2u, IndvarAdd
->getNumOperands());
82 EXPECT_EQ(Phi
, IndvarAdd
->getOperand(0));
84 VPInstruction
*ICmp
= dyn_cast
<VPInstruction
>(&*Iter
++);
85 EXPECT_EQ(Instruction::ICmp
, ICmp
->getOpcode());
86 EXPECT_EQ(2u, ICmp
->getNumOperands());
87 EXPECT_EQ(IndvarAdd
, ICmp
->getOperand(0));
88 EXPECT_EQ(VecBB
->getCondBit(), ICmp
);
90 LoopVectorizationLegality::InductionList Inductions
;
91 SmallPtrSet
<Instruction
*, 1> DeadInstructions
;
92 VPlanHCFGTransforms::VPInstructionsToVPRecipes(Plan
, &Inductions
,
96 TEST_F(VPlanHCFGTest
, testVPInstructionToVPRecipesInner
) {
97 const char *ModuleString
=
98 "define void @f(i32* %A, i64 %N) {\n"
100 " br label %for.body\n"
102 " %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
103 " %arr.idx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n"
104 " %l1 = load i32, i32* %arr.idx, align 4\n"
105 " %res = add i32 %l1, 10\n"
106 " store i32 %res, i32* %arr.idx, align 4\n"
107 " %indvars.iv.next = add i64 %indvars.iv, 1\n"
108 " %exitcond = icmp ne i64 %indvars.iv.next, %N\n"
109 " br i1 %exitcond, label %for.body, label %for.end\n"
114 Module
&M
= parseModule(ModuleString
);
116 Function
*F
= M
.getFunction("f");
117 BasicBlock
*LoopHeader
= F
->getEntryBlock().getSingleSuccessor();
118 auto Plan
= buildHCFG(LoopHeader
);
120 LoopVectorizationLegality::InductionList Inductions
;
121 SmallPtrSet
<Instruction
*, 1> DeadInstructions
;
122 VPlanHCFGTransforms::VPInstructionsToVPRecipes(Plan
, &Inductions
,
125 VPBlockBase
*Entry
= Plan
->getEntry()->getEntryBasicBlock();
126 EXPECT_NE(nullptr, Entry
->getSingleSuccessor());
127 EXPECT_EQ(0u, Entry
->getNumPredecessors());
128 EXPECT_EQ(1u, Entry
->getNumSuccessors());
130 VPBasicBlock
*VecBB
= Entry
->getSingleSuccessor()->getEntryBasicBlock();
131 EXPECT_EQ(6u, VecBB
->size());
132 EXPECT_EQ(2u, VecBB
->getNumPredecessors());
133 EXPECT_EQ(2u, VecBB
->getNumSuccessors());
135 auto Iter
= VecBB
->begin();
136 auto *Phi
= dyn_cast
<VPWidenPHIRecipe
>(&*Iter
++);
137 EXPECT_NE(nullptr, Phi
);
139 auto *Idx
= dyn_cast
<VPWidenRecipe
>(&*Iter
++);
140 EXPECT_NE(nullptr, Idx
);
142 auto *Load
= dyn_cast
<VPWidenMemoryInstructionRecipe
>(&*Iter
++);
143 EXPECT_NE(nullptr, Load
);
145 auto *Add
= dyn_cast
<VPWidenRecipe
>(&*Iter
++);
146 EXPECT_NE(nullptr, Add
);
148 auto *Store
= dyn_cast
<VPWidenMemoryInstructionRecipe
>(&*Iter
++);
149 EXPECT_NE(nullptr, Store
);
151 auto *LastWiden
= dyn_cast
<VPWidenRecipe
>(&*Iter
++);
152 EXPECT_NE(nullptr, LastWiden
);
153 EXPECT_EQ(VecBB
->end(), Iter
);