xref: /llvm-project/llvm/unittests/Transforms/Vectorize/VPlanSlpTest.cpp (revision 348d85a6c7950a5f14ee6c8741380b5876d99afd)
1 //===- llvm/unittest/Transforms/Vectorize/VPlanSlpTest.cpp ---------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "../lib/Transforms/Vectorize/VPlan.h"
10 #include "../lib/Transforms/Vectorize/VPlanHCFGBuilder.h"
11 #include "VPlanTestBase.h"
12 #include "llvm/Analysis/VectorUtils.h"
13 #include "gtest/gtest.h"
14 
15 namespace llvm {
16 namespace {
17 
18 class VPlanSlpTest : public VPlanTestBase {
19 protected:
20   TargetLibraryInfoImpl TLII;
21   TargetLibraryInfo TLI;
22   DataLayout DL;
23 
24   std::unique_ptr<AssumptionCache> AC;
25   std::unique_ptr<ScalarEvolution> SE;
26   std::unique_ptr<AAResults> AARes;
27   std::unique_ptr<BasicAAResult> BasicAA;
28   std::unique_ptr<LoopAccessInfo> LAI;
29   std::unique_ptr<PredicatedScalarEvolution> PSE;
30   std::unique_ptr<InterleavedAccessInfo> IAI;
31 
32   VPlanSlpTest()
33       : TLII(), TLI(TLII),
34         DL("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-"
35            "f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:"
36            "16:32:64-S128") {}
37 
38   VPInterleavedAccessInfo getInterleavedAccessInfo(Function &F, Loop *L,
39                                                    VPlan &Plan) {
40     AC.reset(new AssumptionCache(F));
41     SE.reset(new ScalarEvolution(F, TLI, *AC, *DT, *LI));
42     BasicAA.reset(new BasicAAResult(DL, F, TLI, *AC, &*DT, &*LI));
43     AARes.reset(new AAResults(TLI));
44     AARes->addAAResult(*BasicAA);
45     PSE.reset(new PredicatedScalarEvolution(*SE, *L));
46     LAI.reset(new LoopAccessInfo(L, &*SE, &TLI, &*AARes, &*DT, &*LI));
47     IAI.reset(new InterleavedAccessInfo(*PSE, L, &*DT, &*LI, &*LAI));
48     IAI->analyzeInterleaving(false);
49     return {Plan, *IAI};
50   }
51 };
52 
53 TEST_F(VPlanSlpTest, testSlpSimple_2) {
54   const char *ModuleString =
55       "%struct.Test = type { i32, i32 }\n"
56       "%struct.Test3 = type { i32, i32, i32 }\n"
57       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
58       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
59       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
60       "entry:\n"
61       "  br label %for.body\n"
62       "for.body:                                         ; preds = %for.body, "
63       "%entry\n"
64       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
65       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
66       "%indvars.iv, i32 0\n"
67       "  %vA0 = load i32, i32* %A0, align 4\n"
68       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
69       "%indvars.iv, i32 0\n"
70       "  %vB0 = load i32, i32* %B0, align 4\n"
71       "  %add0 = add nsw i32 %vA0, %vB0\n"
72       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
73       "%indvars.iv, i32 1\n"
74       "  %vA1 = load i32, i32* %A1, align 4\n"
75       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
76       "%indvars.iv, i32 1\n"
77       "  %vB1 = load i32, i32* %B1, align 4\n"
78       "  %add1 = add nsw i32 %vA1, %vB1\n"
79       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
80       "%indvars.iv, i32 0\n"
81       "  store i32 %add0, i32* %C0, align 4\n"
82       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
83       "%indvars.iv, i32 1\n"
84       "  store i32 %add1, i32* %C1, align 4\n"
85       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
86       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
87       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
88       "for.cond.cleanup:                                 ; preds = %for.body\n"
89       "  ret void\n"
90       "}\n";
91 
92   Module &M = parseModule(ModuleString);
93 
94   Function *F = M.getFunction("add_x2");
95   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
96   auto Plan = buildHCFG(LoopHeader);
97   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
98 
99   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
100   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
101   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
102 
103   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
104   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
105 
106   VPlanSlp Slp(VPIAI, *Body);
107   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
108   VPInstruction *CombinedStore = Slp.buildGraph(StoreRoot);
109   EXPECT_EQ(64u, Slp.getWidestBundleBits());
110   EXPECT_EQ(VPInstruction::SLPStore, CombinedStore->getOpcode());
111 
112   auto *CombinedAdd = cast<VPInstruction>(CombinedStore->getOperand(0));
113   EXPECT_EQ(Instruction::Add, CombinedAdd->getOpcode());
114 
115   auto *CombinedLoadA = cast<VPInstruction>(CombinedAdd->getOperand(0));
116   auto *CombinedLoadB = cast<VPInstruction>(CombinedAdd->getOperand(1));
117   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadA->getOpcode());
118   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadB->getOpcode());
119 
120   delete CombinedStore;
121   delete CombinedAdd;
122   delete CombinedLoadA;
123   delete CombinedLoadB;
124 }
125 
126 TEST_F(VPlanSlpTest, testSlpSimple_3) {
127   const char *ModuleString =
128       "%struct.Test = type { i32, i32 }\n"
129       "%struct.Test3 = type { i32, i32, i32 }\n"
130       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
131       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
132       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
133       "entry:\n"
134       "  br label %for.body\n"
135       "for.body:                                         ; preds = %for.body, "
136       "%entry\n"
137       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
138       "  %A0 = getelementptr %struct.Test, %struct.Test* %A, i64 "
139       "                      %indvars.iv, i32 0\n"
140       "  %vA0 = load i32, i32* %A0, align 4\n"
141       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
142       "                      %indvars.iv, i32 0\n"
143       "  %vB0 = load i32, i32* %B0, align 4\n"
144       "  %add0 = add nsw i32 %vA0, %vB0\n"
145       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
146       "                      %indvars.iv, i32 1\n"
147       "  %vA1 = load i32, i32* %A1, align 4\n"
148       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
149       "                      %indvars.iv, i32 1\n"
150       "  %vB1 = load i32, i32* %B1, align 4\n"
151       "  %add1 = add nsw i32 %vA1, %vB1\n"
152       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
153       "                      %indvars.iv, i32 0\n"
154       "  store i32 %add0, i32* %C0, align 4\n"
155       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
156       "                      %indvars.iv, i32 1\n"
157       "  store i32 %add1, i32* %C1, align 4\n"
158       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
159       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
160       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
161       "for.cond.cleanup:                                 ; preds = %for.body\n"
162       "  ret void\n"
163       "}\n";
164 
165   Module &M = parseModule(ModuleString);
166 
167   Function *F = M.getFunction("add_x2");
168   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
169   auto Plan = buildHCFG(LoopHeader);
170 
171   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
172   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
173   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
174 
175   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
176   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
177 
178   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
179 
180   VPlanSlp Slp(VPIAI, *Body);
181   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
182   VPInstruction *CombinedStore = Slp.buildGraph(StoreRoot);
183   EXPECT_EQ(64u, Slp.getWidestBundleBits());
184   EXPECT_EQ(VPInstruction::SLPStore, CombinedStore->getOpcode());
185 
186   auto *CombinedAdd = cast<VPInstruction>(CombinedStore->getOperand(0));
187   EXPECT_EQ(Instruction::Add, CombinedAdd->getOpcode());
188 
189   auto *CombinedLoadA = cast<VPInstruction>(CombinedAdd->getOperand(0));
190   auto *CombinedLoadB = cast<VPInstruction>(CombinedAdd->getOperand(1));
191   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadA->getOpcode());
192   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadB->getOpcode());
193 
194   VPInstruction *GetA = cast<VPInstruction>(&*std::next(Body->begin(), 1));
195   VPInstruction *GetB = cast<VPInstruction>(&*std::next(Body->begin(), 3));
196   EXPECT_EQ(GetA, CombinedLoadA->getOperand(0));
197   EXPECT_EQ(GetB, CombinedLoadB->getOperand(0));
198 
199   delete CombinedStore;
200   delete CombinedAdd;
201   delete CombinedLoadA;
202   delete CombinedLoadB;
203 }
204 
205 TEST_F(VPlanSlpTest, testSlpReuse_1) {
206   const char *ModuleString =
207       "%struct.Test = type { i32, i32 }\n"
208       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
209       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
210       "entry:\n"
211       "  br label %for.body\n"
212       "for.body:                                         ; preds = %for.body, "
213       "%entry\n"
214       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
215       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
216       "%indvars.iv, i32 0\n"
217       "  %vA0 = load i32, i32* %A0, align 4\n"
218       "  %add0 = add nsw i32 %vA0, %vA0\n"
219       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
220       "%indvars.iv, i32 1\n"
221       "  %vA1 = load i32, i32* %A1, align 4\n"
222       "  %add1 = add nsw i32 %vA1, %vA1\n"
223       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
224       "%indvars.iv, i32 0\n"
225       "  store i32 %add0, i32* %C0, align 4\n"
226       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
227       "%indvars.iv, i32 1\n"
228       "  store i32 %add1, i32* %C1, align 4\n"
229       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
230       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
231       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
232       "for.cond.cleanup:                                 ; preds = %for.body\n"
233       "  ret void\n"
234       "}\n";
235 
236   Module &M = parseModule(ModuleString);
237 
238   Function *F = M.getFunction("add_x2");
239   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
240   auto Plan = buildHCFG(LoopHeader);
241   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
242 
243   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
244   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
245   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
246 
247   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 8));
248   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 10));
249 
250   VPlanSlp Slp(VPIAI, *Body);
251   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
252   VPInstruction *CombinedStore = Slp.buildGraph(StoreRoot);
253   EXPECT_EQ(64u, Slp.getWidestBundleBits());
254   EXPECT_EQ(VPInstruction::SLPStore, CombinedStore->getOpcode());
255 
256   auto *CombinedAdd = cast<VPInstruction>(CombinedStore->getOperand(0));
257   EXPECT_EQ(Instruction::Add, CombinedAdd->getOpcode());
258 
259   auto *CombinedLoadA = cast<VPInstruction>(CombinedAdd->getOperand(0));
260   EXPECT_EQ(CombinedLoadA, CombinedAdd->getOperand(1));
261   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadA->getOpcode());
262 
263   delete CombinedStore;
264   delete CombinedAdd;
265   delete CombinedLoadA;
266 }
267 
268 TEST_F(VPlanSlpTest, testSlpReuse_2) {
269   const char *ModuleString =
270       "%struct.Test = type { i32, i32 }\n"
271       "define i32 @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
272       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
273       "entry:\n"
274       "  br label %for.body\n"
275       "for.body:                                         ; preds = %for.body, "
276       "%entry\n"
277       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
278       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
279       "%indvars.iv, i32 0\n"
280       "  %vA0 = load i32, i32* %A0, align 4\n"
281       "  %add0 = add nsw i32 %vA0, %vA0\n"
282       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
283       "%indvars.iv, i32 0\n"
284       "  store i32 %add0, i32* %C0, align 4\n"
285       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
286       "%indvars.iv, i32 1\n"
287       "  %vA1 = load i32, i32* %A1, align 4\n"
288       "  %add1 = add nsw i32 %vA1, %vA1\n"
289       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
290       "%indvars.iv, i32 1\n"
291       "  store i32 %add1, i32* %C1, align 4\n"
292       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
293       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
294       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
295       "for.cond.cleanup:                                 ; preds = %for.body\n"
296       "  ret i32 %vA1\n"
297       "}\n";
298 
299   Module &M = parseModule(ModuleString);
300 
301   Function *F = M.getFunction("add_x2");
302   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
303   auto Plan = buildHCFG(LoopHeader);
304   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
305 
306   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
307   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
308   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
309 
310   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 5));
311   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 10));
312 
313   VPlanSlp Slp(VPIAI, *Body);
314   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
315   Slp.buildGraph(StoreRoot);
316   EXPECT_FALSE(Slp.isCompletelySLP());
317 }
318 
319 static void checkReorderExample(VPInstruction *Store1, VPInstruction *Store2,
320                                 VPBasicBlock *Body,
321                                 VPInterleavedAccessInfo &&IAI) {
322   VPlanSlp Slp(IAI, *Body);
323   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
324   VPInstruction *CombinedStore = Slp.buildGraph(StoreRoot);
325 
326   EXPECT_TRUE(Slp.isCompletelySLP());
327   EXPECT_EQ(CombinedStore->getOpcode(), VPInstruction::SLPStore);
328 
329   VPInstruction *CombinedAdd =
330       cast<VPInstruction>(CombinedStore->getOperand(0));
331   EXPECT_EQ(CombinedAdd->getOpcode(), Instruction::Add);
332 
333   VPInstruction *CombinedMulAB =
334       cast<VPInstruction>(CombinedAdd->getOperand(0));
335   VPInstruction *CombinedMulCD =
336       cast<VPInstruction>(CombinedAdd->getOperand(1));
337   EXPECT_EQ(CombinedMulAB->getOpcode(), Instruction::Mul);
338 
339   VPInstruction *CombinedLoadA =
340       cast<VPInstruction>(CombinedMulAB->getOperand(0));
341   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadA->getOpcode());
342   VPInstruction *LoadvA0 = cast<VPInstruction>(&*std::next(Body->begin(), 2));
343   VPInstruction *LoadvA1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
344   EXPECT_EQ(LoadvA0->getOperand(0), CombinedLoadA->getOperand(0));
345   EXPECT_EQ(LoadvA1->getOperand(0), CombinedLoadA->getOperand(1));
346 
347   VPInstruction *CombinedLoadB =
348       cast<VPInstruction>(CombinedMulAB->getOperand(1));
349   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadB->getOpcode());
350   VPInstruction *LoadvB0 = cast<VPInstruction>(&*std::next(Body->begin(), 4));
351   VPInstruction *LoadvB1 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
352   EXPECT_EQ(LoadvB0->getOperand(0), CombinedLoadB->getOperand(0));
353   EXPECT_EQ(LoadvB1->getOperand(0), CombinedLoadB->getOperand(1));
354 
355   EXPECT_EQ(CombinedMulCD->getOpcode(), Instruction::Mul);
356 
357   VPInstruction *CombinedLoadC =
358       cast<VPInstruction>(CombinedMulCD->getOperand(0));
359   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadC->getOpcode());
360   VPInstruction *LoadvC0 = cast<VPInstruction>(&*std::next(Body->begin(), 7));
361   VPInstruction *LoadvC1 = cast<VPInstruction>(&*std::next(Body->begin(), 17));
362   EXPECT_EQ(LoadvC0->getOperand(0), CombinedLoadC->getOperand(0));
363   EXPECT_EQ(LoadvC1->getOperand(0), CombinedLoadC->getOperand(1));
364 
365   VPInstruction *CombinedLoadD =
366       cast<VPInstruction>(CombinedMulCD->getOperand(1));
367   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadD->getOpcode());
368   VPInstruction *LoadvD0 = cast<VPInstruction>(&*std::next(Body->begin(), 9));
369   VPInstruction *LoadvD1 = cast<VPInstruction>(&*std::next(Body->begin(), 19));
370   EXPECT_EQ(LoadvD0->getOperand(0), CombinedLoadD->getOperand(0));
371   EXPECT_EQ(LoadvD1->getOperand(0), CombinedLoadD->getOperand(1));
372 
373   delete CombinedStore;
374   delete CombinedAdd;
375   delete CombinedMulAB;
376   delete CombinedMulCD;
377   delete CombinedLoadA;
378   delete CombinedLoadB;
379   delete CombinedLoadC;
380   delete CombinedLoadD;
381 }
382 
383 TEST_F(VPlanSlpTest, testSlpReorder_1) {
384   LLVMContext Ctx;
385   const char *ModuleString =
386       "%struct.Test = type { i32, i32 }\n"
387       "define void @add_x3(%struct.Test* %A, %struct.Test* %B, %struct.Test* "
388       "%C,  %struct.Test* %D,  %struct.Test* %E)  {\n"
389       "entry:\n"
390       "  br label %for.body\n"
391       "for.body:                                         ; preds = %for.body, "
392       "%entry\n"
393       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
394       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
395       "%indvars.iv, i32 0\n"
396       "  %vA0 = load i32, i32* %A0, align 4\n"
397       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
398       "%indvars.iv, i32 0\n"
399       "  %vB0 = load i32, i32* %B0, align 4\n"
400       "  %mul11 = mul nsw i32 %vA0, %vB0\n"
401       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
402       "%indvars.iv, i32 0\n"
403       "  %vC0 = load i32, i32* %C0, align 4\n"
404       "  %D0 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
405       "%indvars.iv, i32 0\n"
406       "  %vD0 = load i32, i32* %D0, align 4\n"
407       "  %mul12 = mul nsw i32 %vC0, %vD0\n"
408       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
409       "%indvars.iv, i32 1\n"
410       "  %vA1 = load i32, i32* %A1, align 4\n"
411       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
412       "%indvars.iv, i32 1\n"
413       "  %vB1 = load i32, i32* %B1, align 4\n"
414       "  %mul21 = mul nsw i32 %vA1, %vB1\n"
415       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
416       "%indvars.iv, i32 1\n"
417       "  %vC1 = load i32, i32* %C1, align 4\n"
418       "  %D1 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
419       "%indvars.iv, i32 1\n"
420       "  %vD1 = load i32, i32* %D1, align 4\n"
421       "  %mul22 = mul nsw i32 %vC1, %vD1\n"
422       "  %add1 = add nsw i32 %mul11, %mul12\n"
423       "  %add2 = add nsw i32 %mul22, %mul21\n"
424       "  %E0 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
425       "%indvars.iv, i32 0\n"
426       "  store i32 %add1, i32* %E0, align 4\n"
427       "  %E1 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
428       "%indvars.iv, i32 1\n"
429       "  store i32 %add2, i32* %E1, align 4\n"
430       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
431       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
432       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
433       "for.cond.cleanup:                                 ; preds = %for.body\n"
434       "  ret void\n"
435       "}\n";
436 
437   Module &M = parseModule(ModuleString);
438 
439   Function *F = M.getFunction("add_x3");
440   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
441   auto Plan = buildHCFG(LoopHeader);
442 
443   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
444   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
445   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
446 
447   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 24));
448   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 26));
449 
450   checkReorderExample(
451       Store1, Store2, Body,
452       getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan));
453 }
454 
455 TEST_F(VPlanSlpTest, testSlpReorder_2) {
456   LLVMContext Ctx;
457   const char *ModuleString =
458       "%struct.Test = type { i32, i32 }\n"
459       "define void @add_x3(%struct.Test* %A, %struct.Test* %B, %struct.Test* "
460       "%C,  %struct.Test* %D,  %struct.Test* %E)  {\n"
461       "entry:\n"
462       "  br label %for.body\n"
463       "for.body:                                         ; preds = %for.body, "
464       "%entry\n"
465       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
466       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
467       "%indvars.iv, i32 0\n"
468       "  %vA0 = load i32, i32* %A0, align 4\n"
469       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
470       "%indvars.iv, i32 0\n"
471       "  %vB0 = load i32, i32* %B0, align 4\n"
472       "  %mul11 = mul nsw i32 %vA0, %vB0\n"
473       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
474       "%indvars.iv, i32 0\n"
475       "  %vC0 = load i32, i32* %C0, align 4\n"
476       "  %D0 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
477       "%indvars.iv, i32 0\n"
478       "  %vD0 = load i32, i32* %D0, align 4\n"
479       "  %mul12 = mul nsw i32 %vC0, %vD0\n"
480       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
481       "%indvars.iv, i32 1\n"
482       "  %vA1 = load i32, i32* %A1, align 4\n"
483       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
484       "%indvars.iv, i32 1\n"
485       "  %vB1 = load i32, i32* %B1, align 4\n"
486       "  %mul21 = mul nsw i32 %vB1, %vA1\n"
487       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
488       "%indvars.iv, i32 1\n"
489       "  %vC1 = load i32, i32* %C1, align 4\n"
490       "  %D1 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
491       "%indvars.iv, i32 1\n"
492       "  %vD1 = load i32, i32* %D1, align 4\n"
493       "  %mul22 = mul nsw i32 %vD1, %vC1\n"
494       "  %add1 = add nsw i32 %mul11, %mul12\n"
495       "  %add2 = add nsw i32 %mul22, %mul21\n"
496       "  %E0 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
497       "%indvars.iv, i32 0\n"
498       "  store i32 %add1, i32* %E0, align 4\n"
499       "  %E1 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
500       "%indvars.iv, i32 1\n"
501       "  store i32 %add2, i32* %E1, align 4\n"
502       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
503       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
504       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
505       "for.cond.cleanup:                                 ; preds = %for.body\n"
506       "  ret void\n"
507       "}\n";
508 
509   Module &M = parseModule(ModuleString);
510 
511   Function *F = M.getFunction("add_x3");
512   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
513   auto Plan = buildHCFG(LoopHeader);
514 
515   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
516   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
517   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
518 
519   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 24));
520   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 26));
521 
522   checkReorderExample(
523       Store1, Store2, Body,
524       getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan));
525 }
526 
527 TEST_F(VPlanSlpTest, testSlpReorder_3) {
528   LLVMContext Ctx;
529   const char *ModuleString =
530       "%struct.Test = type { i32, i32 }\n"
531       "define void @add_x3(%struct.Test* %A, %struct.Test* %B, %struct.Test* "
532       "%C,  %struct.Test* %D,  %struct.Test* %E)  {\n"
533       "entry:\n"
534       "  br label %for.body\n"
535       "for.body:                                         ; preds = %for.body, "
536       "%entry\n"
537       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
538       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
539       "%indvars.iv, i32 1\n"
540       "  %vA1 = load i32, i32* %A1, align 4\n"
541       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
542       "%indvars.iv, i32 0\n"
543       "  %vB0 = load i32, i32* %B0, align 4\n"
544       "  %mul11 = mul nsw i32 %vA1, %vB0\n"
545       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
546       "%indvars.iv, i32 0\n"
547       "  %vC0 = load i32, i32* %C0, align 4\n"
548       "  %D0 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
549       "%indvars.iv, i32 0\n"
550       "  %vD0 = load i32, i32* %D0, align 4\n"
551       "  %mul12 = mul nsw i32 %vC0, %vD0\n"
552       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
553       "%indvars.iv, i32 0\n"
554       "  %vA0 = load i32, i32* %A0, align 4\n"
555       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
556       "%indvars.iv, i32 1\n"
557       "  %vB1 = load i32, i32* %B1, align 4\n"
558       "  %mul21 = mul nsw i32 %vB1, %vA0\n"
559       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
560       "%indvars.iv, i32 1\n"
561       "  %vC1 = load i32, i32* %C1, align 4\n"
562       "  %D1 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
563       "%indvars.iv, i32 1\n"
564       "  %vD1 = load i32, i32* %D1, align 4\n"
565       "  %mul22 = mul nsw i32 %vD1, %vC1\n"
566       "  %add1 = add nsw i32 %mul11, %mul12\n"
567       "  %add2 = add nsw i32 %mul22, %mul21\n"
568       "  %E0 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
569       "%indvars.iv, i32 0\n"
570       "  store i32 %add1, i32* %E0, align 4\n"
571       "  %E1 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
572       "%indvars.iv, i32 1\n"
573       "  store i32 %add2, i32* %E1, align 4\n"
574       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
575       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
576       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
577       "for.cond.cleanup:                                 ; preds = %for.body\n"
578       "  ret void\n"
579       "}\n";
580 
581   Module &M = parseModule(ModuleString);
582 
583   Function *F = M.getFunction("add_x3");
584   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
585   auto Plan = buildHCFG(LoopHeader);
586 
587   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
588   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
589   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
590 
591   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 24));
592   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 26));
593 
594   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
595   VPlanSlp Slp(VPIAI, *Body);
596   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
597   EXPECT_EQ(nullptr, Slp.buildGraph(StoreRoot));
598 
599   // FIXME Need to select better first value for lane0.
600   EXPECT_FALSE(Slp.isCompletelySLP());
601 }
602 
603 TEST_F(VPlanSlpTest, testSlpReorder_4) {
604   LLVMContext Ctx;
605   const char *ModuleString =
606       "%struct.Test = type { i32, i32 }\n"
607       "define void @add_x3(%struct.Test* %A, %struct.Test* %B, %struct.Test* "
608       "%C,  %struct.Test* %D,  %struct.Test* %E)  {\n"
609       "entry:\n"
610       "  br label %for.body\n"
611       "for.body:                                         ; preds = %for.body, "
612       "%entry\n"
613       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
614       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
615       "%indvars.iv, i32 0\n"
616       "  %vA0 = load i32, i32* %A0, align 4\n"
617       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
618       "%indvars.iv, i32 0\n"
619       "  %vB0 = load i32, i32* %B0, align 4\n"
620       "  %mul11 = mul nsw i32 %vA0, %vB0\n"
621       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
622       "%indvars.iv, i32 0\n"
623       "  %vC0 = load i32, i32* %C0, align 4\n"
624       "  %D0 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
625       "%indvars.iv, i32 0\n"
626       "  %vD0 = load i32, i32* %D0, align 4\n"
627       "  %mul12 = mul nsw i32 %vC0, %vD0\n"
628       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
629       "%indvars.iv, i32 1\n"
630       "  %vA1 = load i32, i32* %A1, align 4\n"
631       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
632       "%indvars.iv, i32 1\n"
633       "  %vB1 = load i32, i32* %B1, align 4\n"
634       "  %mul21 = mul nsw i32 %vA1, %vB1\n"
635       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
636       "%indvars.iv, i32 1\n"
637       "  %vC1 = load i32, i32* %C1, align 4\n"
638       "  %D1 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
639       "%indvars.iv, i32 1\n"
640       "  %vD1 = load i32, i32* %D1, align 4\n"
641       "  %mul22 = mul nsw i32 %vC1, %vD1\n"
642       "  %add1 = add nsw i32 %mul11, %mul12\n"
643       "  %add2 = add nsw i32 %mul22, %mul21\n"
644       "  %E0 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
645       "%indvars.iv, i32 0\n"
646       "  store i32 %add1, i32* %E0, align 4\n"
647       "  %E1 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
648       "%indvars.iv, i32 1\n"
649       "  store i32 %add2, i32* %E1, align 4\n"
650       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
651       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
652       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
653       "for.cond.cleanup:                                 ; preds = %for.body\n"
654       "  ret void\n"
655       "}\n";
656 
657   Module &M = parseModule(ModuleString);
658 
659   Function *F = M.getFunction("add_x3");
660   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
661   auto Plan = buildHCFG(LoopHeader);
662 
663   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
664   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
665   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
666 
667   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 24));
668   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 26));
669 
670   checkReorderExample(
671       Store1, Store2, Body,
672       getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan));
673 }
674 
675 // Make sure we do not combine instructions with operands in different BBs.
676 TEST_F(VPlanSlpTest, testInstrsInDifferentBBs) {
677   const char *ModuleString =
678       "%struct.Test = type { i32, i32 }\n"
679       "%struct.Test3 = type { i32, i32, i32 }\n"
680       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
681       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
682       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
683       "entry:\n"
684       "  br label %for.body\n"
685       "for.body:                                         ; preds = %for.body, "
686       "%entry\n"
687       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
688       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
689       "%indvars.iv, i32 0\n"
690       "  %vA0 = load i32, i32* %A0, align 4\n"
691       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
692       "%indvars.iv, i32 0\n"
693       "  %vB0 = load i32, i32* %B0, align 4\n"
694       "  %add0 = add nsw i32 %vA0, %vB0\n"
695       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
696       "%indvars.iv, i32 1\n"
697       "  %vA1 = load i32, i32* %A1, align 4\n"
698       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
699       "%indvars.iv, i32 1\n"
700       "  br label %bb2\n"
701       "bb2:\n"
702       "  %vB1 = load i32, i32* %B1, align 4\n"
703       "  %add1 = add nsw i32 %vA1, %vB1\n"
704       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
705       "%indvars.iv, i32 0\n"
706       "  store i32 %add0, i32* %C0, align 4\n"
707       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
708       "%indvars.iv, i32 1\n"
709       "  store i32 %add1, i32* %C1, align 4\n"
710       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
711       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
712       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
713       "for.cond.cleanup:                                 ; preds = %for.body\n"
714       "  ret void\n"
715       "}\n";
716 
717   Module &M = parseModule(ModuleString);
718 
719   Function *F = M.getFunction("add_x2");
720   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
721   auto Plan = buildHCFG(LoopHeader);
722   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
723 
724   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
725   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
726   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
727   VPBasicBlock *BB2 = Body->getSingleSuccessor()->getEntryBasicBlock();
728 
729   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(BB2->begin(), 3));
730   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(BB2->begin(), 5));
731 
732   VPlanSlp Slp(VPIAI, *BB2);
733   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
734   EXPECT_EQ(nullptr, Slp.buildGraph(StoreRoot));
735   EXPECT_EQ(0u, Slp.getWidestBundleBits());
736 }
737 
738 // Make sure we do not combine instructions with operands in different BBs.
739 TEST_F(VPlanSlpTest, testInstrsInDifferentBBs2) {
740   const char *ModuleString =
741       "%struct.Test = type { i32, i32 }\n"
742       "%struct.Test3 = type { i32, i32, i32 }\n"
743       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
744       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
745       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
746       "entry:\n"
747       "  br label %for.body\n"
748       "for.body:                                         ; preds = %for.body, "
749       "%entry\n"
750       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
751       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
752       "%indvars.iv, i32 0\n"
753       "  %vA0 = load i32, i32* %A0, align 4\n"
754       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
755       "%indvars.iv, i32 0\n"
756       "  %vB0 = load i32, i32* %B0, align 4\n"
757       "  %add0 = add nsw i32 %vA0, %vB0\n"
758       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
759       "%indvars.iv, i32 1\n"
760       "  %vA1 = load i32, i32* %A1, align 4\n"
761       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
762       "%indvars.iv, i32 1\n"
763       "  %vB1 = load i32, i32* %B1, align 4\n"
764       "  %add1 = add nsw i32 %vA1, %vB1\n"
765       "  br label %bb2\n"
766       "bb2:\n"
767       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
768       "%indvars.iv, i32 0\n"
769       "  store i32 %add0, i32* %C0, align 4\n"
770       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
771       "%indvars.iv, i32 1\n"
772       "  store i32 %add1, i32* %C1, align 4\n"
773       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
774       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
775       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
776       "for.cond.cleanup:                                 ; preds = %for.body\n"
777       "  ret void\n"
778       "}\n";
779 
780   Module &M = parseModule(ModuleString);
781 
782   Function *F = M.getFunction("add_x2");
783   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
784   auto Plan = buildHCFG(LoopHeader);
785   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
786 
787   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
788   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
789   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
790   VPBasicBlock *BB2 = Body->getSingleSuccessor()->getEntryBasicBlock();
791 
792   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(BB2->begin(), 1));
793   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(BB2->begin(), 3));
794 
795   VPlanSlp Slp(VPIAI, *BB2);
796   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
797   EXPECT_EQ(nullptr, Slp.buildGraph(StoreRoot));
798   EXPECT_EQ(0u, Slp.getWidestBundleBits());
799 }
800 
801 TEST_F(VPlanSlpTest, testSlpAtomicLoad) {
802   const char *ModuleString =
803       "%struct.Test = type { i32, i32 }\n"
804       "%struct.Test3 = type { i32, i32, i32 }\n"
805       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
806       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
807       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
808       "entry:\n"
809       "  br label %for.body\n"
810       "for.body:                                         ; preds = %for.body, "
811       "%entry\n"
812       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
813       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
814       "%indvars.iv, i32 0\n"
815       "  %vA0 = load atomic i32, i32* %A0 monotonic, align 4\n"
816       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
817       "%indvars.iv, i32 0\n"
818       "  %vB0 = load i32, i32* %B0, align 4\n"
819       "  %add0 = add nsw i32 %vA0, %vB0\n"
820       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
821       "%indvars.iv, i32 1\n"
822       "  %vA1 = load i32, i32* %A1, align 4\n"
823       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
824       "%indvars.iv, i32 1\n"
825       "  %vB1 = load i32, i32* %B1, align 4\n"
826       "  %add1 = add nsw i32 %vA1, %vB1\n"
827       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
828       "%indvars.iv, i32 0\n"
829       "  store i32 %add0, i32* %C0, align 4\n"
830       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
831       "%indvars.iv, i32 1\n"
832       "  store i32 %add1, i32* %C1, align 4\n"
833       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
834       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
835       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
836       "for.cond.cleanup:                                 ; preds = %for.body\n"
837       "  ret void\n"
838       "}\n";
839 
840   Module &M = parseModule(ModuleString);
841 
842   Function *F = M.getFunction("add_x2");
843   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
844   auto Plan = buildHCFG(LoopHeader);
845   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
846 
847   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
848   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
849   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
850 
851   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
852   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
853 
854   VPlanSlp Slp(VPIAI, *Body);
855   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
856   EXPECT_EQ(nullptr, Slp.buildGraph(StoreRoot));
857   EXPECT_FALSE(Slp.isCompletelySLP());
858 }
859 
860 TEST_F(VPlanSlpTest, testSlpAtomicStore) {
861   const char *ModuleString =
862       "%struct.Test = type { i32, i32 }\n"
863       "%struct.Test3 = type { i32, i32, i32 }\n"
864       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
865       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
866       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
867       "entry:\n"
868       "  br label %for.body\n"
869       "for.body:                                         ; preds = %for.body, "
870       "%entry\n"
871       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
872       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
873       "%indvars.iv, i32 0\n"
874       "  %vA0 = load i32, i32* %A0, align 4\n"
875       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
876       "%indvars.iv, i32 0\n"
877       "  %vB0 = load i32, i32* %B0, align 4\n"
878       "  %add0 = add nsw i32 %vA0, %vB0\n"
879       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
880       "%indvars.iv, i32 1\n"
881       "  %vA1 = load i32, i32* %A1, align 4\n"
882       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
883       "%indvars.iv, i32 1\n"
884       "  %vB1 = load i32, i32* %B1, align 4\n"
885       "  %add1 = add nsw i32 %vA1, %vB1\n"
886       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
887       "%indvars.iv, i32 0\n"
888       "  store atomic i32 %add0, i32* %C0 monotonic, align 4\n"
889       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
890       "%indvars.iv, i32 1\n"
891       "  store i32 %add1, i32* %C1, align 4\n"
892       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
893       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
894       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
895       "for.cond.cleanup:                                 ; preds = %for.body\n"
896       "  ret void\n"
897       "}\n";
898 
899   Module &M = parseModule(ModuleString);
900 
901   Function *F = M.getFunction("add_x2");
902   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
903   auto Plan = buildHCFG(LoopHeader);
904   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
905 
906   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
907   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
908   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
909 
910   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
911   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
912 
913   VPlanSlp Slp(VPIAI, *Body);
914   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
915   Slp.buildGraph(StoreRoot);
916   EXPECT_FALSE(Slp.isCompletelySLP());
917 }
918 
919 } // namespace
920 } // namespace llvm
921