1 //===- VecUtilsTest.cpp --------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h" 10 #include "llvm/Analysis/AliasAnalysis.h" 11 #include "llvm/Analysis/AssumptionCache.h" 12 #include "llvm/Analysis/BasicAliasAnalysis.h" 13 #include "llvm/Analysis/LoopInfo.h" 14 #include "llvm/Analysis/ScalarEvolution.h" 15 #include "llvm/Analysis/TargetLibraryInfo.h" 16 #include "llvm/AsmParser/Parser.h" 17 #include "llvm/IR/DataLayout.h" 18 #include "llvm/IR/Dominators.h" 19 #include "llvm/SandboxIR/Context.h" 20 #include "llvm/SandboxIR/Function.h" 21 #include "llvm/SandboxIR/Type.h" 22 #include "llvm/Support/SourceMgr.h" 23 #include "gtest/gtest.h" 24 25 using namespace llvm; 26 27 struct VecUtilsTest : public testing::Test { 28 LLVMContext C; 29 std::unique_ptr<Module> M; 30 std::unique_ptr<AssumptionCache> AC; 31 std::unique_ptr<TargetLibraryInfoImpl> TLII; 32 std::unique_ptr<TargetLibraryInfo> TLI; 33 std::unique_ptr<DominatorTree> DT; 34 std::unique_ptr<LoopInfo> LI; 35 std::unique_ptr<ScalarEvolution> SE; 36 void parseIR(const char *IR) { 37 SMDiagnostic Err; 38 M = parseAssemblyString(IR, Err, C); 39 if (!M) 40 Err.print("VecUtilsTest", errs()); 41 } 42 ScalarEvolution &getSE(llvm::Function &LLVMF) { 43 TLII = std::make_unique<TargetLibraryInfoImpl>(); 44 TLI = std::make_unique<TargetLibraryInfo>(*TLII); 45 AC = std::make_unique<AssumptionCache>(LLVMF); 46 DT = std::make_unique<DominatorTree>(LLVMF); 47 LI = std::make_unique<LoopInfo>(*DT); 48 SE = std::make_unique<ScalarEvolution>(LLVMF, *TLI, *AC, *DT, *LI); 49 return *SE; 50 } 51 }; 52 53 sandboxir::BasicBlock &getBasicBlockByName(sandboxir::Function &F, 54 StringRef Name) { 55 for (sandboxir::BasicBlock &BB : F) 56 if (BB.getName() == Name) 57 return BB; 58 llvm_unreachable("Expected to find basic block!"); 59 } 60 61 TEST_F(VecUtilsTest, GetNumElements) { 62 sandboxir::Context Ctx(C); 63 auto *ElemTy = sandboxir::Type::getInt32Ty(Ctx); 64 EXPECT_EQ(sandboxir::VecUtils::getNumElements(ElemTy), 1); 65 auto *VTy = sandboxir::FixedVectorType::get(ElemTy, 2); 66 EXPECT_EQ(sandboxir::VecUtils::getNumElements(VTy), 2); 67 auto *VTy1 = sandboxir::FixedVectorType::get(ElemTy, 1); 68 EXPECT_EQ(sandboxir::VecUtils::getNumElements(VTy1), 1); 69 } 70 71 TEST_F(VecUtilsTest, GetElementType) { 72 sandboxir::Context Ctx(C); 73 auto *ElemTy = sandboxir::Type::getInt32Ty(Ctx); 74 EXPECT_EQ(sandboxir::VecUtils::getElementType(ElemTy), ElemTy); 75 auto *VTy = sandboxir::FixedVectorType::get(ElemTy, 2); 76 EXPECT_EQ(sandboxir::VecUtils::getElementType(VTy), ElemTy); 77 } 78 79 TEST_F(VecUtilsTest, AreConsecutive_gep_float) { 80 parseIR(R"IR( 81 define void @foo(ptr %ptr) { 82 %gep0 = getelementptr inbounds float, ptr %ptr, i64 0 83 %gep1 = getelementptr inbounds float, ptr %ptr, i64 1 84 %gep2 = getelementptr inbounds float, ptr %ptr, i64 2 85 %gep3 = getelementptr inbounds float, ptr %ptr, i64 3 86 87 %ld0 = load float, ptr %gep0 88 %ld1 = load float, ptr %gep1 89 %ld2 = load float, ptr %gep2 90 %ld3 = load float, ptr %gep3 91 92 %v2ld0 = load <2 x float>, ptr %gep0 93 %v2ld1 = load <2 x float>, ptr %gep1 94 %v2ld2 = load <2 x float>, ptr %gep2 95 %v2ld3 = load <2 x float>, ptr %gep3 96 97 %v3ld0 = load <3 x float>, ptr %gep0 98 %v3ld1 = load <3 x float>, ptr %gep1 99 %v3ld2 = load <3 x float>, ptr %gep2 100 %v3ld3 = load <3 x float>, ptr %gep3 101 ret void 102 } 103 )IR"); 104 Function &LLVMF = *M->getFunction("foo"); 105 const DataLayout &DL = M->getDataLayout(); 106 auto &SE = getSE(LLVMF); 107 108 sandboxir::Context Ctx(C); 109 auto &F = *Ctx.createFunction(&LLVMF); 110 111 auto &BB = *F.begin(); 112 auto It = std::next(BB.begin(), 4); 113 auto *L0 = cast<sandboxir::LoadInst>(&*It++); 114 auto *L1 = cast<sandboxir::LoadInst>(&*It++); 115 auto *L2 = cast<sandboxir::LoadInst>(&*It++); 116 auto *L3 = cast<sandboxir::LoadInst>(&*It++); 117 118 auto *V2L0 = cast<sandboxir::LoadInst>(&*It++); 119 auto *V2L1 = cast<sandboxir::LoadInst>(&*It++); 120 auto *V2L2 = cast<sandboxir::LoadInst>(&*It++); 121 auto *V2L3 = cast<sandboxir::LoadInst>(&*It++); 122 123 auto *V3L0 = cast<sandboxir::LoadInst>(&*It++); 124 auto *V3L1 = cast<sandboxir::LoadInst>(&*It++); 125 auto *V3L2 = cast<sandboxir::LoadInst>(&*It++); 126 auto *V3L3 = cast<sandboxir::LoadInst>(&*It++); 127 128 // Scalar 129 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL)); 130 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL)); 131 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL)); 132 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL)); 133 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL)); 134 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL)); 135 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL)); 136 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL)); 137 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL)); 138 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL)); 139 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL)); 140 141 // Check 2-wide loads 142 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL)); 143 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL)); 144 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL)); 145 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL)); 146 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL)); 147 148 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 149 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 150 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 151 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 152 153 // Check 3-wide loads 154 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL)); 155 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL)); 156 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL)); 157 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL)); 158 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL)); 159 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL)); 160 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL)); 161 162 // Check mixes of vectors and scalar 163 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL)); 164 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL)); 165 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL)); 166 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL)); 167 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL)); 168 169 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL)); 170 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL)); 171 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL)); 172 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL)); 173 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL)); 174 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL)); 175 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL)); 176 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL)); 177 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL)); 178 } 179 180 TEST_F(VecUtilsTest, AreConsecutive_gep_i8) { 181 parseIR(R"IR( 182 define void @foo(ptr %ptr) { 183 %gep0 = getelementptr inbounds i8, ptr %ptr, i64 0 184 %gep1 = getelementptr inbounds i8, ptr %ptr, i64 4 185 %gep2 = getelementptr inbounds i8, ptr %ptr, i64 8 186 %gep3 = getelementptr inbounds i8, ptr %ptr, i64 12 187 188 %ld0 = load float, ptr %gep0 189 %ld1 = load float, ptr %gep1 190 %ld2 = load float, ptr %gep2 191 %ld3 = load float, ptr %gep3 192 193 %v2ld0 = load <2 x float>, ptr %gep0 194 %v2ld1 = load <2 x float>, ptr %gep1 195 %v2ld2 = load <2 x float>, ptr %gep2 196 %v2ld3 = load <2 x float>, ptr %gep3 197 198 %v3ld0 = load <3 x float>, ptr %gep0 199 %v3ld1 = load <3 x float>, ptr %gep1 200 %v3ld2 = load <3 x float>, ptr %gep2 201 %v3ld3 = load <3 x float>, ptr %gep3 202 ret void 203 } 204 )IR"); 205 Function &LLVMF = *M->getFunction("foo"); 206 const DataLayout &DL = M->getDataLayout(); 207 auto &SE = getSE(LLVMF); 208 209 sandboxir::Context Ctx(C); 210 auto &F = *Ctx.createFunction(&LLVMF); 211 auto &BB = *F.begin(); 212 auto It = std::next(BB.begin(), 4); 213 auto *L0 = cast<sandboxir::LoadInst>(&*It++); 214 auto *L1 = cast<sandboxir::LoadInst>(&*It++); 215 auto *L2 = cast<sandboxir::LoadInst>(&*It++); 216 auto *L3 = cast<sandboxir::LoadInst>(&*It++); 217 218 auto *V2L0 = cast<sandboxir::LoadInst>(&*It++); 219 auto *V2L1 = cast<sandboxir::LoadInst>(&*It++); 220 auto *V2L2 = cast<sandboxir::LoadInst>(&*It++); 221 auto *V2L3 = cast<sandboxir::LoadInst>(&*It++); 222 223 auto *V3L0 = cast<sandboxir::LoadInst>(&*It++); 224 auto *V3L1 = cast<sandboxir::LoadInst>(&*It++); 225 auto *V3L2 = cast<sandboxir::LoadInst>(&*It++); 226 auto *V3L3 = cast<sandboxir::LoadInst>(&*It++); 227 228 // Scalar 229 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL)); 230 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL)); 231 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL)); 232 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL)); 233 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL)); 234 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL)); 235 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL)); 236 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL)); 237 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL)); 238 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL)); 239 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL)); 240 241 // Check 2-wide loads 242 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL)); 243 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL)); 244 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL)); 245 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL)); 246 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL)); 247 248 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 249 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 250 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 251 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 252 253 // Check 3-wide loads 254 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL)); 255 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL)); 256 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL)); 257 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL)); 258 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL)); 259 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL)); 260 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL)); 261 262 // Check mixes of vectors and scalar 263 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL)); 264 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL)); 265 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL)); 266 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL)); 267 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL)); 268 269 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL)); 270 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL)); 271 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL)); 272 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL)); 273 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL)); 274 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL)); 275 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL)); 276 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL)); 277 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL)); 278 } 279 280 TEST_F(VecUtilsTest, AreConsecutive_gep_i1) { 281 parseIR(R"IR( 282 define void @foo(ptr %ptr) { 283 %gep0 = getelementptr inbounds i1, ptr %ptr, i64 0 284 %gep1 = getelementptr inbounds i2, ptr %ptr, i64 4 285 %gep2 = getelementptr inbounds i3, ptr %ptr, i64 8 286 %gep3 = getelementptr inbounds i7, ptr %ptr, i64 12 287 288 %ld0 = load float, ptr %gep0 289 %ld1 = load float, ptr %gep1 290 %ld2 = load float, ptr %gep2 291 %ld3 = load float, ptr %gep3 292 293 %v2ld0 = load <2 x float>, ptr %gep0 294 %v2ld1 = load <2 x float>, ptr %gep1 295 %v2ld2 = load <2 x float>, ptr %gep2 296 %v2ld3 = load <2 x float>, ptr %gep3 297 298 %v3ld0 = load <3 x float>, ptr %gep0 299 %v3ld1 = load <3 x float>, ptr %gep1 300 %v3ld2 = load <3 x float>, ptr %gep2 301 %v3ld3 = load <3 x float>, ptr %gep3 302 ret void 303 } 304 )IR"); 305 Function &LLVMF = *M->getFunction("foo"); 306 const DataLayout &DL = M->getDataLayout(); 307 auto &SE = getSE(LLVMF); 308 309 sandboxir::Context Ctx(C); 310 auto &F = *Ctx.createFunction(&LLVMF); 311 auto &BB = *F.begin(); 312 auto It = std::next(BB.begin(), 4); 313 auto *L0 = cast<sandboxir::LoadInst>(&*It++); 314 auto *L1 = cast<sandboxir::LoadInst>(&*It++); 315 auto *L2 = cast<sandboxir::LoadInst>(&*It++); 316 auto *L3 = cast<sandboxir::LoadInst>(&*It++); 317 318 auto *V2L0 = cast<sandboxir::LoadInst>(&*It++); 319 auto *V2L1 = cast<sandboxir::LoadInst>(&*It++); 320 auto *V2L2 = cast<sandboxir::LoadInst>(&*It++); 321 auto *V2L3 = cast<sandboxir::LoadInst>(&*It++); 322 323 auto *V3L0 = cast<sandboxir::LoadInst>(&*It++); 324 auto *V3L1 = cast<sandboxir::LoadInst>(&*It++); 325 auto *V3L2 = cast<sandboxir::LoadInst>(&*It++); 326 auto *V3L3 = cast<sandboxir::LoadInst>(&*It++); 327 328 // Scalar 329 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL)); 330 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL)); 331 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL)); 332 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL)); 333 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL)); 334 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL)); 335 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL)); 336 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL)); 337 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL)); 338 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL)); 339 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL)); 340 341 // Check 2-wide loads 342 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL)); 343 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL)); 344 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL)); 345 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL)); 346 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL)); 347 348 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 349 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 350 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 351 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL)); 352 353 // Check 3-wide loads 354 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL)); 355 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL)); 356 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL)); 357 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL)); 358 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL)); 359 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL)); 360 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL)); 361 362 // Check mixes of vectors and scalar 363 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL)); 364 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL)); 365 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL)); 366 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL)); 367 EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL)); 368 369 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL)); 370 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL)); 371 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL)); 372 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL)); 373 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL)); 374 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL)); 375 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL)); 376 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL)); 377 EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL)); 378 } 379 380 TEST_F(VecUtilsTest, GetNumLanes) { 381 parseIR(R"IR( 382 define <4 x float> @foo(float %v, <2 x float> %v2, <4 x float> %ret, ptr %ptr) { 383 store float %v, ptr %ptr 384 store <2 x float> %v2, ptr %ptr 385 ret <4 x float> %ret 386 } 387 )IR"); 388 Function &LLVMF = *M->getFunction("foo"); 389 390 sandboxir::Context Ctx(C); 391 auto &F = *Ctx.createFunction(&LLVMF); 392 auto &BB = *F.begin(); 393 394 auto It = BB.begin(); 395 auto *S0 = cast<sandboxir::StoreInst>(&*It++); 396 auto *S1 = cast<sandboxir::StoreInst>(&*It++); 397 auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 398 EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S0->getValueOperand()->getType()), 399 1u); 400 EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S0), 1u); 401 EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S1->getValueOperand()->getType()), 402 2u); 403 EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S1), 2u); 404 EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Ret->getReturnValue()->getType()), 405 4u); 406 EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Ret), 4u); 407 408 SmallVector<sandboxir::Value *> Bndl({S0, S1, Ret}); 409 EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Bndl), 7u); 410 } 411 412 TEST_F(VecUtilsTest, GetWideType) { 413 sandboxir::Context Ctx(C); 414 415 auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx); 416 auto *Int32X4Ty = sandboxir::FixedVectorType::get(Int32Ty, 4); 417 EXPECT_EQ(sandboxir::VecUtils::getWideType(Int32Ty, 4), Int32X4Ty); 418 auto *Int32X8Ty = sandboxir::FixedVectorType::get(Int32Ty, 8); 419 EXPECT_EQ(sandboxir::VecUtils::getWideType(Int32X4Ty, 2), Int32X8Ty); 420 } 421 422 TEST_F(VecUtilsTest, GetLowest) { 423 parseIR(R"IR( 424 define void @foo(i8 %v) { 425 bb0: 426 br label %bb1 427 bb1: 428 %A = add i8 %v, 1 429 %B = add i8 %v, 2 430 %C = add i8 %v, 3 431 ret void 432 } 433 )IR"); 434 Function &LLVMF = *M->getFunction("foo"); 435 436 sandboxir::Context Ctx(C); 437 auto &F = *Ctx.createFunction(&LLVMF); 438 auto &BB0 = getBasicBlockByName(F, "bb0"); 439 auto It = BB0.begin(); 440 auto *BB0I = cast<sandboxir::BranchInst>(&*It++); 441 442 auto &BB = getBasicBlockByName(F, "bb1"); 443 It = BB.begin(); 444 auto *IA = cast<sandboxir::Instruction>(&*It++); 445 auto *C1 = cast<sandboxir::Constant>(IA->getOperand(1)); 446 auto *IB = cast<sandboxir::Instruction>(&*It++); 447 auto *C2 = cast<sandboxir::Constant>(IB->getOperand(1)); 448 auto *IC = cast<sandboxir::Instruction>(&*It++); 449 auto *C3 = cast<sandboxir::Constant>(IC->getOperand(1)); 450 // Check getLowest(ArrayRef<Instruction *>) 451 SmallVector<sandboxir::Instruction *> A({IA}); 452 EXPECT_EQ(sandboxir::VecUtils::getLowest(A), IA); 453 SmallVector<sandboxir::Instruction *> ABC({IA, IB, IC}); 454 EXPECT_EQ(sandboxir::VecUtils::getLowest(ABC), IC); 455 SmallVector<sandboxir::Instruction *> ACB({IA, IC, IB}); 456 EXPECT_EQ(sandboxir::VecUtils::getLowest(ACB), IC); 457 SmallVector<sandboxir::Instruction *> CAB({IC, IA, IB}); 458 EXPECT_EQ(sandboxir::VecUtils::getLowest(CAB), IC); 459 SmallVector<sandboxir::Instruction *> CBA({IC, IB, IA}); 460 EXPECT_EQ(sandboxir::VecUtils::getLowest(CBA), IC); 461 462 // Check getLowest(ArrayRef<Value *>) 463 SmallVector<sandboxir::Value *> C1Only({C1}); 464 EXPECT_EQ(sandboxir::VecUtils::getLowest(C1Only, &BB), nullptr); 465 EXPECT_EQ(sandboxir::VecUtils::getLowest(C1Only, &BB0), nullptr); 466 SmallVector<sandboxir::Value *> AOnly({IA}); 467 EXPECT_EQ(sandboxir::VecUtils::getLowest(AOnly, &BB), IA); 468 EXPECT_EQ(sandboxir::VecUtils::getLowest(AOnly, &BB0), nullptr); 469 SmallVector<sandboxir::Value *> AC1({IA, C1}); 470 EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1, &BB), IA); 471 EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1, &BB0), nullptr); 472 SmallVector<sandboxir::Value *> C1A({C1, IA}); 473 EXPECT_EQ(sandboxir::VecUtils::getLowest(C1A, &BB), IA); 474 EXPECT_EQ(sandboxir::VecUtils::getLowest(C1A, &BB0), nullptr); 475 SmallVector<sandboxir::Value *> AC1B({IA, C1, IB}); 476 EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1B, &BB), IB); 477 EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1B, &BB0), nullptr); 478 SmallVector<sandboxir::Value *> ABC1({IA, IB, C1}); 479 EXPECT_EQ(sandboxir::VecUtils::getLowest(ABC1, &BB), IB); 480 EXPECT_EQ(sandboxir::VecUtils::getLowest(ABC1, &BB0), nullptr); 481 SmallVector<sandboxir::Value *> AC1C2({IA, C1, C2}); 482 EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1C2, &BB), IA); 483 EXPECT_EQ(sandboxir::VecUtils::getLowest(AC1C2, &BB0), nullptr); 484 SmallVector<sandboxir::Value *> C1C2C3({C1, C2, C3}); 485 EXPECT_EQ(sandboxir::VecUtils::getLowest(C1C2C3, &BB), nullptr); 486 EXPECT_EQ(sandboxir::VecUtils::getLowest(C1C2C3, &BB0), nullptr); 487 488 SmallVector<sandboxir::Value *> DiffBBs({BB0I, IA}); 489 EXPECT_EQ(sandboxir::VecUtils::getLowest(DiffBBs, &BB0), BB0I); 490 EXPECT_EQ(sandboxir::VecUtils::getLowest(DiffBBs, &BB), IA); 491 } 492 493 TEST_F(VecUtilsTest, GetLastPHIOrSelf) { 494 parseIR(R"IR( 495 define void @foo(i8 %v) { 496 entry: 497 br label %bb1 498 499 bb1: 500 %phi1 = phi i8 [0, %entry], [1, %bb1] 501 %phi2 = phi i8 [0, %entry], [1, %bb1] 502 br label %bb1 503 504 bb2: 505 ret void 506 } 507 )IR"); 508 Function &LLVMF = *M->getFunction("foo"); 509 510 sandboxir::Context Ctx(C); 511 auto &F = *Ctx.createFunction(&LLVMF); 512 auto &BB = getBasicBlockByName(F, "bb1"); 513 auto It = BB.begin(); 514 auto *PHI1 = cast<sandboxir::PHINode>(&*It++); 515 auto *PHI2 = cast<sandboxir::PHINode>(&*It++); 516 auto *Br = cast<sandboxir::BranchInst>(&*It++); 517 EXPECT_EQ(sandboxir::VecUtils::getLastPHIOrSelf(PHI1), PHI2); 518 EXPECT_EQ(sandboxir::VecUtils::getLastPHIOrSelf(PHI2), PHI2); 519 EXPECT_EQ(sandboxir::VecUtils::getLastPHIOrSelf(Br), Br); 520 EXPECT_EQ(sandboxir::VecUtils::getLastPHIOrSelf(nullptr), nullptr); 521 } 522 523 TEST_F(VecUtilsTest, GetCommonScalarType) { 524 parseIR(R"IR( 525 define void @foo(i8 %v, ptr %ptr) { 526 bb0: 527 %add0 = add i8 %v, %v 528 store i8 %v, ptr %ptr 529 ret void 530 } 531 )IR"); 532 Function &LLVMF = *M->getFunction("foo"); 533 534 sandboxir::Context Ctx(C); 535 auto &F = *Ctx.createFunction(&LLVMF); 536 auto &BB = *F.begin(); 537 auto It = BB.begin(); 538 auto *Add0 = cast<sandboxir::BinaryOperator>(&*It++); 539 auto *Store = cast<sandboxir::StoreInst>(&*It++); 540 auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 541 { 542 SmallVector<sandboxir::Value *> Vec = {Add0, Store}; 543 EXPECT_EQ(sandboxir::VecUtils::tryGetCommonScalarType(Vec), 544 Add0->getType()); 545 EXPECT_EQ(sandboxir::VecUtils::getCommonScalarType(Vec), Add0->getType()); 546 } 547 { 548 SmallVector<sandboxir::Value *> Vec = {Add0, Ret}; 549 EXPECT_EQ(sandboxir::VecUtils::tryGetCommonScalarType(Vec), nullptr); 550 #ifndef NDEBUG 551 EXPECT_DEATH(sandboxir::VecUtils::getCommonScalarType(Vec), ".*common.*"); 552 #endif // NDEBUG 553 } 554 } 555 556 TEST_F(VecUtilsTest, FloorPowerOf2) { 557 EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(0), 0u); 558 EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(1 << 0), 1u << 0); 559 EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(3), 2u); 560 EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(4), 4u); 561 EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(5), 4u); 562 EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(7), 4u); 563 EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(8), 8u); 564 EXPECT_EQ(sandboxir::VecUtils::getFloorPowerOf2(9), 8u); 565 } 566