15ea69481Svporpo //===- VecUtilsTest.cpp --------------------------------------------------===// 25ea69481Svporpo // 35ea69481Svporpo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ea69481Svporpo // See https://llvm.org/LICENSE.txt for license information. 55ea69481Svporpo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ea69481Svporpo // 75ea69481Svporpo //===----------------------------------------------------------------------===// 85ea69481Svporpo 95ea69481Svporpo #include "llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h" 10083369fdSvporpo #include "llvm/Analysis/AliasAnalysis.h" 11083369fdSvporpo #include "llvm/Analysis/AssumptionCache.h" 12083369fdSvporpo #include "llvm/Analysis/BasicAliasAnalysis.h" 13083369fdSvporpo #include "llvm/Analysis/LoopInfo.h" 14083369fdSvporpo #include "llvm/Analysis/ScalarEvolution.h" 15083369fdSvporpo #include "llvm/Analysis/TargetLibraryInfo.h" 165ea69481Svporpo #include "llvm/AsmParser/Parser.h" 17083369fdSvporpo #include "llvm/IR/DataLayout.h" 18083369fdSvporpo #include "llvm/IR/Dominators.h" 195ea69481Svporpo #include "llvm/SandboxIR/Context.h" 20083369fdSvporpo #include "llvm/SandboxIR/Function.h" 215ea69481Svporpo #include "llvm/SandboxIR/Type.h" 22083369fdSvporpo #include "llvm/Support/SourceMgr.h" 235ea69481Svporpo #include "gtest/gtest.h" 245ea69481Svporpo 255ea69481Svporpo using namespace llvm; 265ea69481Svporpo 275ea69481Svporpo struct VecUtilsTest : public testing::Test { 285ea69481Svporpo LLVMContext C; 29083369fdSvporpo std::unique_ptr<Module> M; 30083369fdSvporpo std::unique_ptr<AssumptionCache> AC; 31083369fdSvporpo std::unique_ptr<TargetLibraryInfoImpl> TLII; 32083369fdSvporpo std::unique_ptr<TargetLibraryInfo> TLI; 33083369fdSvporpo std::unique_ptr<DominatorTree> DT; 34083369fdSvporpo std::unique_ptr<LoopInfo> LI; 35083369fdSvporpo std::unique_ptr<ScalarEvolution> SE; 36083369fdSvporpo void parseIR(const char *IR) { 37083369fdSvporpo SMDiagnostic Err; 38083369fdSvporpo M = parseAssemblyString(IR, Err, C); 39083369fdSvporpo if (!M) 40083369fdSvporpo Err.print("VecUtilsTest", errs()); 41083369fdSvporpo } 42083369fdSvporpo ScalarEvolution &getSE(llvm::Function &LLVMF) { 43083369fdSvporpo TLII = std::make_unique<TargetLibraryInfoImpl>(); 44083369fdSvporpo TLI = std::make_unique<TargetLibraryInfo>(*TLII); 45083369fdSvporpo AC = std::make_unique<AssumptionCache>(LLVMF); 46083369fdSvporpo DT = std::make_unique<DominatorTree>(LLVMF); 47083369fdSvporpo LI = std::make_unique<LoopInfo>(*DT); 48083369fdSvporpo SE = std::make_unique<ScalarEvolution>(LLVMF, *TLI, *AC, *DT, *LI); 49083369fdSvporpo return *SE; 50083369fdSvporpo } 515ea69481Svporpo }; 525ea69481Svporpo 532dc1c955Svporpo sandboxir::BasicBlock &getBasicBlockByName(sandboxir::Function &F, 542dc1c955Svporpo StringRef Name) { 552dc1c955Svporpo for (sandboxir::BasicBlock &BB : F) 562dc1c955Svporpo if (BB.getName() == Name) 572dc1c955Svporpo return BB; 582dc1c955Svporpo llvm_unreachable("Expected to find basic block!"); 592dc1c955Svporpo } 602dc1c955Svporpo 615ea69481Svporpo TEST_F(VecUtilsTest, GetNumElements) { 625ea69481Svporpo sandboxir::Context Ctx(C); 635ea69481Svporpo auto *ElemTy = sandboxir::Type::getInt32Ty(Ctx); 645ea69481Svporpo EXPECT_EQ(sandboxir::VecUtils::getNumElements(ElemTy), 1); 655ea69481Svporpo auto *VTy = sandboxir::FixedVectorType::get(ElemTy, 2); 665ea69481Svporpo EXPECT_EQ(sandboxir::VecUtils::getNumElements(VTy), 2); 675ea69481Svporpo auto *VTy1 = sandboxir::FixedVectorType::get(ElemTy, 1); 685ea69481Svporpo EXPECT_EQ(sandboxir::VecUtils::getNumElements(VTy1), 1); 695ea69481Svporpo } 705ea69481Svporpo 715ea69481Svporpo TEST_F(VecUtilsTest, GetElementType) { 725ea69481Svporpo sandboxir::Context Ctx(C); 735ea69481Svporpo auto *ElemTy = sandboxir::Type::getInt32Ty(Ctx); 745ea69481Svporpo EXPECT_EQ(sandboxir::VecUtils::getElementType(ElemTy), ElemTy); 755ea69481Svporpo auto *VTy = sandboxir::FixedVectorType::get(ElemTy, 2); 765ea69481Svporpo EXPECT_EQ(sandboxir::VecUtils::getElementType(VTy), ElemTy); 775ea69481Svporpo } 78083369fdSvporpo 79083369fdSvporpo TEST_F(VecUtilsTest, AreConsecutive_gep_float) { 80083369fdSvporpo parseIR(R"IR( 81083369fdSvporpo define void @foo(ptr %ptr) { 82083369fdSvporpo %gep0 = getelementptr inbounds float, ptr %ptr, i64 0 83083369fdSvporpo %gep1 = getelementptr inbounds float, ptr %ptr, i64 1 84083369fdSvporpo %gep2 = getelementptr inbounds float, ptr %ptr, i64 2 85083369fdSvporpo %gep3 = getelementptr inbounds float, ptr %ptr, i64 3 86083369fdSvporpo 87083369fdSvporpo %ld0 = load float, ptr %gep0 88083369fdSvporpo %ld1 = load float, ptr %gep1 89083369fdSvporpo %ld2 = load float, ptr %gep2 90083369fdSvporpo %ld3 = load float, ptr %gep3 91083369fdSvporpo 92083369fdSvporpo %v2ld0 = load <2 x float>, ptr %gep0 93083369fdSvporpo %v2ld1 = load <2 x float>, ptr %gep1 94083369fdSvporpo %v2ld2 = load <2 x float>, ptr %gep2 95083369fdSvporpo %v2ld3 = load <2 x float>, ptr %gep3 96083369fdSvporpo 97083369fdSvporpo %v3ld0 = load <3 x float>, ptr %gep0 98083369fdSvporpo %v3ld1 = load <3 x float>, ptr %gep1 99083369fdSvporpo %v3ld2 = load <3 x float>, ptr %gep2 100083369fdSvporpo %v3ld3 = load <3 x float>, ptr %gep3 101083369fdSvporpo ret void 102083369fdSvporpo } 103083369fdSvporpo )IR"); 104083369fdSvporpo Function &LLVMF = *M->getFunction("foo"); 105083369fdSvporpo const DataLayout &DL = M->getDataLayout(); 106083369fdSvporpo auto &SE = getSE(LLVMF); 107083369fdSvporpo 108083369fdSvporpo sandboxir::Context Ctx(C); 109083369fdSvporpo auto &F = *Ctx.createFunction(&LLVMF); 110083369fdSvporpo 111083369fdSvporpo auto &BB = *F.begin(); 112083369fdSvporpo auto It = std::next(BB.begin(), 4); 113083369fdSvporpo auto *L0 = cast<sandboxir::LoadInst>(&*It++); 114083369fdSvporpo auto *L1 = cast<sandboxir::LoadInst>(&*It++); 115083369fdSvporpo auto *L2 = cast<sandboxir::LoadInst>(&*It++); 116083369fdSvporpo auto *L3 = cast<sandboxir::LoadInst>(&*It++); 117083369fdSvporpo 118083369fdSvporpo auto *V2L0 = cast<sandboxir::LoadInst>(&*It++); 119083369fdSvporpo auto *V2L1 = cast<sandboxir::LoadInst>(&*It++); 120083369fdSvporpo auto *V2L2 = cast<sandboxir::LoadInst>(&*It++); 121083369fdSvporpo auto *V2L3 = cast<sandboxir::LoadInst>(&*It++); 122083369fdSvporpo 123083369fdSvporpo auto *V3L0 = cast<sandboxir::LoadInst>(&*It++); 124083369fdSvporpo auto *V3L1 = cast<sandboxir::LoadInst>(&*It++); 125083369fdSvporpo auto *V3L2 = cast<sandboxir::LoadInst>(&*It++); 126083369fdSvporpo auto *V3L3 = cast<sandboxir::LoadInst>(&*It++); 127083369fdSvporpo 128083369fdSvporpo // Scalar 129083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL)); 130083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL)); 131083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL)); 132083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL)); 133083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL)); 134083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL)); 135083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL)); 136083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL)); 137083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL)); 138083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL)); 139083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL)); 140083369fdSvporpo 141083369fdSvporpo // Check 2-wide loads 142083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL)); 143083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL)); 144083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL)); 145083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL)); 146083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL)); 147083369fdSvporpo 148083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 149083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 150083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 151083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 152083369fdSvporpo 153083369fdSvporpo // Check 3-wide loads 154083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL)); 155083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL)); 156083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL)); 157083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL)); 158083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL)); 159083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL)); 160083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL)); 161083369fdSvporpo 162083369fdSvporpo // Check mixes of vectors and scalar 163083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL)); 164083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL)); 165083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL)); 166083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL)); 167083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL)); 168083369fdSvporpo 169083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL)); 170083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL)); 171083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL)); 172083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL)); 173083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL)); 174083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL)); 175083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL)); 176083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL)); 177083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL)); 178083369fdSvporpo } 179083369fdSvporpo 180083369fdSvporpo TEST_F(VecUtilsTest, AreConsecutive_gep_i8) { 181083369fdSvporpo parseIR(R"IR( 182083369fdSvporpo define void @foo(ptr %ptr) { 183083369fdSvporpo %gep0 = getelementptr inbounds i8, ptr %ptr, i64 0 184083369fdSvporpo %gep1 = getelementptr inbounds i8, ptr %ptr, i64 4 185083369fdSvporpo %gep2 = getelementptr inbounds i8, ptr %ptr, i64 8 186083369fdSvporpo %gep3 = getelementptr inbounds i8, ptr %ptr, i64 12 187083369fdSvporpo 188083369fdSvporpo %ld0 = load float, ptr %gep0 189083369fdSvporpo %ld1 = load float, ptr %gep1 190083369fdSvporpo %ld2 = load float, ptr %gep2 191083369fdSvporpo %ld3 = load float, ptr %gep3 192083369fdSvporpo 193083369fdSvporpo %v2ld0 = load <2 x float>, ptr %gep0 194083369fdSvporpo %v2ld1 = load <2 x float>, ptr %gep1 195083369fdSvporpo %v2ld2 = load <2 x float>, ptr %gep2 196083369fdSvporpo %v2ld3 = load <2 x float>, ptr %gep3 197083369fdSvporpo 198083369fdSvporpo %v3ld0 = load <3 x float>, ptr %gep0 199083369fdSvporpo %v3ld1 = load <3 x float>, ptr %gep1 200083369fdSvporpo %v3ld2 = load <3 x float>, ptr %gep2 201083369fdSvporpo %v3ld3 = load <3 x float>, ptr %gep3 202083369fdSvporpo ret void 203083369fdSvporpo } 204083369fdSvporpo )IR"); 205083369fdSvporpo Function &LLVMF = *M->getFunction("foo"); 206083369fdSvporpo const DataLayout &DL = M->getDataLayout(); 207083369fdSvporpo auto &SE = getSE(LLVMF); 208083369fdSvporpo 209083369fdSvporpo sandboxir::Context Ctx(C); 210083369fdSvporpo auto &F = *Ctx.createFunction(&LLVMF); 211083369fdSvporpo auto &BB = *F.begin(); 212083369fdSvporpo auto It = std::next(BB.begin(), 4); 213083369fdSvporpo auto *L0 = cast<sandboxir::LoadInst>(&*It++); 214083369fdSvporpo auto *L1 = cast<sandboxir::LoadInst>(&*It++); 215083369fdSvporpo auto *L2 = cast<sandboxir::LoadInst>(&*It++); 216083369fdSvporpo auto *L3 = cast<sandboxir::LoadInst>(&*It++); 217083369fdSvporpo 218083369fdSvporpo auto *V2L0 = cast<sandboxir::LoadInst>(&*It++); 219083369fdSvporpo auto *V2L1 = cast<sandboxir::LoadInst>(&*It++); 220083369fdSvporpo auto *V2L2 = cast<sandboxir::LoadInst>(&*It++); 221083369fdSvporpo auto *V2L3 = cast<sandboxir::LoadInst>(&*It++); 222083369fdSvporpo 223083369fdSvporpo auto *V3L0 = cast<sandboxir::LoadInst>(&*It++); 224083369fdSvporpo auto *V3L1 = cast<sandboxir::LoadInst>(&*It++); 225083369fdSvporpo auto *V3L2 = cast<sandboxir::LoadInst>(&*It++); 226083369fdSvporpo auto *V3L3 = cast<sandboxir::LoadInst>(&*It++); 227083369fdSvporpo 228083369fdSvporpo // Scalar 229083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL)); 230083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL)); 231083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL)); 232083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL)); 233083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL)); 234083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL)); 235083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL)); 236083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL)); 237083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL)); 238083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL)); 239083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL)); 240083369fdSvporpo 241083369fdSvporpo // Check 2-wide loads 242083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL)); 243083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL)); 244083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL)); 245083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL)); 246083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL)); 247083369fdSvporpo 248083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 249083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 250083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 251083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 252083369fdSvporpo 253083369fdSvporpo // Check 3-wide loads 254083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL)); 255083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL)); 256083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL)); 257083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL)); 258083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL)); 259083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL)); 260083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL)); 261083369fdSvporpo 262083369fdSvporpo // Check mixes of vectors and scalar 263083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL)); 264083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL)); 265083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL)); 266083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL)); 267083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL)); 268083369fdSvporpo 269083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL)); 270083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL)); 271083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL)); 272083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL)); 273083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL)); 274083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL)); 275083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL)); 276083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL)); 277083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL)); 278083369fdSvporpo } 279083369fdSvporpo 280083369fdSvporpo TEST_F(VecUtilsTest, AreConsecutive_gep_i1) { 281083369fdSvporpo parseIR(R"IR( 282083369fdSvporpo define void @foo(ptr %ptr) { 283083369fdSvporpo %gep0 = getelementptr inbounds i1, ptr %ptr, i64 0 284083369fdSvporpo %gep1 = getelementptr inbounds i2, ptr %ptr, i64 4 285083369fdSvporpo %gep2 = getelementptr inbounds i3, ptr %ptr, i64 8 286083369fdSvporpo %gep3 = getelementptr inbounds i7, ptr %ptr, i64 12 287083369fdSvporpo 288083369fdSvporpo %ld0 = load float, ptr %gep0 289083369fdSvporpo %ld1 = load float, ptr %gep1 290083369fdSvporpo %ld2 = load float, ptr %gep2 291083369fdSvporpo %ld3 = load float, ptr %gep3 292083369fdSvporpo 293083369fdSvporpo %v2ld0 = load <2 x float>, ptr %gep0 294083369fdSvporpo %v2ld1 = load <2 x float>, ptr %gep1 295083369fdSvporpo %v2ld2 = load <2 x float>, ptr %gep2 296083369fdSvporpo %v2ld3 = load <2 x float>, ptr %gep3 297083369fdSvporpo 298083369fdSvporpo %v3ld0 = load <3 x float>, ptr %gep0 299083369fdSvporpo %v3ld1 = load <3 x float>, ptr %gep1 300083369fdSvporpo %v3ld2 = load <3 x float>, ptr %gep2 301083369fdSvporpo %v3ld3 = load <3 x float>, ptr %gep3 302083369fdSvporpo ret void 303083369fdSvporpo } 304083369fdSvporpo )IR"); 305083369fdSvporpo Function &LLVMF = *M->getFunction("foo"); 306083369fdSvporpo const DataLayout &DL = M->getDataLayout(); 307083369fdSvporpo auto &SE = getSE(LLVMF); 308083369fdSvporpo 309083369fdSvporpo sandboxir::Context Ctx(C); 310083369fdSvporpo auto &F = *Ctx.createFunction(&LLVMF); 311083369fdSvporpo auto &BB = *F.begin(); 312083369fdSvporpo auto It = std::next(BB.begin(), 4); 313083369fdSvporpo auto *L0 = cast<sandboxir::LoadInst>(&*It++); 314083369fdSvporpo auto *L1 = cast<sandboxir::LoadInst>(&*It++); 315083369fdSvporpo auto *L2 = cast<sandboxir::LoadInst>(&*It++); 316083369fdSvporpo auto *L3 = cast<sandboxir::LoadInst>(&*It++); 317083369fdSvporpo 318083369fdSvporpo auto *V2L0 = cast<sandboxir::LoadInst>(&*It++); 319083369fdSvporpo auto *V2L1 = cast<sandboxir::LoadInst>(&*It++); 320083369fdSvporpo auto *V2L2 = cast<sandboxir::LoadInst>(&*It++); 321083369fdSvporpo auto *V2L3 = cast<sandboxir::LoadInst>(&*It++); 322083369fdSvporpo 323083369fdSvporpo auto *V3L0 = cast<sandboxir::LoadInst>(&*It++); 324083369fdSvporpo auto *V3L1 = cast<sandboxir::LoadInst>(&*It++); 325083369fdSvporpo auto *V3L2 = cast<sandboxir::LoadInst>(&*It++); 326083369fdSvporpo auto *V3L3 = cast<sandboxir::LoadInst>(&*It++); 327083369fdSvporpo 328083369fdSvporpo // Scalar 329083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL)); 330083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL)); 331083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL)); 332083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL)); 333083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL)); 334083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL)); 335083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL)); 336083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL)); 337083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL)); 338083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL)); 339083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL)); 340083369fdSvporpo 341083369fdSvporpo // Check 2-wide loads 342083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL)); 343083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL)); 344083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL)); 345083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL)); 346083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL)); 347083369fdSvporpo 348083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 349083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 350083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 351083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 352083369fdSvporpo 353083369fdSvporpo // Check 3-wide loads 354083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL)); 355083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL)); 356083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL)); 357083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL)); 358083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL)); 359083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL)); 360083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL)); 361083369fdSvporpo 362083369fdSvporpo // Check mixes of vectors and scalar 363083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL)); 364083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL)); 365083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL)); 366083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL)); 367083369fdSvporpo EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL)); 368083369fdSvporpo 369083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL)); 370083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL)); 371083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL)); 372083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL)); 373083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL)); 374083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL)); 375083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL)); 376083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL)); 377083369fdSvporpo EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL)); 378083369fdSvporpo } 379320389d4Svporpo 380320389d4Svporpo TEST_F(VecUtilsTest, GetNumLanes) { 381320389d4Svporpo parseIR(R"IR( 382320389d4Svporpo define <4 x float> @foo(float %v, <2 x float> %v2, <4 x float> %ret, ptr %ptr) { 383320389d4Svporpo store float %v, ptr %ptr 384320389d4Svporpo store <2 x float> %v2, ptr %ptr 385320389d4Svporpo ret <4 x float> %ret 386320389d4Svporpo } 387320389d4Svporpo )IR"); 388320389d4Svporpo Function &LLVMF = *M->getFunction("foo"); 389320389d4Svporpo 390320389d4Svporpo sandboxir::Context Ctx(C); 391320389d4Svporpo auto &F = *Ctx.createFunction(&LLVMF); 392320389d4Svporpo auto &BB = *F.begin(); 393320389d4Svporpo 394320389d4Svporpo auto It = BB.begin(); 395320389d4Svporpo auto *S0 = cast<sandboxir::StoreInst>(&*It++); 396320389d4Svporpo auto *S1 = cast<sandboxir::StoreInst>(&*It++); 397320389d4Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 398320389d4Svporpo EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S0->getValueOperand()->getType()), 399320389d4Svporpo 1u); 400d047488dSVasileios Porpodas EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S0), 1u); 401320389d4Svporpo EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S1->getValueOperand()->getType()), 402320389d4Svporpo 2u); 403d047488dSVasileios Porpodas EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S1), 2u); 404320389d4Svporpo EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Ret->getReturnValue()->getType()), 405320389d4Svporpo 4u); 406d047488dSVasileios Porpodas EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Ret), 4u); 407320389d4Svporpo 408320389d4Svporpo SmallVector<sandboxir::Value *> Bndl({S0, S1, Ret}); 409320389d4Svporpo EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Bndl), 7u); 410320389d4Svporpo } 411320389d4Svporpo 412320389d4Svporpo TEST_F(VecUtilsTest, GetWideType) { 413320389d4Svporpo sandboxir::Context Ctx(C); 414320389d4Svporpo 415320389d4Svporpo auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx); 416320389d4Svporpo auto *Int32X4Ty = sandboxir::FixedVectorType::get(Int32Ty, 4); 417320389d4Svporpo EXPECT_EQ(sandboxir::VecUtils::getWideType(Int32Ty, 4), Int32X4Ty); 418320389d4Svporpo auto *Int32X8Ty = sandboxir::FixedVectorType::get(Int32Ty, 8); 419320389d4Svporpo EXPECT_EQ(sandboxir::VecUtils::getWideType(Int32X4Ty, 2), Int32X8Ty); 420320389d4Svporpo } 421f7ef7b2fSvporpo 422f7ef7b2fSvporpo TEST_F(VecUtilsTest, GetLowest) { 423f7ef7b2fSvporpo parseIR(R"IR( 424f7ef7b2fSvporpo define void @foo(i8 %v) { 425f7ef7b2fSvporpo bb0: 4262dc1c955Svporpo br label %bb1 4272dc1c955Svporpo bb1: 4282dc1c955Svporpo %A = add i8 %v, 1 4292dc1c955Svporpo %B = add i8 %v, 2 4302dc1c955Svporpo %C = add i8 %v, 3 431f7ef7b2fSvporpo ret void 432f7ef7b2fSvporpo } 433f7ef7b2fSvporpo )IR"); 434f7ef7b2fSvporpo Function &LLVMF = *M->getFunction("foo"); 435f7ef7b2fSvporpo 436f7ef7b2fSvporpo sandboxir::Context Ctx(C); 437f7ef7b2fSvporpo auto &F = *Ctx.createFunction(&LLVMF); 4382dc1c955Svporpo auto &BB0 = getBasicBlockByName(F, "bb0"); 4392dc1c955Svporpo auto It = BB0.begin(); 4402dc1c955Svporpo auto *BB0I = cast<sandboxir::BranchInst>(&*It++); 4412dc1c955Svporpo 4422dc1c955Svporpo auto &BB = getBasicBlockByName(F, "bb1"); 4432dc1c955Svporpo It = BB.begin(); 4442dc1c955Svporpo auto *IA = cast<sandboxir::Instruction>(&*It++); 4452dc1c955Svporpo auto *C1 = cast<sandboxir::Constant>(IA->getOperand(1)); 4462dc1c955Svporpo auto *IB = cast<sandboxir::Instruction>(&*It++); 4472dc1c955Svporpo auto *C2 = cast<sandboxir::Constant>(IB->getOperand(1)); 4482dc1c955Svporpo auto *IC = cast<sandboxir::Instruction>(&*It++); 4492dc1c955Svporpo auto *C3 = cast<sandboxir::Constant>(IC->getOperand(1)); 4502dc1c955Svporpo // Check getLowest(ArrayRef<Instruction *>) 4512dc1c955Svporpo SmallVector<sandboxir::Instruction *> A({IA}); 4522dc1c955Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(A), IA); 453f7ef7b2fSvporpo SmallVector<sandboxir::Instruction *> ABC({IA, IB, IC}); 454f7ef7b2fSvporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(ABC), IC); 455f7ef7b2fSvporpo SmallVector<sandboxir::Instruction *> ACB({IA, IC, IB}); 456f7ef7b2fSvporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(ACB), IC); 457f7ef7b2fSvporpo SmallVector<sandboxir::Instruction *> CAB({IC, IA, IB}); 458f7ef7b2fSvporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(CAB), IC); 459f7ef7b2fSvporpo SmallVector<sandboxir::Instruction *> CBA({IC, IB, IA}); 460f7ef7b2fSvporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(CBA), IC); 4612dc1c955Svporpo 4622dc1c955Svporpo // Check getLowest(ArrayRef<Value *>) 4632dc1c955Svporpo SmallVector<sandboxir::Value *> C1Only({C1}); 464*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(C1Only, &BB), nullptr); 465*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(C1Only, &BB0), nullptr); 4662dc1c955Svporpo SmallVector<sandboxir::Value *> AOnly({IA}); 467*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(AOnly, &BB), IA); 468*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(AOnly, &BB0), nullptr); 4692dc1c955Svporpo SmallVector<sandboxir::Value *> AC1({IA, C1}); 470*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1, &BB), IA); 471*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1, &BB0), nullptr); 4722dc1c955Svporpo SmallVector<sandboxir::Value *> C1A({C1, IA}); 473*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(C1A, &BB), IA); 474*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(C1A, &BB0), nullptr); 4752dc1c955Svporpo SmallVector<sandboxir::Value *> AC1B({IA, C1, IB}); 476*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1B, &BB), IB); 477*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1B, &BB0), nullptr); 4782dc1c955Svporpo SmallVector<sandboxir::Value *> ABC1({IA, IB, C1}); 479*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(ABC1, &BB), IB); 480*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(ABC1, &BB0), nullptr); 4812dc1c955Svporpo SmallVector<sandboxir::Value *> AC1C2({IA, C1, C2}); 482*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1C2, &BB), IA); 483*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1C2, &BB0), nullptr); 4842dc1c955Svporpo SmallVector<sandboxir::Value *> C1C2C3({C1, C2, C3}); 485*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(C1C2C3, &BB), nullptr); 486*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(C1C2C3, &BB0), nullptr); 4872dc1c955Svporpo 4882dc1c955Svporpo SmallVector<sandboxir::Value *> DiffBBs({BB0I, IA}); 489*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(DiffBBs, &BB0), BB0I); 490*ac75d322Svporpo EXPECT_EQ(sandboxir::VecUtils::getLowest(DiffBBs, &BB), IA); 491f7ef7b2fSvporpo } 4923be3b33eSvporpo 493d2234ca1Svporpo TEST_F(VecUtilsTest, GetLastPHIOrSelf) { 494d2234ca1Svporpo parseIR(R"IR( 495d2234ca1Svporpo define void @foo(i8 %v) { 496d2234ca1Svporpo entry: 497d2234ca1Svporpo br label %bb1 498d2234ca1Svporpo 499d2234ca1Svporpo bb1: 500d2234ca1Svporpo %phi1 = phi i8 [0, %entry], [1, %bb1] 501d2234ca1Svporpo %phi2 = phi i8 [0, %entry], [1, %bb1] 502d2234ca1Svporpo br label %bb1 503d2234ca1Svporpo 504d2234ca1Svporpo bb2: 505d2234ca1Svporpo ret void 506d2234ca1Svporpo } 507d2234ca1Svporpo )IR"); 508d2234ca1Svporpo Function &LLVMF = *M->getFunction("foo"); 509d2234ca1Svporpo 510d2234ca1Svporpo sandboxir::Context Ctx(C); 511d2234ca1Svporpo auto &F = *Ctx.createFunction(&LLVMF); 512d2234ca1Svporpo auto &BB = getBasicBlockByName(F, "bb1"); 513d2234ca1Svporpo auto It = BB.begin(); 514d2234ca1Svporpo auto *PHI1 = cast<sandboxir::PHINode>(&*It++); 515d2234ca1Svporpo auto *PHI2 = cast<sandboxir::PHINode>(&*It++); 516d2234ca1Svporpo auto *Br = cast<sandboxir::BranchInst>(&*It++); 517d2234ca1Svporpo EXPECT_EQ(sandboxir::VecUtils::getLastPHIOrSelf(PHI1), PHI2); 518d2234ca1Svporpo EXPECT_EQ(sandboxir::VecUtils::getLastPHIOrSelf(PHI2), PHI2); 519d2234ca1Svporpo EXPECT_EQ(sandboxir::VecUtils::getLastPHIOrSelf(Br), Br); 520d2234ca1Svporpo EXPECT_EQ(sandboxir::VecUtils::getLastPHIOrSelf(nullptr), nullptr); 521d2234ca1Svporpo } 522d2234ca1Svporpo 5233be3b33eSvporpo TEST_F(VecUtilsTest, GetCommonScalarType) { 5243be3b33eSvporpo parseIR(R"IR( 5253be3b33eSvporpo define void @foo(i8 %v, ptr %ptr) { 5263be3b33eSvporpo bb0: 5273be3b33eSvporpo %add0 = add i8 %v, %v 5283be3b33eSvporpo store i8 %v, ptr %ptr 5293be3b33eSvporpo ret void 5303be3b33eSvporpo } 5313be3b33eSvporpo )IR"); 5323be3b33eSvporpo Function &LLVMF = *M->getFunction("foo"); 5333be3b33eSvporpo 5343be3b33eSvporpo sandboxir::Context Ctx(C); 5353be3b33eSvporpo auto &F = *Ctx.createFunction(&LLVMF); 5363be3b33eSvporpo auto &BB = *F.begin(); 5373be3b33eSvporpo auto It = BB.begin(); 5383be3b33eSvporpo auto *Add0 = cast<sandboxir::BinaryOperator>(&*It++); 5393be3b33eSvporpo auto *Store = cast<sandboxir::StoreInst>(&*It++); 5403be3b33eSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 5413be3b33eSvporpo { 5423be3b33eSvporpo SmallVector<sandboxir::Value *> Vec = {Add0, Store}; 5433be3b33eSvporpo EXPECT_EQ(sandboxir::VecUtils::tryGetCommonScalarType(Vec), 5443be3b33eSvporpo Add0->getType()); 5453be3b33eSvporpo EXPECT_EQ(sandboxir::VecUtils::getCommonScalarType(Vec), Add0->getType()); 5463be3b33eSvporpo } 5473be3b33eSvporpo { 5483be3b33eSvporpo SmallVector<sandboxir::Value *> Vec = {Add0, Ret}; 5493be3b33eSvporpo EXPECT_EQ(sandboxir::VecUtils::tryGetCommonScalarType(Vec), nullptr); 5503be3b33eSvporpo #ifndef NDEBUG 5513be3b33eSvporpo EXPECT_DEATH(sandboxir::VecUtils::getCommonScalarType(Vec), ".*common.*"); 5523be3b33eSvporpo #endif // NDEBUG 5533be3b33eSvporpo } 5543be3b33eSvporpo } 5556312beefSvporpo 5566312beefSvporpo TEST_F(VecUtilsTest, FloorPowerOf2) { 5576312beefSvporpo EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(0), 0u); 5586312beefSvporpo EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(1 << 0), 1u << 0); 5596312beefSvporpo EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(3), 2u); 5606312beefSvporpo EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(4), 4u); 5616312beefSvporpo EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(5), 4u); 5626312beefSvporpo EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(7), 4u); 5636312beefSvporpo EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(8), 8u); 5646312beefSvporpo EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(9), 8u); 5656312beefSvporpo } 566