109e516c5SFlorian Hahn //===- llvm/unittest/Transforms/Vectorize/VPlanSlpTest.cpp ---------------===//
209e516c5SFlorian Hahn //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609e516c5SFlorian Hahn //
709e516c5SFlorian Hahn //===----------------------------------------------------------------------===//
809e516c5SFlorian Hahn 
909e516c5SFlorian Hahn #include "../lib/Transforms/Vectorize/VPlan.h"
1009e516c5SFlorian Hahn #include "../lib/Transforms/Vectorize/VPlanHCFGBuilder.h"
1109e516c5SFlorian Hahn #include "VPlanTestBase.h"
122ce38b3fSdfukalov #include "llvm/Analysis/TargetLibraryInfo.h"
1309e516c5SFlorian Hahn #include "llvm/Analysis/VectorUtils.h"
1409e516c5SFlorian Hahn #include "gtest/gtest.h"
1509e516c5SFlorian Hahn 
1609e516c5SFlorian Hahn namespace llvm {
1709e516c5SFlorian Hahn namespace {
1809e516c5SFlorian Hahn 
1909e516c5SFlorian Hahn class VPlanSlpTest : public VPlanTestBase {
2009e516c5SFlorian Hahn protected:
2109e516c5SFlorian Hahn   TargetLibraryInfoImpl TLII;
2209e516c5SFlorian Hahn   TargetLibraryInfo TLI;
2309e516c5SFlorian Hahn   DataLayout DL;
2409e516c5SFlorian Hahn 
2509e516c5SFlorian Hahn   std::unique_ptr<AssumptionCache> AC;
2609e516c5SFlorian Hahn   std::unique_ptr<ScalarEvolution> SE;
2709e516c5SFlorian Hahn   std::unique_ptr<AAResults> AARes;
2809e516c5SFlorian Hahn   std::unique_ptr<BasicAAResult> BasicAA;
2909e516c5SFlorian Hahn   std::unique_ptr<LoopAccessInfo> LAI;
3009e516c5SFlorian Hahn   std::unique_ptr<PredicatedScalarEvolution> PSE;
3109e516c5SFlorian Hahn   std::unique_ptr<InterleavedAccessInfo> IAI;
3209e516c5SFlorian Hahn 
VPlanSlpTest()3309e516c5SFlorian Hahn   VPlanSlpTest()
3409e516c5SFlorian Hahn       : TLII(), TLI(TLII),
3509e516c5SFlorian Hahn         DL("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-"
3609e516c5SFlorian Hahn            "f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:"
3709e516c5SFlorian Hahn            "16:32:64-S128") {}
3809e516c5SFlorian Hahn 
getInterleavedAccessInfo(Function & F,Loop * L,VPlan & Plan)3909e516c5SFlorian Hahn   VPInterleavedAccessInfo getInterleavedAccessInfo(Function &F, Loop *L,
4009e516c5SFlorian Hahn                                                    VPlan &Plan) {
4109e516c5SFlorian Hahn     AC.reset(new AssumptionCache(F));
4209e516c5SFlorian Hahn     SE.reset(new ScalarEvolution(F, TLI, *AC, *DT, *LI));
43a6074b09SMax Kazantsev     BasicAA.reset(new BasicAAResult(DL, F, TLI, *AC, &*DT));
4409e516c5SFlorian Hahn     AARes.reset(new AAResults(TLI));
4509e516c5SFlorian Hahn     AARes->addAAResult(*BasicAA);
4609e516c5SFlorian Hahn     PSE.reset(new PredicatedScalarEvolution(*SE, *L));
4709e516c5SFlorian Hahn     LAI.reset(new LoopAccessInfo(L, &*SE, &TLI, &*AARes, &*DT, &*LI));
4809e516c5SFlorian Hahn     IAI.reset(new InterleavedAccessInfo(*PSE, L, &*DT, &*LI, &*LAI));
4909e516c5SFlorian Hahn     IAI->analyzeInterleaving(false);
5009e516c5SFlorian Hahn     return {Plan, *IAI};
5109e516c5SFlorian Hahn   }
5209e516c5SFlorian Hahn };
5309e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpSimple_2)5409e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpSimple_2) {
5509e516c5SFlorian Hahn   const char *ModuleString =
5609e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
5709e516c5SFlorian Hahn       "%struct.Test3 = type { i32, i32, i32 }\n"
5809e516c5SFlorian Hahn       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
5909e516c5SFlorian Hahn       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
6009e516c5SFlorian Hahn       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
6109e516c5SFlorian Hahn       "entry:\n"
6209e516c5SFlorian Hahn       "  br label %for.body\n"
6309e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
6409e516c5SFlorian Hahn       "%entry\n"
6509e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
6609e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
6709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
6809e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
6909e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
7009e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
7109e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
7209e516c5SFlorian Hahn       "  %add0 = add nsw i32 %vA0, %vB0\n"
7309e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
7409e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
7509e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
7609e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
7709e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
7809e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
7909e516c5SFlorian Hahn       "  %add1 = add nsw i32 %vA1, %vB1\n"
8009e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
8109e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
8209e516c5SFlorian Hahn       "  store i32 %add0, i32* %C0, align 4\n"
8309e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
8409e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
8509e516c5SFlorian Hahn       "  store i32 %add1, i32* %C1, align 4\n"
8609e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
8709e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
8809e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
8909e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
9009e516c5SFlorian Hahn       "  ret void\n"
9109e516c5SFlorian Hahn       "}\n";
9209e516c5SFlorian Hahn 
9309e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
9409e516c5SFlorian Hahn 
9509e516c5SFlorian Hahn   Function *F = M.getFunction("add_x2");
9609e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
9709e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
9809e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
9909e516c5SFlorian Hahn 
10009e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
10109e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
10209e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
10309e516c5SFlorian Hahn 
10409e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
10509e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
10609e516c5SFlorian Hahn 
10709e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *Body);
10809e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
10909e516c5SFlorian Hahn   VPInstruction *CombinedStore = Slp.buildGraph(StoreRoot);
11009e516c5SFlorian Hahn   EXPECT_EQ(64u, Slp.getWidestBundleBits());
11109e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPStore, CombinedStore->getOpcode());
11209e516c5SFlorian Hahn 
11309e516c5SFlorian Hahn   auto *CombinedAdd = cast<VPInstruction>(CombinedStore->getOperand(0));
11409e516c5SFlorian Hahn   EXPECT_EQ(Instruction::Add, CombinedAdd->getOpcode());
11509e516c5SFlorian Hahn 
11609e516c5SFlorian Hahn   auto *CombinedLoadA = cast<VPInstruction>(CombinedAdd->getOperand(0));
11709e516c5SFlorian Hahn   auto *CombinedLoadB = cast<VPInstruction>(CombinedAdd->getOperand(1));
11809e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadA->getOpcode());
11909e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadB->getOpcode());
120348d85a6SFlorian Hahn 
121348d85a6SFlorian Hahn   delete CombinedStore;
122348d85a6SFlorian Hahn   delete CombinedAdd;
123348d85a6SFlorian Hahn   delete CombinedLoadA;
124348d85a6SFlorian Hahn   delete CombinedLoadB;
12509e516c5SFlorian Hahn }
12609e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpSimple_3)12709e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpSimple_3) {
12809e516c5SFlorian Hahn   const char *ModuleString =
12909e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
13009e516c5SFlorian Hahn       "%struct.Test3 = type { i32, i32, i32 }\n"
13109e516c5SFlorian Hahn       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
13209e516c5SFlorian Hahn       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
13309e516c5SFlorian Hahn       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
13409e516c5SFlorian Hahn       "entry:\n"
13509e516c5SFlorian Hahn       "  br label %for.body\n"
13609e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
13709e516c5SFlorian Hahn       "%entry\n"
13809e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
13909e516c5SFlorian Hahn       "  %A0 = getelementptr %struct.Test, %struct.Test* %A, i64 "
14009e516c5SFlorian Hahn       "                      %indvars.iv, i32 0\n"
14109e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
14209e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
14309e516c5SFlorian Hahn       "                      %indvars.iv, i32 0\n"
14409e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
14509e516c5SFlorian Hahn       "  %add0 = add nsw i32 %vA0, %vB0\n"
14609e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
14709e516c5SFlorian Hahn       "                      %indvars.iv, i32 1\n"
14809e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
14909e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
15009e516c5SFlorian Hahn       "                      %indvars.iv, i32 1\n"
15109e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
15209e516c5SFlorian Hahn       "  %add1 = add nsw i32 %vA1, %vB1\n"
15309e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
15409e516c5SFlorian Hahn       "                      %indvars.iv, i32 0\n"
15509e516c5SFlorian Hahn       "  store i32 %add0, i32* %C0, align 4\n"
15609e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
15709e516c5SFlorian Hahn       "                      %indvars.iv, i32 1\n"
15809e516c5SFlorian Hahn       "  store i32 %add1, i32* %C1, align 4\n"
15909e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
16009e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
16109e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
16209e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
16309e516c5SFlorian Hahn       "  ret void\n"
16409e516c5SFlorian Hahn       "}\n";
16509e516c5SFlorian Hahn 
16609e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
16709e516c5SFlorian Hahn 
16809e516c5SFlorian Hahn   Function *F = M.getFunction("add_x2");
16909e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
17009e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
17109e516c5SFlorian Hahn 
17209e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
17309e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
17409e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
17509e516c5SFlorian Hahn 
17609e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
17709e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
17809e516c5SFlorian Hahn 
17909e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
18009e516c5SFlorian Hahn 
18109e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *Body);
18209e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
18309e516c5SFlorian Hahn   VPInstruction *CombinedStore = Slp.buildGraph(StoreRoot);
18409e516c5SFlorian Hahn   EXPECT_EQ(64u, Slp.getWidestBundleBits());
18509e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPStore, CombinedStore->getOpcode());
18609e516c5SFlorian Hahn 
18709e516c5SFlorian Hahn   auto *CombinedAdd = cast<VPInstruction>(CombinedStore->getOperand(0));
18809e516c5SFlorian Hahn   EXPECT_EQ(Instruction::Add, CombinedAdd->getOpcode());
18909e516c5SFlorian Hahn 
19009e516c5SFlorian Hahn   auto *CombinedLoadA = cast<VPInstruction>(CombinedAdd->getOperand(0));
19109e516c5SFlorian Hahn   auto *CombinedLoadB = cast<VPInstruction>(CombinedAdd->getOperand(1));
19209e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadA->getOpcode());
19309e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadB->getOpcode());
19409e516c5SFlorian Hahn 
19509e516c5SFlorian Hahn   VPInstruction *GetA = cast<VPInstruction>(&*std::next(Body->begin(), 1));
19609e516c5SFlorian Hahn   VPInstruction *GetB = cast<VPInstruction>(&*std::next(Body->begin(), 3));
19709e516c5SFlorian Hahn   EXPECT_EQ(GetA, CombinedLoadA->getOperand(0));
19809e516c5SFlorian Hahn   EXPECT_EQ(GetB, CombinedLoadB->getOperand(0));
199348d85a6SFlorian Hahn 
200348d85a6SFlorian Hahn   delete CombinedStore;
201348d85a6SFlorian Hahn   delete CombinedAdd;
202348d85a6SFlorian Hahn   delete CombinedLoadA;
203348d85a6SFlorian Hahn   delete CombinedLoadB;
20409e516c5SFlorian Hahn }
20509e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpReuse_1)20609e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpReuse_1) {
20709e516c5SFlorian Hahn   const char *ModuleString =
20809e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
20909e516c5SFlorian Hahn       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
21009e516c5SFlorian Hahn       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
21109e516c5SFlorian Hahn       "entry:\n"
21209e516c5SFlorian Hahn       "  br label %for.body\n"
21309e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
21409e516c5SFlorian Hahn       "%entry\n"
21509e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
21609e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
21709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
21809e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
21909e516c5SFlorian Hahn       "  %add0 = add nsw i32 %vA0, %vA0\n"
22009e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
22109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
22209e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
22309e516c5SFlorian Hahn       "  %add1 = add nsw i32 %vA1, %vA1\n"
22409e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
22509e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
22609e516c5SFlorian Hahn       "  store i32 %add0, i32* %C0, align 4\n"
22709e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
22809e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
22909e516c5SFlorian Hahn       "  store i32 %add1, i32* %C1, align 4\n"
23009e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
23109e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
23209e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
23309e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
23409e516c5SFlorian Hahn       "  ret void\n"
23509e516c5SFlorian Hahn       "}\n";
23609e516c5SFlorian Hahn 
23709e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
23809e516c5SFlorian Hahn 
23909e516c5SFlorian Hahn   Function *F = M.getFunction("add_x2");
24009e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
24109e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
24209e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
24309e516c5SFlorian Hahn 
24409e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
24509e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
24609e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
24709e516c5SFlorian Hahn 
24809e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 8));
24909e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 10));
25009e516c5SFlorian Hahn 
25109e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *Body);
25209e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
25309e516c5SFlorian Hahn   VPInstruction *CombinedStore = Slp.buildGraph(StoreRoot);
25409e516c5SFlorian Hahn   EXPECT_EQ(64u, Slp.getWidestBundleBits());
25509e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPStore, CombinedStore->getOpcode());
25609e516c5SFlorian Hahn 
25709e516c5SFlorian Hahn   auto *CombinedAdd = cast<VPInstruction>(CombinedStore->getOperand(0));
25809e516c5SFlorian Hahn   EXPECT_EQ(Instruction::Add, CombinedAdd->getOpcode());
25909e516c5SFlorian Hahn 
26009e516c5SFlorian Hahn   auto *CombinedLoadA = cast<VPInstruction>(CombinedAdd->getOperand(0));
26109e516c5SFlorian Hahn   EXPECT_EQ(CombinedLoadA, CombinedAdd->getOperand(1));
26209e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadA->getOpcode());
263348d85a6SFlorian Hahn 
264348d85a6SFlorian Hahn   delete CombinedStore;
265348d85a6SFlorian Hahn   delete CombinedAdd;
266348d85a6SFlorian Hahn   delete CombinedLoadA;
26709e516c5SFlorian Hahn }
26809e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpReuse_2)26909e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpReuse_2) {
27009e516c5SFlorian Hahn   const char *ModuleString =
27109e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
272*05776122SFlorian Hahn       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
27309e516c5SFlorian Hahn       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
27409e516c5SFlorian Hahn       "entry:\n"
27509e516c5SFlorian Hahn       "  br label %for.body\n"
27609e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
27709e516c5SFlorian Hahn       "%entry\n"
27809e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
27909e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
28009e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
28109e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
28209e516c5SFlorian Hahn       "  %add0 = add nsw i32 %vA0, %vA0\n"
28309e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
28409e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
28509e516c5SFlorian Hahn       "  store i32 %add0, i32* %C0, align 4\n"
28609e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
28709e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
28809e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
28909e516c5SFlorian Hahn       "  %add1 = add nsw i32 %vA1, %vA1\n"
29009e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
29109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
29209e516c5SFlorian Hahn       "  store i32 %add1, i32* %C1, align 4\n"
293*05776122SFlorian Hahn       "  %use = add i32 %vA1, 1\n"
29409e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
29509e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
29609e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
29709e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
298*05776122SFlorian Hahn       "  ret void\n"
29909e516c5SFlorian Hahn       "}\n";
30009e516c5SFlorian Hahn 
30109e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
30209e516c5SFlorian Hahn 
30309e516c5SFlorian Hahn   Function *F = M.getFunction("add_x2");
30409e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
30509e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
30609e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
30709e516c5SFlorian Hahn 
30809e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
30909e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
31009e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
31109e516c5SFlorian Hahn 
31209e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 5));
31309e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 10));
31409e516c5SFlorian Hahn 
31509e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *Body);
31609e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
31709e516c5SFlorian Hahn   Slp.buildGraph(StoreRoot);
31809e516c5SFlorian Hahn   EXPECT_FALSE(Slp.isCompletelySLP());
31909e516c5SFlorian Hahn }
32009e516c5SFlorian Hahn 
checkReorderExample(VPInstruction * Store1,VPInstruction * Store2,VPBasicBlock * Body,VPInterleavedAccessInfo && IAI)32109e516c5SFlorian Hahn static void checkReorderExample(VPInstruction *Store1, VPInstruction *Store2,
32209e516c5SFlorian Hahn                                 VPBasicBlock *Body,
32309e516c5SFlorian Hahn                                 VPInterleavedAccessInfo &&IAI) {
32409e516c5SFlorian Hahn   VPlanSlp Slp(IAI, *Body);
32509e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
32609e516c5SFlorian Hahn   VPInstruction *CombinedStore = Slp.buildGraph(StoreRoot);
32709e516c5SFlorian Hahn 
32809e516c5SFlorian Hahn   EXPECT_TRUE(Slp.isCompletelySLP());
32909e516c5SFlorian Hahn   EXPECT_EQ(CombinedStore->getOpcode(), VPInstruction::SLPStore);
33009e516c5SFlorian Hahn 
33109e516c5SFlorian Hahn   VPInstruction *CombinedAdd =
33209e516c5SFlorian Hahn       cast<VPInstruction>(CombinedStore->getOperand(0));
33309e516c5SFlorian Hahn   EXPECT_EQ(CombinedAdd->getOpcode(), Instruction::Add);
33409e516c5SFlorian Hahn 
33509e516c5SFlorian Hahn   VPInstruction *CombinedMulAB =
33609e516c5SFlorian Hahn       cast<VPInstruction>(CombinedAdd->getOperand(0));
33709e516c5SFlorian Hahn   VPInstruction *CombinedMulCD =
33809e516c5SFlorian Hahn       cast<VPInstruction>(CombinedAdd->getOperand(1));
33909e516c5SFlorian Hahn   EXPECT_EQ(CombinedMulAB->getOpcode(), Instruction::Mul);
34009e516c5SFlorian Hahn 
34109e516c5SFlorian Hahn   VPInstruction *CombinedLoadA =
34209e516c5SFlorian Hahn       cast<VPInstruction>(CombinedMulAB->getOperand(0));
34309e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadA->getOpcode());
34409e516c5SFlorian Hahn   VPInstruction *LoadvA0 = cast<VPInstruction>(&*std::next(Body->begin(), 2));
34509e516c5SFlorian Hahn   VPInstruction *LoadvA1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
34609e516c5SFlorian Hahn   EXPECT_EQ(LoadvA0->getOperand(0), CombinedLoadA->getOperand(0));
34709e516c5SFlorian Hahn   EXPECT_EQ(LoadvA1->getOperand(0), CombinedLoadA->getOperand(1));
34809e516c5SFlorian Hahn 
34909e516c5SFlorian Hahn   VPInstruction *CombinedLoadB =
35009e516c5SFlorian Hahn       cast<VPInstruction>(CombinedMulAB->getOperand(1));
35109e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadB->getOpcode());
35209e516c5SFlorian Hahn   VPInstruction *LoadvB0 = cast<VPInstruction>(&*std::next(Body->begin(), 4));
35309e516c5SFlorian Hahn   VPInstruction *LoadvB1 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
35409e516c5SFlorian Hahn   EXPECT_EQ(LoadvB0->getOperand(0), CombinedLoadB->getOperand(0));
35509e516c5SFlorian Hahn   EXPECT_EQ(LoadvB1->getOperand(0), CombinedLoadB->getOperand(1));
35609e516c5SFlorian Hahn 
35709e516c5SFlorian Hahn   EXPECT_EQ(CombinedMulCD->getOpcode(), Instruction::Mul);
35809e516c5SFlorian Hahn 
35909e516c5SFlorian Hahn   VPInstruction *CombinedLoadC =
36009e516c5SFlorian Hahn       cast<VPInstruction>(CombinedMulCD->getOperand(0));
36109e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadC->getOpcode());
36209e516c5SFlorian Hahn   VPInstruction *LoadvC0 = cast<VPInstruction>(&*std::next(Body->begin(), 7));
36309e516c5SFlorian Hahn   VPInstruction *LoadvC1 = cast<VPInstruction>(&*std::next(Body->begin(), 17));
36409e516c5SFlorian Hahn   EXPECT_EQ(LoadvC0->getOperand(0), CombinedLoadC->getOperand(0));
36509e516c5SFlorian Hahn   EXPECT_EQ(LoadvC1->getOperand(0), CombinedLoadC->getOperand(1));
36609e516c5SFlorian Hahn 
36709e516c5SFlorian Hahn   VPInstruction *CombinedLoadD =
36809e516c5SFlorian Hahn       cast<VPInstruction>(CombinedMulCD->getOperand(1));
36909e516c5SFlorian Hahn   EXPECT_EQ(VPInstruction::SLPLoad, CombinedLoadD->getOpcode());
37009e516c5SFlorian Hahn   VPInstruction *LoadvD0 = cast<VPInstruction>(&*std::next(Body->begin(), 9));
37109e516c5SFlorian Hahn   VPInstruction *LoadvD1 = cast<VPInstruction>(&*std::next(Body->begin(), 19));
37209e516c5SFlorian Hahn   EXPECT_EQ(LoadvD0->getOperand(0), CombinedLoadD->getOperand(0));
37309e516c5SFlorian Hahn   EXPECT_EQ(LoadvD1->getOperand(0), CombinedLoadD->getOperand(1));
374348d85a6SFlorian Hahn 
375348d85a6SFlorian Hahn   delete CombinedStore;
376348d85a6SFlorian Hahn   delete CombinedAdd;
377348d85a6SFlorian Hahn   delete CombinedMulAB;
378348d85a6SFlorian Hahn   delete CombinedMulCD;
379348d85a6SFlorian Hahn   delete CombinedLoadA;
380348d85a6SFlorian Hahn   delete CombinedLoadB;
381348d85a6SFlorian Hahn   delete CombinedLoadC;
382348d85a6SFlorian Hahn   delete CombinedLoadD;
38309e516c5SFlorian Hahn }
38409e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpReorder_1)38509e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpReorder_1) {
38609e516c5SFlorian Hahn   LLVMContext Ctx;
38709e516c5SFlorian Hahn   const char *ModuleString =
38809e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
38909e516c5SFlorian Hahn       "define void @add_x3(%struct.Test* %A, %struct.Test* %B, %struct.Test* "
39009e516c5SFlorian Hahn       "%C,  %struct.Test* %D,  %struct.Test* %E)  {\n"
39109e516c5SFlorian Hahn       "entry:\n"
39209e516c5SFlorian Hahn       "  br label %for.body\n"
39309e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
39409e516c5SFlorian Hahn       "%entry\n"
39509e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
39609e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
39709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
39809e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
39909e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
40009e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
40109e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
40209e516c5SFlorian Hahn       "  %mul11 = mul nsw i32 %vA0, %vB0\n"
40309e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
40409e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
40509e516c5SFlorian Hahn       "  %vC0 = load i32, i32* %C0, align 4\n"
40609e516c5SFlorian Hahn       "  %D0 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
40709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
40809e516c5SFlorian Hahn       "  %vD0 = load i32, i32* %D0, align 4\n"
40909e516c5SFlorian Hahn       "  %mul12 = mul nsw i32 %vC0, %vD0\n"
41009e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
41109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
41209e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
41309e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
41409e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
41509e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
41609e516c5SFlorian Hahn       "  %mul21 = mul nsw i32 %vA1, %vB1\n"
41709e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
41809e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
41909e516c5SFlorian Hahn       "  %vC1 = load i32, i32* %C1, align 4\n"
42009e516c5SFlorian Hahn       "  %D1 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
42109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
42209e516c5SFlorian Hahn       "  %vD1 = load i32, i32* %D1, align 4\n"
42309e516c5SFlorian Hahn       "  %mul22 = mul nsw i32 %vC1, %vD1\n"
42409e516c5SFlorian Hahn       "  %add1 = add nsw i32 %mul11, %mul12\n"
42509e516c5SFlorian Hahn       "  %add2 = add nsw i32 %mul22, %mul21\n"
42609e516c5SFlorian Hahn       "  %E0 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
42709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
42809e516c5SFlorian Hahn       "  store i32 %add1, i32* %E0, align 4\n"
42909e516c5SFlorian Hahn       "  %E1 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
43009e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
43109e516c5SFlorian Hahn       "  store i32 %add2, i32* %E1, align 4\n"
43209e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
43309e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
43409e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
43509e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
43609e516c5SFlorian Hahn       "  ret void\n"
43709e516c5SFlorian Hahn       "}\n";
43809e516c5SFlorian Hahn 
43909e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
44009e516c5SFlorian Hahn 
44109e516c5SFlorian Hahn   Function *F = M.getFunction("add_x3");
44209e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
44309e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
44409e516c5SFlorian Hahn 
44509e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
44609e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
44709e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
44809e516c5SFlorian Hahn 
44909e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 24));
45009e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 26));
45109e516c5SFlorian Hahn 
45209e516c5SFlorian Hahn   checkReorderExample(
45309e516c5SFlorian Hahn       Store1, Store2, Body,
45409e516c5SFlorian Hahn       getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan));
45509e516c5SFlorian Hahn }
45609e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpReorder_2)45709e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpReorder_2) {
45809e516c5SFlorian Hahn   LLVMContext Ctx;
45909e516c5SFlorian Hahn   const char *ModuleString =
46009e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
46109e516c5SFlorian Hahn       "define void @add_x3(%struct.Test* %A, %struct.Test* %B, %struct.Test* "
46209e516c5SFlorian Hahn       "%C,  %struct.Test* %D,  %struct.Test* %E)  {\n"
46309e516c5SFlorian Hahn       "entry:\n"
46409e516c5SFlorian Hahn       "  br label %for.body\n"
46509e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
46609e516c5SFlorian Hahn       "%entry\n"
46709e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
46809e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
46909e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
47009e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
47109e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
47209e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
47309e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
47409e516c5SFlorian Hahn       "  %mul11 = mul nsw i32 %vA0, %vB0\n"
47509e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
47609e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
47709e516c5SFlorian Hahn       "  %vC0 = load i32, i32* %C0, align 4\n"
47809e516c5SFlorian Hahn       "  %D0 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
47909e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
48009e516c5SFlorian Hahn       "  %vD0 = load i32, i32* %D0, align 4\n"
48109e516c5SFlorian Hahn       "  %mul12 = mul nsw i32 %vC0, %vD0\n"
48209e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
48309e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
48409e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
48509e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
48609e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
48709e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
48809e516c5SFlorian Hahn       "  %mul21 = mul nsw i32 %vB1, %vA1\n"
48909e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
49009e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
49109e516c5SFlorian Hahn       "  %vC1 = load i32, i32* %C1, align 4\n"
49209e516c5SFlorian Hahn       "  %D1 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
49309e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
49409e516c5SFlorian Hahn       "  %vD1 = load i32, i32* %D1, align 4\n"
49509e516c5SFlorian Hahn       "  %mul22 = mul nsw i32 %vD1, %vC1\n"
49609e516c5SFlorian Hahn       "  %add1 = add nsw i32 %mul11, %mul12\n"
49709e516c5SFlorian Hahn       "  %add2 = add nsw i32 %mul22, %mul21\n"
49809e516c5SFlorian Hahn       "  %E0 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
49909e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
50009e516c5SFlorian Hahn       "  store i32 %add1, i32* %E0, align 4\n"
50109e516c5SFlorian Hahn       "  %E1 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
50209e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
50309e516c5SFlorian Hahn       "  store i32 %add2, i32* %E1, align 4\n"
50409e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
50509e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
50609e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
50709e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
50809e516c5SFlorian Hahn       "  ret void\n"
50909e516c5SFlorian Hahn       "}\n";
51009e516c5SFlorian Hahn 
51109e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
51209e516c5SFlorian Hahn 
51309e516c5SFlorian Hahn   Function *F = M.getFunction("add_x3");
51409e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
51509e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
51609e516c5SFlorian Hahn 
51709e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
51809e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
51909e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
52009e516c5SFlorian Hahn 
52109e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 24));
52209e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 26));
52309e516c5SFlorian Hahn 
52409e516c5SFlorian Hahn   checkReorderExample(
52509e516c5SFlorian Hahn       Store1, Store2, Body,
52609e516c5SFlorian Hahn       getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan));
52709e516c5SFlorian Hahn }
52809e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpReorder_3)52909e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpReorder_3) {
53009e516c5SFlorian Hahn   LLVMContext Ctx;
53109e516c5SFlorian Hahn   const char *ModuleString =
53209e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
53309e516c5SFlorian Hahn       "define void @add_x3(%struct.Test* %A, %struct.Test* %B, %struct.Test* "
53409e516c5SFlorian Hahn       "%C,  %struct.Test* %D,  %struct.Test* %E)  {\n"
53509e516c5SFlorian Hahn       "entry:\n"
53609e516c5SFlorian Hahn       "  br label %for.body\n"
53709e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
53809e516c5SFlorian Hahn       "%entry\n"
53909e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
54009e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
54109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
54209e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
54309e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
54409e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
54509e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
54609e516c5SFlorian Hahn       "  %mul11 = mul nsw i32 %vA1, %vB0\n"
54709e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
54809e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
54909e516c5SFlorian Hahn       "  %vC0 = load i32, i32* %C0, align 4\n"
55009e516c5SFlorian Hahn       "  %D0 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
55109e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
55209e516c5SFlorian Hahn       "  %vD0 = load i32, i32* %D0, align 4\n"
55309e516c5SFlorian Hahn       "  %mul12 = mul nsw i32 %vC0, %vD0\n"
55409e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
55509e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
55609e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
55709e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
55809e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
55909e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
56009e516c5SFlorian Hahn       "  %mul21 = mul nsw i32 %vB1, %vA0\n"
56109e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
56209e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
56309e516c5SFlorian Hahn       "  %vC1 = load i32, i32* %C1, align 4\n"
56409e516c5SFlorian Hahn       "  %D1 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
56509e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
56609e516c5SFlorian Hahn       "  %vD1 = load i32, i32* %D1, align 4\n"
56709e516c5SFlorian Hahn       "  %mul22 = mul nsw i32 %vD1, %vC1\n"
56809e516c5SFlorian Hahn       "  %add1 = add nsw i32 %mul11, %mul12\n"
56909e516c5SFlorian Hahn       "  %add2 = add nsw i32 %mul22, %mul21\n"
57009e516c5SFlorian Hahn       "  %E0 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
57109e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
57209e516c5SFlorian Hahn       "  store i32 %add1, i32* %E0, align 4\n"
57309e516c5SFlorian Hahn       "  %E1 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
57409e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
57509e516c5SFlorian Hahn       "  store i32 %add2, i32* %E1, align 4\n"
57609e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
57709e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
57809e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
57909e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
58009e516c5SFlorian Hahn       "  ret void\n"
58109e516c5SFlorian Hahn       "}\n";
58209e516c5SFlorian Hahn 
58309e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
58409e516c5SFlorian Hahn 
58509e516c5SFlorian Hahn   Function *F = M.getFunction("add_x3");
58609e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
58709e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
58809e516c5SFlorian Hahn 
58909e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
59009e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
59109e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
59209e516c5SFlorian Hahn 
59309e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 24));
59409e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 26));
59509e516c5SFlorian Hahn 
59609e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
59709e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *Body);
59809e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
59909e516c5SFlorian Hahn   EXPECT_EQ(nullptr, Slp.buildGraph(StoreRoot));
60009e516c5SFlorian Hahn 
60109e516c5SFlorian Hahn   // FIXME Need to select better first value for lane0.
60209e516c5SFlorian Hahn   EXPECT_FALSE(Slp.isCompletelySLP());
60309e516c5SFlorian Hahn }
60409e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpReorder_4)60509e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpReorder_4) {
60609e516c5SFlorian Hahn   LLVMContext Ctx;
60709e516c5SFlorian Hahn   const char *ModuleString =
60809e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
60909e516c5SFlorian Hahn       "define void @add_x3(%struct.Test* %A, %struct.Test* %B, %struct.Test* "
61009e516c5SFlorian Hahn       "%C,  %struct.Test* %D,  %struct.Test* %E)  {\n"
61109e516c5SFlorian Hahn       "entry:\n"
61209e516c5SFlorian Hahn       "  br label %for.body\n"
61309e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
61409e516c5SFlorian Hahn       "%entry\n"
61509e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
61609e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
61709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
61809e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
61909e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
62009e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
62109e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
62209e516c5SFlorian Hahn       "  %mul11 = mul nsw i32 %vA0, %vB0\n"
62309e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
62409e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
62509e516c5SFlorian Hahn       "  %vC0 = load i32, i32* %C0, align 4\n"
62609e516c5SFlorian Hahn       "  %D0 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
62709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
62809e516c5SFlorian Hahn       "  %vD0 = load i32, i32* %D0, align 4\n"
62909e516c5SFlorian Hahn       "  %mul12 = mul nsw i32 %vC0, %vD0\n"
63009e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
63109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
63209e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
63309e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
63409e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
63509e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
63609e516c5SFlorian Hahn       "  %mul21 = mul nsw i32 %vA1, %vB1\n"
63709e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
63809e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
63909e516c5SFlorian Hahn       "  %vC1 = load i32, i32* %C1, align 4\n"
64009e516c5SFlorian Hahn       "  %D1 = getelementptr inbounds %struct.Test, %struct.Test* %D, i64 "
64109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
64209e516c5SFlorian Hahn       "  %vD1 = load i32, i32* %D1, align 4\n"
64309e516c5SFlorian Hahn       "  %mul22 = mul nsw i32 %vC1, %vD1\n"
64409e516c5SFlorian Hahn       "  %add1 = add nsw i32 %mul11, %mul12\n"
64509e516c5SFlorian Hahn       "  %add2 = add nsw i32 %mul22, %mul21\n"
64609e516c5SFlorian Hahn       "  %E0 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
64709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
64809e516c5SFlorian Hahn       "  store i32 %add1, i32* %E0, align 4\n"
64909e516c5SFlorian Hahn       "  %E1 = getelementptr inbounds %struct.Test, %struct.Test* %E, i64 "
65009e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
65109e516c5SFlorian Hahn       "  store i32 %add2, i32* %E1, align 4\n"
65209e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
65309e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
65409e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
65509e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
65609e516c5SFlorian Hahn       "  ret void\n"
65709e516c5SFlorian Hahn       "}\n";
65809e516c5SFlorian Hahn 
65909e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
66009e516c5SFlorian Hahn 
66109e516c5SFlorian Hahn   Function *F = M.getFunction("add_x3");
66209e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
66309e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
66409e516c5SFlorian Hahn 
66509e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
66609e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
66709e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
66809e516c5SFlorian Hahn 
66909e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 24));
67009e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 26));
67109e516c5SFlorian Hahn 
67209e516c5SFlorian Hahn   checkReorderExample(
67309e516c5SFlorian Hahn       Store1, Store2, Body,
67409e516c5SFlorian Hahn       getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan));
67509e516c5SFlorian Hahn }
67609e516c5SFlorian Hahn 
67709e516c5SFlorian Hahn // Make sure we do not combine instructions with operands in different BBs.
TEST_F(VPlanSlpTest,testInstrsInDifferentBBs)67809e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testInstrsInDifferentBBs) {
67909e516c5SFlorian Hahn   const char *ModuleString =
68009e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
68109e516c5SFlorian Hahn       "%struct.Test3 = type { i32, i32, i32 }\n"
68209e516c5SFlorian Hahn       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
68309e516c5SFlorian Hahn       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
68409e516c5SFlorian Hahn       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
68509e516c5SFlorian Hahn       "entry:\n"
68609e516c5SFlorian Hahn       "  br label %for.body\n"
68709e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
68809e516c5SFlorian Hahn       "%entry\n"
68909e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
69009e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
69109e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
69209e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
69309e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
69409e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
69509e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
69609e516c5SFlorian Hahn       "  %add0 = add nsw i32 %vA0, %vB0\n"
69709e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
69809e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
69909e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
70009e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
70109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
70209e516c5SFlorian Hahn       "  br label %bb2\n"
70309e516c5SFlorian Hahn       "bb2:\n"
70409e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
70509e516c5SFlorian Hahn       "  %add1 = add nsw i32 %vA1, %vB1\n"
70609e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
70709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
70809e516c5SFlorian Hahn       "  store i32 %add0, i32* %C0, align 4\n"
70909e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
71009e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
71109e516c5SFlorian Hahn       "  store i32 %add1, i32* %C1, align 4\n"
71209e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
71309e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
71409e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
71509e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
71609e516c5SFlorian Hahn       "  ret void\n"
71709e516c5SFlorian Hahn       "}\n";
71809e516c5SFlorian Hahn 
71909e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
72009e516c5SFlorian Hahn 
72109e516c5SFlorian Hahn   Function *F = M.getFunction("add_x2");
72209e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
72309e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
72409e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
72509e516c5SFlorian Hahn 
72609e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
72709e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
72809e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
72909e516c5SFlorian Hahn   VPBasicBlock *BB2 = Body->getSingleSuccessor()->getEntryBasicBlock();
73009e516c5SFlorian Hahn 
73109e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(BB2->begin(), 3));
73209e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(BB2->begin(), 5));
73309e516c5SFlorian Hahn 
73409e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *BB2);
73509e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
73609e516c5SFlorian Hahn   EXPECT_EQ(nullptr, Slp.buildGraph(StoreRoot));
73709e516c5SFlorian Hahn   EXPECT_EQ(0u, Slp.getWidestBundleBits());
73809e516c5SFlorian Hahn }
73909e516c5SFlorian Hahn 
74009e516c5SFlorian Hahn // Make sure we do not combine instructions with operands in different BBs.
TEST_F(VPlanSlpTest,testInstrsInDifferentBBs2)74109e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testInstrsInDifferentBBs2) {
74209e516c5SFlorian Hahn   const char *ModuleString =
74309e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
74409e516c5SFlorian Hahn       "%struct.Test3 = type { i32, i32, i32 }\n"
74509e516c5SFlorian Hahn       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
74609e516c5SFlorian Hahn       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
74709e516c5SFlorian Hahn       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
74809e516c5SFlorian Hahn       "entry:\n"
74909e516c5SFlorian Hahn       "  br label %for.body\n"
75009e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
75109e516c5SFlorian Hahn       "%entry\n"
75209e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
75309e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
75409e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
75509e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
75609e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
75709e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
75809e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
75909e516c5SFlorian Hahn       "  %add0 = add nsw i32 %vA0, %vB0\n"
76009e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
76109e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
76209e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
76309e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
76409e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
76509e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
76609e516c5SFlorian Hahn       "  %add1 = add nsw i32 %vA1, %vB1\n"
76709e516c5SFlorian Hahn       "  br label %bb2\n"
76809e516c5SFlorian Hahn       "bb2:\n"
76909e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
77009e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
77109e516c5SFlorian Hahn       "  store i32 %add0, i32* %C0, align 4\n"
77209e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
77309e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
77409e516c5SFlorian Hahn       "  store i32 %add1, i32* %C1, align 4\n"
77509e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
77609e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
77709e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
77809e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
77909e516c5SFlorian Hahn       "  ret void\n"
78009e516c5SFlorian Hahn       "}\n";
78109e516c5SFlorian Hahn 
78209e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
78309e516c5SFlorian Hahn 
78409e516c5SFlorian Hahn   Function *F = M.getFunction("add_x2");
78509e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
78609e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
78709e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
78809e516c5SFlorian Hahn 
78909e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
79009e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
79109e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
79209e516c5SFlorian Hahn   VPBasicBlock *BB2 = Body->getSingleSuccessor()->getEntryBasicBlock();
79309e516c5SFlorian Hahn 
79409e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(BB2->begin(), 1));
79509e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(BB2->begin(), 3));
79609e516c5SFlorian Hahn 
79709e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *BB2);
79809e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
79909e516c5SFlorian Hahn   EXPECT_EQ(nullptr, Slp.buildGraph(StoreRoot));
80009e516c5SFlorian Hahn   EXPECT_EQ(0u, Slp.getWidestBundleBits());
80109e516c5SFlorian Hahn }
80209e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpAtomicLoad)80309e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpAtomicLoad) {
80409e516c5SFlorian Hahn   const char *ModuleString =
80509e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
80609e516c5SFlorian Hahn       "%struct.Test3 = type { i32, i32, i32 }\n"
80709e516c5SFlorian Hahn       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
80809e516c5SFlorian Hahn       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
80909e516c5SFlorian Hahn       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
81009e516c5SFlorian Hahn       "entry:\n"
81109e516c5SFlorian Hahn       "  br label %for.body\n"
81209e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
81309e516c5SFlorian Hahn       "%entry\n"
81409e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
81509e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
81609e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
81709e516c5SFlorian Hahn       "  %vA0 = load atomic i32, i32* %A0 monotonic, align 4\n"
81809e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
81909e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
82009e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
82109e516c5SFlorian Hahn       "  %add0 = add nsw i32 %vA0, %vB0\n"
82209e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
82309e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
82409e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
82509e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
82609e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
82709e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
82809e516c5SFlorian Hahn       "  %add1 = add nsw i32 %vA1, %vB1\n"
82909e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
83009e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
83109e516c5SFlorian Hahn       "  store i32 %add0, i32* %C0, align 4\n"
83209e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
83309e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
83409e516c5SFlorian Hahn       "  store i32 %add1, i32* %C1, align 4\n"
83509e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
83609e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
83709e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
83809e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
83909e516c5SFlorian Hahn       "  ret void\n"
84009e516c5SFlorian Hahn       "}\n";
84109e516c5SFlorian Hahn 
84209e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
84309e516c5SFlorian Hahn 
84409e516c5SFlorian Hahn   Function *F = M.getFunction("add_x2");
84509e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
84609e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
84709e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
84809e516c5SFlorian Hahn 
84909e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
85009e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
85109e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
85209e516c5SFlorian Hahn 
85309e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
85409e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
85509e516c5SFlorian Hahn 
85609e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *Body);
85709e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
85809e516c5SFlorian Hahn   EXPECT_EQ(nullptr, Slp.buildGraph(StoreRoot));
85909e516c5SFlorian Hahn   EXPECT_FALSE(Slp.isCompletelySLP());
86009e516c5SFlorian Hahn }
86109e516c5SFlorian Hahn 
TEST_F(VPlanSlpTest,testSlpAtomicStore)86209e516c5SFlorian Hahn TEST_F(VPlanSlpTest, testSlpAtomicStore) {
86309e516c5SFlorian Hahn   const char *ModuleString =
86409e516c5SFlorian Hahn       "%struct.Test = type { i32, i32 }\n"
86509e516c5SFlorian Hahn       "%struct.Test3 = type { i32, i32, i32 }\n"
86609e516c5SFlorian Hahn       "%struct.Test4xi8 = type { i8, i8, i8 }\n"
86709e516c5SFlorian Hahn       "define void @add_x2(%struct.Test* nocapture readonly %A, %struct.Test* "
86809e516c5SFlorian Hahn       "nocapture readonly %B, %struct.Test* nocapture %C)  {\n"
86909e516c5SFlorian Hahn       "entry:\n"
87009e516c5SFlorian Hahn       "  br label %for.body\n"
87109e516c5SFlorian Hahn       "for.body:                                         ; preds = %for.body, "
87209e516c5SFlorian Hahn       "%entry\n"
87309e516c5SFlorian Hahn       "  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
87409e516c5SFlorian Hahn       "  %A0 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
87509e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
87609e516c5SFlorian Hahn       "  %vA0 = load i32, i32* %A0, align 4\n"
87709e516c5SFlorian Hahn       "  %B0 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
87809e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
87909e516c5SFlorian Hahn       "  %vB0 = load i32, i32* %B0, align 4\n"
88009e516c5SFlorian Hahn       "  %add0 = add nsw i32 %vA0, %vB0\n"
88109e516c5SFlorian Hahn       "  %A1 = getelementptr inbounds %struct.Test, %struct.Test* %A, i64 "
88209e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
88309e516c5SFlorian Hahn       "  %vA1 = load i32, i32* %A1, align 4\n"
88409e516c5SFlorian Hahn       "  %B1 = getelementptr inbounds %struct.Test, %struct.Test* %B, i64 "
88509e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
88609e516c5SFlorian Hahn       "  %vB1 = load i32, i32* %B1, align 4\n"
88709e516c5SFlorian Hahn       "  %add1 = add nsw i32 %vA1, %vB1\n"
88809e516c5SFlorian Hahn       "  %C0 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
88909e516c5SFlorian Hahn       "%indvars.iv, i32 0\n"
89009e516c5SFlorian Hahn       "  store atomic i32 %add0, i32* %C0 monotonic, align 4\n"
89109e516c5SFlorian Hahn       "  %C1 = getelementptr inbounds %struct.Test, %struct.Test* %C, i64 "
89209e516c5SFlorian Hahn       "%indvars.iv, i32 1\n"
89309e516c5SFlorian Hahn       "  store i32 %add1, i32* %C1, align 4\n"
89409e516c5SFlorian Hahn       "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
89509e516c5SFlorian Hahn       "  %exitcond = icmp eq i64 %indvars.iv.next, 1024\n"
89609e516c5SFlorian Hahn       "  br i1 %exitcond, label %for.cond.cleanup, label %for.body\n"
89709e516c5SFlorian Hahn       "for.cond.cleanup:                                 ; preds = %for.body\n"
89809e516c5SFlorian Hahn       "  ret void\n"
89909e516c5SFlorian Hahn       "}\n";
90009e516c5SFlorian Hahn 
90109e516c5SFlorian Hahn   Module &M = parseModule(ModuleString);
90209e516c5SFlorian Hahn 
90309e516c5SFlorian Hahn   Function *F = M.getFunction("add_x2");
90409e516c5SFlorian Hahn   BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
90509e516c5SFlorian Hahn   auto Plan = buildHCFG(LoopHeader);
90609e516c5SFlorian Hahn   auto VPIAI = getInterleavedAccessInfo(*F, LI->getLoopFor(LoopHeader), *Plan);
90709e516c5SFlorian Hahn 
90809e516c5SFlorian Hahn   VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
90909e516c5SFlorian Hahn   EXPECT_NE(nullptr, Entry->getSingleSuccessor());
91009e516c5SFlorian Hahn   VPBasicBlock *Body = Entry->getSingleSuccessor()->getEntryBasicBlock();
91109e516c5SFlorian Hahn 
91209e516c5SFlorian Hahn   VPInstruction *Store1 = cast<VPInstruction>(&*std::next(Body->begin(), 12));
91309e516c5SFlorian Hahn   VPInstruction *Store2 = cast<VPInstruction>(&*std::next(Body->begin(), 14));
91409e516c5SFlorian Hahn 
91509e516c5SFlorian Hahn   VPlanSlp Slp(VPIAI, *Body);
91609e516c5SFlorian Hahn   SmallVector<VPValue *, 4> StoreRoot = {Store1, Store2};
91709e516c5SFlorian Hahn   Slp.buildGraph(StoreRoot);
91809e516c5SFlorian Hahn   EXPECT_FALSE(Slp.isCompletelySLP());
91909e516c5SFlorian Hahn }
92009e516c5SFlorian Hahn 
92109e516c5SFlorian Hahn } // namespace
92209e516c5SFlorian Hahn } // namespace llvm
923