brintos

brintos / llvm-project-archived public Read only

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