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