xref: /llvm-project/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/VecUtilsTest.cpp (revision ac75d322801411f496fe5d1155c86453f915ae98)
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