xref: /llvm-project/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/VecUtilsTest.cpp (revision 320389d4289c9bca579d74e9416bedb7fd4a0ef2)
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 TEST_F(VecUtilsTest, GetNumElements) {
54   sandboxir::Context Ctx(C);
55   auto *ElemTy = sandboxir::Type::getInt32Ty(Ctx);
56   EXPECT_EQ(sandboxir::VecUtils::getNumElements(ElemTy), 1);
57   auto *VTy = sandboxir::FixedVectorType::get(ElemTy, 2);
58   EXPECT_EQ(sandboxir::VecUtils::getNumElements(VTy), 2);
59   auto *VTy1 = sandboxir::FixedVectorType::get(ElemTy, 1);
60   EXPECT_EQ(sandboxir::VecUtils::getNumElements(VTy1), 1);
61 }
62 
63 TEST_F(VecUtilsTest, GetElementType) {
64   sandboxir::Context Ctx(C);
65   auto *ElemTy = sandboxir::Type::getInt32Ty(Ctx);
66   EXPECT_EQ(sandboxir::VecUtils::getElementType(ElemTy), ElemTy);
67   auto *VTy = sandboxir::FixedVectorType::get(ElemTy, 2);
68   EXPECT_EQ(sandboxir::VecUtils::getElementType(VTy), ElemTy);
69 }
70 
71 TEST_F(VecUtilsTest, AreConsecutive_gep_float) {
72   parseIR(R"IR(
73 define void @foo(ptr %ptr) {
74   %gep0 = getelementptr inbounds float, ptr %ptr, i64 0
75   %gep1 = getelementptr inbounds float, ptr %ptr, i64 1
76   %gep2 = getelementptr inbounds float, ptr %ptr, i64 2
77   %gep3 = getelementptr inbounds float, ptr %ptr, i64 3
78 
79   %ld0 = load float, ptr %gep0
80   %ld1 = load float, ptr %gep1
81   %ld2 = load float, ptr %gep2
82   %ld3 = load float, ptr %gep3
83 
84   %v2ld0 = load <2 x float>, ptr %gep0
85   %v2ld1 = load <2 x float>, ptr %gep1
86   %v2ld2 = load <2 x float>, ptr %gep2
87   %v2ld3 = load <2 x float>, ptr %gep3
88 
89   %v3ld0 = load <3 x float>, ptr %gep0
90   %v3ld1 = load <3 x float>, ptr %gep1
91   %v3ld2 = load <3 x float>, ptr %gep2
92   %v3ld3 = load <3 x float>, ptr %gep3
93   ret void
94 }
95 )IR");
96   Function &LLVMF = *M->getFunction("foo");
97   const DataLayout &DL = M->getDataLayout();
98   auto &SE = getSE(LLVMF);
99 
100   sandboxir::Context Ctx(C);
101   auto &F = *Ctx.createFunction(&LLVMF);
102 
103   auto &BB = *F.begin();
104   auto It = std::next(BB.begin(), 4);
105   auto *L0 = cast<sandboxir::LoadInst>(&*It++);
106   auto *L1 = cast<sandboxir::LoadInst>(&*It++);
107   auto *L2 = cast<sandboxir::LoadInst>(&*It++);
108   auto *L3 = cast<sandboxir::LoadInst>(&*It++);
109 
110   auto *V2L0 = cast<sandboxir::LoadInst>(&*It++);
111   auto *V2L1 = cast<sandboxir::LoadInst>(&*It++);
112   auto *V2L2 = cast<sandboxir::LoadInst>(&*It++);
113   auto *V2L3 = cast<sandboxir::LoadInst>(&*It++);
114 
115   auto *V3L0 = cast<sandboxir::LoadInst>(&*It++);
116   auto *V3L1 = cast<sandboxir::LoadInst>(&*It++);
117   auto *V3L2 = cast<sandboxir::LoadInst>(&*It++);
118   auto *V3L3 = cast<sandboxir::LoadInst>(&*It++);
119 
120   // Scalar
121   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL));
122   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL));
123   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL));
124   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL));
125   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL));
126   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL));
127   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL));
128   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL));
129   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL));
130   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL));
131   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL));
132 
133   // Check 2-wide loads
134   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL));
135   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL));
136   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL));
137   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL));
138   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL));
139 
140   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
141   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
142   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
143   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
144 
145   // Check 3-wide loads
146   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL));
147   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL));
148   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL));
149   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL));
150   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL));
151   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL));
152   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL));
153 
154   // Check mixes of vectors and scalar
155   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL));
156   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL));
157   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL));
158   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL));
159   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL));
160 
161   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL));
162   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL));
163   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL));
164   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL));
165   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL));
166   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL));
167   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL));
168   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL));
169   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL));
170 }
171 
172 TEST_F(VecUtilsTest, AreConsecutive_gep_i8) {
173   parseIR(R"IR(
174 define void @foo(ptr %ptr) {
175   %gep0 = getelementptr inbounds i8, ptr %ptr, i64 0
176   %gep1 = getelementptr inbounds i8, ptr %ptr, i64 4
177   %gep2 = getelementptr inbounds i8, ptr %ptr, i64 8
178   %gep3 = getelementptr inbounds i8, ptr %ptr, i64 12
179 
180   %ld0 = load float, ptr %gep0
181   %ld1 = load float, ptr %gep1
182   %ld2 = load float, ptr %gep2
183   %ld3 = load float, ptr %gep3
184 
185   %v2ld0 = load <2 x float>, ptr %gep0
186   %v2ld1 = load <2 x float>, ptr %gep1
187   %v2ld2 = load <2 x float>, ptr %gep2
188   %v2ld3 = load <2 x float>, ptr %gep3
189 
190   %v3ld0 = load <3 x float>, ptr %gep0
191   %v3ld1 = load <3 x float>, ptr %gep1
192   %v3ld2 = load <3 x float>, ptr %gep2
193   %v3ld3 = load <3 x float>, ptr %gep3
194   ret void
195 }
196 )IR");
197   Function &LLVMF = *M->getFunction("foo");
198   const DataLayout &DL = M->getDataLayout();
199   auto &SE = getSE(LLVMF);
200 
201   sandboxir::Context Ctx(C);
202   auto &F = *Ctx.createFunction(&LLVMF);
203   auto &BB = *F.begin();
204   auto It = std::next(BB.begin(), 4);
205   auto *L0 = cast<sandboxir::LoadInst>(&*It++);
206   auto *L1 = cast<sandboxir::LoadInst>(&*It++);
207   auto *L2 = cast<sandboxir::LoadInst>(&*It++);
208   auto *L3 = cast<sandboxir::LoadInst>(&*It++);
209 
210   auto *V2L0 = cast<sandboxir::LoadInst>(&*It++);
211   auto *V2L1 = cast<sandboxir::LoadInst>(&*It++);
212   auto *V2L2 = cast<sandboxir::LoadInst>(&*It++);
213   auto *V2L3 = cast<sandboxir::LoadInst>(&*It++);
214 
215   auto *V3L0 = cast<sandboxir::LoadInst>(&*It++);
216   auto *V3L1 = cast<sandboxir::LoadInst>(&*It++);
217   auto *V3L2 = cast<sandboxir::LoadInst>(&*It++);
218   auto *V3L3 = cast<sandboxir::LoadInst>(&*It++);
219 
220   // Scalar
221   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL));
222   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL));
223   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL));
224   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL));
225   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL));
226   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL));
227   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL));
228   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL));
229   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL));
230   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL));
231   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL));
232 
233   // Check 2-wide loads
234   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL));
235   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL));
236   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL));
237   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL));
238   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL));
239 
240   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
241   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
242   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
243   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
244 
245   // Check 3-wide loads
246   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL));
247   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL));
248   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL));
249   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL));
250   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL));
251   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL));
252   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL));
253 
254   // Check mixes of vectors and scalar
255   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL));
256   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL));
257   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL));
258   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL));
259   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL));
260 
261   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL));
262   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL));
263   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL));
264   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL));
265   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL));
266   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL));
267   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL));
268   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL));
269   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL));
270 }
271 
272 TEST_F(VecUtilsTest, AreConsecutive_gep_i1) {
273   parseIR(R"IR(
274 define void @foo(ptr %ptr) {
275   %gep0 = getelementptr inbounds i1, ptr %ptr, i64 0
276   %gep1 = getelementptr inbounds i2, ptr %ptr, i64 4
277   %gep2 = getelementptr inbounds i3, ptr %ptr, i64 8
278   %gep3 = getelementptr inbounds i7, ptr %ptr, i64 12
279 
280   %ld0 = load float, ptr %gep0
281   %ld1 = load float, ptr %gep1
282   %ld2 = load float, ptr %gep2
283   %ld3 = load float, ptr %gep3
284 
285   %v2ld0 = load <2 x float>, ptr %gep0
286   %v2ld1 = load <2 x float>, ptr %gep1
287   %v2ld2 = load <2 x float>, ptr %gep2
288   %v2ld3 = load <2 x float>, ptr %gep3
289 
290   %v3ld0 = load <3 x float>, ptr %gep0
291   %v3ld1 = load <3 x float>, ptr %gep1
292   %v3ld2 = load <3 x float>, ptr %gep2
293   %v3ld3 = load <3 x float>, ptr %gep3
294   ret void
295 }
296 )IR");
297   Function &LLVMF = *M->getFunction("foo");
298   const DataLayout &DL = M->getDataLayout();
299   auto &SE = getSE(LLVMF);
300 
301   sandboxir::Context Ctx(C);
302   auto &F = *Ctx.createFunction(&LLVMF);
303   auto &BB = *F.begin();
304   auto It = std::next(BB.begin(), 4);
305   auto *L0 = cast<sandboxir::LoadInst>(&*It++);
306   auto *L1 = cast<sandboxir::LoadInst>(&*It++);
307   auto *L2 = cast<sandboxir::LoadInst>(&*It++);
308   auto *L3 = cast<sandboxir::LoadInst>(&*It++);
309 
310   auto *V2L0 = cast<sandboxir::LoadInst>(&*It++);
311   auto *V2L1 = cast<sandboxir::LoadInst>(&*It++);
312   auto *V2L2 = cast<sandboxir::LoadInst>(&*It++);
313   auto *V2L3 = cast<sandboxir::LoadInst>(&*It++);
314 
315   auto *V3L0 = cast<sandboxir::LoadInst>(&*It++);
316   auto *V3L1 = cast<sandboxir::LoadInst>(&*It++);
317   auto *V3L2 = cast<sandboxir::LoadInst>(&*It++);
318   auto *V3L3 = cast<sandboxir::LoadInst>(&*It++);
319 
320   // Scalar
321   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, L1, SE, DL));
322   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, L2, SE, DL));
323   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L2, L3, SE, DL));
324   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L0, SE, DL));
325   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L1, SE, DL));
326   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L2, SE, DL));
327   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L2, SE, DL));
328   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, L3, SE, DL));
329   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L1, L3, SE, DL));
330   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L2, L0, SE, DL));
331   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L3, L1, SE, DL));
332 
333   // Check 2-wide loads
334   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V2L2, SE, DL));
335   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L1, V2L3, SE, DL));
336   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V2L1, SE, DL));
337   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, V2L2, SE, DL));
338   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L2, V2L3, SE, DL));
339 
340   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
341   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
342   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
343   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L3, V2L1, SE, DL));
344 
345   // Check 3-wide loads
346   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, V3L3, SE, DL));
347   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V3L1, SE, DL));
348   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L2, SE, DL));
349   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L3, SE, DL));
350   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L1, V3L0, SE, DL));
351   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L2, V3L1, SE, DL));
352   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L3, V3L2, SE, DL));
353 
354   // Check mixes of vectors and scalar
355   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L0, V2L1, SE, DL));
356   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(L1, V2L2, SE, DL));
357   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, L2, SE, DL));
358   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V3L0, L3, SE, DL));
359   EXPECT_TRUE(sandboxir::VecUtils::areConsecutive(V2L0, V3L2, SE, DL));
360 
361   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L2, SE, DL));
362   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V3L2, SE, DL));
363   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(L0, V2L3, SE, DL));
364   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L0, V3L1, SE, DL));
365   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L1, SE, DL));
366   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, L2, SE, DL));
367   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L1, SE, DL));
368   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V3L0, V2L2, SE, DL));
369   EXPECT_FALSE(sandboxir::VecUtils::areConsecutive(V2L1, L0, SE, DL));
370 }
371 
372 TEST_F(VecUtilsTest, GetNumLanes) {
373   parseIR(R"IR(
374 define <4 x float> @foo(float %v, <2 x float> %v2, <4 x float> %ret, ptr %ptr) {
375   store float %v, ptr %ptr
376   store <2 x float> %v2, ptr %ptr
377   ret <4 x float> %ret
378 }
379 )IR");
380   Function &LLVMF = *M->getFunction("foo");
381 
382   sandboxir::Context Ctx(C);
383   auto &F = *Ctx.createFunction(&LLVMF);
384   auto &BB = *F.begin();
385 
386   auto It = BB.begin();
387   auto *S0 = cast<sandboxir::StoreInst>(&*It++);
388   auto *S1 = cast<sandboxir::StoreInst>(&*It++);
389   auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
390   EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S0->getValueOperand()->getType()),
391             1u);
392   EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S0), 1);
393   EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S1->getValueOperand()->getType()),
394             2u);
395   EXPECT_EQ(sandboxir::VecUtils::getNumLanes(S1), 2);
396   EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Ret->getReturnValue()->getType()),
397             4u);
398   EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Ret), 4);
399 
400   SmallVector<sandboxir::Value *> Bndl({S0, S1, Ret});
401   EXPECT_EQ(sandboxir::VecUtils::getNumLanes(Bndl), 7u);
402 }
403 
404 TEST_F(VecUtilsTest, GetWideType) {
405   sandboxir::Context Ctx(C);
406 
407   auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);
408   auto *Int32X4Ty = sandboxir::FixedVectorType::get(Int32Ty, 4);
409   EXPECT_EQ(sandboxir::VecUtils::getWideType(Int32Ty, 4), Int32X4Ty);
410   auto *Int32X8Ty = sandboxir::FixedVectorType::get(Int32Ty, 8);
411   EXPECT_EQ(sandboxir::VecUtils::getWideType(Int32X4Ty, 2), Int32X8Ty);
412 }
413