xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp (revision 9faff9a09178eee3b79b669859df72d75de412c3)
1 //===- llvm/unittest/CodeGen/GlobalISel/LegalizerInfoTest.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/CodeGen/GlobalISel/LegalizerInfo.h"
10 #include "llvm/CodeGen/TargetOpcodes.h"
11 #include "GISelMITest.h"
12 #include "gtest/gtest.h"
13 
14 using namespace llvm;
15 using namespace LegalizeActions;
16 using namespace LegalityPredicates;
17 using namespace LegalizeMutations;
18 
19 // Define a couple of pretty printers to help debugging when things go wrong.
20 namespace llvm {
21 std::ostream &
operator <<(std::ostream & OS,const LegalizeAction Act)22 operator<<(std::ostream &OS, const LegalizeAction Act) {
23   switch (Act) {
24   case Lower: OS << "Lower"; break;
25   case Legal: OS << "Legal"; break;
26   case NarrowScalar: OS << "NarrowScalar"; break;
27   case WidenScalar:  OS << "WidenScalar"; break;
28   case FewerElements:  OS << "FewerElements"; break;
29   case MoreElements:  OS << "MoreElements"; break;
30   case Libcall: OS << "Libcall"; break;
31   case Custom: OS << "Custom"; break;
32   case Bitcast: OS << "Bitcast"; break;
33   case Unsupported: OS << "Unsupported"; break;
34   case NotFound: OS << "NotFound"; break;
35   case UseLegacyRules: OS << "UseLegacyRules"; break;
36   }
37   return OS;
38 }
39 
operator <<(std::ostream & OS,const llvm::LegalizeActionStep Ty)40 std::ostream &operator<<(std::ostream &OS, const llvm::LegalizeActionStep Ty) {
41   OS << "LegalizeActionStep(" << Ty.Action << ", " << Ty.TypeIdx << ", "
42      << Ty.NewType << ')';
43   return OS;
44 }
45 }
46 
47 namespace {
48 
49 
TEST(LegalizerInfoTest,ScalarRISC)50 TEST(LegalizerInfoTest, ScalarRISC) {
51   using namespace TargetOpcode;
52   LegalizerInfo L;
53   auto &LegacyInfo = L.getLegacyLegalizerInfo();
54   // Typical RISCy set of operations based on AArch64.
55   for (unsigned Op : {G_ADD, G_SUB}) {
56     for (unsigned Size : {32, 64})
57       LegacyInfo.setAction({Op, 0, LLT::scalar(Size)},
58                            LegacyLegalizeActions::Legal);
59     LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
60         Op, 0, LegacyLegalizerInfo::widenToLargerTypesAndNarrowToLargest);
61   }
62 
63   LegacyInfo.computeTables();
64 
65   for (unsigned opcode : {G_ADD, G_SUB}) {
66     // Check we infer the correct types and actually do what we're told.
67     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(8)}}),
68               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
69     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(16)}}),
70               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
71     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(32)}}),
72               LegalizeActionStep(Legal, 0, LLT{}));
73     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(64)}}),
74               LegalizeActionStep(Legal, 0, LLT{}));
75 
76     // Make sure the default for over-sized types applies.
77     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(128)}}),
78               LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64)));
79     // Make sure we also handle unusual sizes
80     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(1)}}),
81               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
82     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(31)}}),
83               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
84     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(33)}}),
85               LegalizeActionStep(WidenScalar, 0, LLT::scalar(64)));
86     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(63)}}),
87               LegalizeActionStep(WidenScalar, 0, LLT::scalar(64)));
88     EXPECT_EQ(L.getAction({opcode, {LLT::scalar(65)}}),
89               LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64)));
90   }
91 }
92 
TEST(LegalizerInfoTest,VectorRISC)93 TEST(LegalizerInfoTest, VectorRISC) {
94   using namespace TargetOpcode;
95   LegalizerInfo L;
96   auto &LegacyInfo = L.getLegacyLegalizerInfo();
97   // Typical RISCy set of operations based on ARM.
98   LegacyInfo.setAction({G_ADD, LLT::fixed_vector(8, 8)},
99                        LegacyLegalizeActions::Legal);
100   LegacyInfo.setAction({G_ADD, LLT::fixed_vector(16, 8)},
101                        LegacyLegalizeActions::Legal);
102   LegacyInfo.setAction({G_ADD, LLT::fixed_vector(4, 16)},
103                        LegacyLegalizeActions::Legal);
104   LegacyInfo.setAction({G_ADD, LLT::fixed_vector(8, 16)},
105                        LegacyLegalizeActions::Legal);
106   LegacyInfo.setAction({G_ADD, LLT::fixed_vector(2, 32)},
107                        LegacyLegalizeActions::Legal);
108   LegacyInfo.setAction({G_ADD, LLT::fixed_vector(4, 32)},
109                        LegacyLegalizeActions::Legal);
110 
111   LegacyInfo.setLegalizeVectorElementToDifferentSizeStrategy(
112       G_ADD, 0, LegacyLegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
113 
114   LegacyInfo.setAction({G_ADD, 0, LLT::scalar(32)},
115                        LegacyLegalizeActions::Legal);
116 
117   LegacyInfo.computeTables();
118 
119   // Check we infer the correct types and actually do what we're told for some
120   // simple cases.
121   EXPECT_EQ(L.getAction({G_ADD, {LLT::fixed_vector(8, 8)}}),
122             LegalizeActionStep(Legal, 0, LLT{}));
123   EXPECT_EQ(L.getAction({G_ADD, {LLT::fixed_vector(8, 7)}}),
124             LegalizeActionStep(WidenScalar, 0, LLT::fixed_vector(8, 8)));
125   EXPECT_EQ(L.getAction({G_ADD, {LLT::fixed_vector(2, 8)}}),
126             LegalizeActionStep(MoreElements, 0, LLT::fixed_vector(8, 8)));
127   EXPECT_EQ(L.getAction({G_ADD, {LLT::fixed_vector(8, 32)}}),
128             LegalizeActionStep(FewerElements, 0, LLT::fixed_vector(4, 32)));
129   // Check a few non-power-of-2 sizes:
130   EXPECT_EQ(L.getAction({G_ADD, {LLT::fixed_vector(3, 3)}}),
131             LegalizeActionStep(WidenScalar, 0, LLT::fixed_vector(3, 8)));
132   EXPECT_EQ(L.getAction({G_ADD, {LLT::fixed_vector(3, 8)}}),
133             LegalizeActionStep(MoreElements, 0, LLT::fixed_vector(8, 8)));
134 }
135 
TEST(LegalizerInfoTest,MultipleTypes)136 TEST(LegalizerInfoTest, MultipleTypes) {
137   using namespace TargetOpcode;
138   LegalizerInfo L;
139   auto &LegacyInfo = L.getLegacyLegalizerInfo();
140   LLT p0 = LLT::pointer(0, 64);
141   LLT s64 = LLT::scalar(64);
142 
143   // Typical RISCy set of operations based on AArch64.
144   LegacyInfo.setAction({G_PTRTOINT, 0, s64}, LegacyLegalizeActions::Legal);
145   LegacyInfo.setAction({G_PTRTOINT, 1, p0}, LegacyLegalizeActions::Legal);
146 
147   LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
148       G_PTRTOINT, 0, LegacyLegalizerInfo::widenToLargerTypesAndNarrowToLargest);
149 
150   LegacyInfo.computeTables();
151 
152   // Check we infer the correct types and actually do what we're told.
153   EXPECT_EQ(L.getAction({G_PTRTOINT, {s64, p0}}),
154             LegalizeActionStep(Legal, 0, LLT{}));
155 
156   // Make sure we also handle unusual sizes
157   EXPECT_EQ(
158       L.getAction({G_PTRTOINT, {LLT::scalar(65), s64}}),
159       LegalizeActionStep(NarrowScalar, 0, s64));
160   EXPECT_EQ(
161       L.getAction({G_PTRTOINT, {s64, LLT::pointer(0, 32)}}),
162       LegalizeActionStep(Unsupported, 1, LLT::pointer(0, 32)));
163 }
164 
TEST(LegalizerInfoTest,MultipleSteps)165 TEST(LegalizerInfoTest, MultipleSteps) {
166   using namespace TargetOpcode;
167   LegalizerInfo L;
168   auto &LegacyInfo = L.getLegacyLegalizerInfo();
169   LLT s32 = LLT::scalar(32);
170   LLT s64 = LLT::scalar(64);
171 
172   LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
173       G_UREM, 0, LegacyLegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
174   LegacyInfo.setAction({G_UREM, 0, s32}, LegacyLegalizeActions::Lower);
175   LegacyInfo.setAction({G_UREM, 0, s64}, LegacyLegalizeActions::Lower);
176 
177   LegacyInfo.computeTables();
178 
179   EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(16)}}),
180             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
181   EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(32)}}),
182             LegalizeActionStep(Lower, 0, LLT::scalar(32)));
183 }
184 
TEST(LegalizerInfoTest,SizeChangeStrategy)185 TEST(LegalizerInfoTest, SizeChangeStrategy) {
186   using namespace TargetOpcode;
187   LegalizerInfo L;
188   auto &LegacyInfo = L.getLegacyLegalizerInfo();
189   for (unsigned Size : {1, 8, 16, 32})
190     LegacyInfo.setAction({G_UREM, 0, LLT::scalar(Size)},
191                          LegacyLegalizeActions::Legal);
192 
193   LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
194       G_UREM, 0, LegacyLegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
195   LegacyInfo.computeTables();
196 
197   // Check we infer the correct types and actually do what we're told.
198   for (unsigned Size : {1, 8, 16, 32}) {
199     EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(Size)}}),
200               LegalizeActionStep(Legal, 0, LLT{}));
201   }
202   EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(2)}}),
203             LegalizeActionStep(WidenScalar, 0, LLT::scalar(8)));
204   EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(7)}}),
205             LegalizeActionStep(WidenScalar, 0, LLT::scalar(8)));
206   EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(9)}}),
207             LegalizeActionStep(WidenScalar, 0, LLT::scalar(16)));
208   EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(17)}}),
209             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
210   EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(31)}}),
211             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
212   EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(33)}}),
213             LegalizeActionStep(Unsupported, 0, LLT::scalar(33)));
214 }
215 }
216 
217 #define EXPECT_ACTION(Action, Index, Type, Query)                              \
218   do {                                                                         \
219     auto A = LI.getAction(Query);                                              \
220     EXPECT_EQ(LegalizeActionStep(Action, Index, Type), A) << A;                \
221   } while (0)
222 
TEST(LegalizerInfoTest,RuleSets)223 TEST(LegalizerInfoTest, RuleSets) {
224   using namespace TargetOpcode;
225 
226   const LLT s5 = LLT::scalar(5);
227   const LLT s8 = LLT::scalar(8);
228   const LLT s16 = LLT::scalar(16);
229   const LLT s32 = LLT::scalar(32);
230   const LLT s33 = LLT::scalar(33);
231   const LLT s64 = LLT::scalar(64);
232 
233   const LLT v2s5 = LLT::fixed_vector(2, 5);
234   const LLT v2s8 = LLT::fixed_vector(2, 8);
235   const LLT v2s16 = LLT::fixed_vector(2, 16);
236   const LLT v2s32 = LLT::fixed_vector(2, 32);
237   const LLT v3s32 = LLT::fixed_vector(3, 32);
238   const LLT v4s32 = LLT::fixed_vector(4, 32);
239   const LLT v8s32 = LLT::fixed_vector(8, 32);
240   const LLT v2s33 = LLT::fixed_vector(2, 33);
241   const LLT v2s64 = LLT::fixed_vector(2, 64);
242 
243   const LLT p0 = LLT::pointer(0, 32);
244   const LLT v2p0 = LLT::fixed_vector(2, p0);
245   const LLT v3p0 = LLT::fixed_vector(3, p0);
246   const LLT v4p0 = LLT::fixed_vector(4, p0);
247 
248   const LLT s1 = LLT::scalar(1);
249   const LLT v2s1 = LLT::fixed_vector(2, 1);
250   const LLT v4s1 = LLT::fixed_vector(4, 1);
251 
252   {
253     LegalizerInfo LI;
254     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
255 
256     LI.getActionDefinitionsBuilder(G_IMPLICIT_DEF)
257       .legalFor({v4s32, v4p0})
258       .moreElementsToNextPow2(0);
259     LegacyInfo.computeTables();
260 
261     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_IMPLICIT_DEF, {s32}));
262     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_IMPLICIT_DEF, {v2s32}));
263     EXPECT_ACTION(MoreElements, 0, v4p0, LegalityQuery(G_IMPLICIT_DEF, {v3p0}));
264     EXPECT_ACTION(MoreElements, 0, v4s32, LegalityQuery(G_IMPLICIT_DEF, {v3s32}));
265   }
266 
267   // Test minScalarOrElt
268   {
269     LegalizerInfo LI;
270     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
271     LI.getActionDefinitionsBuilder(G_OR)
272       .legalFor({s32})
273       .minScalarOrElt(0, s32);
274     LegacyInfo.computeTables();
275 
276     EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_OR, {s16}));
277     EXPECT_ACTION(WidenScalar, 0, v2s32, LegalityQuery(G_OR, {v2s16}));
278   }
279 
280   // Test maxScalarOrELt
281   {
282     LegalizerInfo LI;
283     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
284     LI.getActionDefinitionsBuilder(G_AND)
285       .legalFor({s16})
286       .maxScalarOrElt(0, s16);
287     LegacyInfo.computeTables();
288 
289     EXPECT_ACTION(NarrowScalar, 0, s16, LegalityQuery(G_AND, {s32}));
290     EXPECT_ACTION(NarrowScalar, 0, v2s16, LegalityQuery(G_AND, {v2s32}));
291   }
292 
293   // Test clampScalarOrElt
294   {
295     LegalizerInfo LI;
296     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
297     LI.getActionDefinitionsBuilder(G_XOR)
298       .legalFor({s16})
299       .clampScalarOrElt(0, s16, s32);
300     LegacyInfo.computeTables();
301 
302     EXPECT_ACTION(NarrowScalar, 0, s32, LegalityQuery(G_XOR, {s64}));
303     EXPECT_ACTION(WidenScalar, 0, s16, LegalityQuery(G_XOR, {s8}));
304 
305     // Make sure the number of elements is preserved.
306     EXPECT_ACTION(NarrowScalar, 0, v2s32, LegalityQuery(G_XOR, {v2s64}));
307     EXPECT_ACTION(WidenScalar, 0, v2s16, LegalityQuery(G_XOR, {v2s8}));
308   }
309 
310   // Test minScalar
311   {
312     LegalizerInfo LI;
313     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
314     LI.getActionDefinitionsBuilder(G_OR)
315       .legalFor({s32})
316       .minScalar(0, s32);
317     LegacyInfo.computeTables();
318 
319     // Only handle scalars, ignore vectors.
320     EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_OR, {s16}));
321     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_OR, {v2s16}));
322   }
323 
324   // Test minScalarIf
325   {
326     bool IfCond = true;
327     LegalizerInfo LI;
328     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
329     LI.getActionDefinitionsBuilder(G_OR)
330       .legalFor({s32})
331       .minScalarIf([&](const LegalityQuery &Query) {
332                      return IfCond;
333                    }, 0, s32);
334     LegacyInfo.computeTables();
335 
336     // Only handle scalars, ignore vectors.
337     EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_OR, {s16}));
338     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_OR, {v2s16}));
339 
340     IfCond = false;
341     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_OR, {s16}));
342     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_OR, {v2s16}));
343   }
344 
345   // Test maxScalar
346   {
347     LegalizerInfo LI;
348     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
349     LI.getActionDefinitionsBuilder(G_AND)
350       .legalFor({s16})
351       .maxScalar(0, s16);
352     LegacyInfo.computeTables();
353 
354     // Only handle scalars, ignore vectors.
355     EXPECT_ACTION(NarrowScalar, 0, s16, LegalityQuery(G_AND, {s32}));
356     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_AND, {v2s32}));
357   }
358 
359   // Test clampScalar
360   {
361     LegalizerInfo LI;
362     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
363 
364     LI.getActionDefinitionsBuilder(G_XOR)
365       .legalFor({s16})
366       .clampScalar(0, s16, s32);
367     LegacyInfo.computeTables();
368 
369     EXPECT_ACTION(NarrowScalar, 0, s32, LegalityQuery(G_XOR, {s64}));
370     EXPECT_ACTION(WidenScalar, 0, s16, LegalityQuery(G_XOR, {s8}));
371 
372     // Only handle scalars, ignore vectors.
373     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_XOR, {v2s64}));
374     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_XOR, {v2s8}));
375   }
376 
377   // Test widenScalarOrEltToNextPow2
378   {
379     LegalizerInfo LI;
380     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
381 
382     LI.getActionDefinitionsBuilder(G_AND)
383       .legalFor({s32})
384       .widenScalarOrEltToNextPow2(0, 32);
385     LegacyInfo.computeTables();
386 
387     // Handle scalars and vectors
388     EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_AND, {s5}));
389     EXPECT_ACTION(WidenScalar, 0, v2s32, LegalityQuery(G_AND, {v2s5}));
390     EXPECT_ACTION(WidenScalar, 0, s64, LegalityQuery(G_AND, {s33}));
391     EXPECT_ACTION(WidenScalar, 0, v2s64, LegalityQuery(G_AND, {v2s33}));
392   }
393 
394   // Test widenScalarToNextPow2
395   {
396     LegalizerInfo LI;
397     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
398 
399     LI.getActionDefinitionsBuilder(G_AND)
400       .legalFor({s32})
401       .widenScalarToNextPow2(0, 32);
402     LegacyInfo.computeTables();
403 
404     EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_AND, {s5}));
405     EXPECT_ACTION(WidenScalar, 0, s64, LegalityQuery(G_AND, {s33}));
406 
407     // Do nothing for vectors.
408     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_AND, {v2s5}));
409     EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_AND, {v2s33}));
410   }
411 
412   // Test changeElementCountTo
413   {
414     LegalizerInfo LI;
415     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
416 
417     // Type index form
418     LI.getActionDefinitionsBuilder(G_SELECT)
419       .moreElementsIf(isScalar(1), changeElementCountTo(1, 0));
420 
421     // Raw type form
422     LI.getActionDefinitionsBuilder(G_ADD)
423       .fewerElementsIf(typeIs(0, v4s32), changeElementCountTo(0, v2s32))
424       .fewerElementsIf(typeIs(0, v8s32), changeElementCountTo(0, s32))
425       .fewerElementsIf(typeIs(0, LLT::scalable_vector(4, 16)),
426                        changeElementCountTo(0, LLT::scalable_vector(2, 16)))
427       .fewerElementsIf(typeIs(0, LLT::scalable_vector(8, 16)),
428                        changeElementCountTo(0, s16));
429 
430     LegacyInfo.computeTables();
431 
432     EXPECT_ACTION(MoreElements, 1, v4s1, LegalityQuery(G_SELECT, {v4s32, s1}));
433     EXPECT_ACTION(MoreElements, 1, v2s1, LegalityQuery(G_SELECT, {v2s32, s1}));
434     EXPECT_ACTION(MoreElements, 1, v2s1, LegalityQuery(G_SELECT, {v2s32, s1}));
435     EXPECT_ACTION(MoreElements, 1, v4s1, LegalityQuery(G_SELECT, {v4p0, s1}));
436 
437     EXPECT_ACTION(MoreElements, 1, LLT::scalable_vector(2, 1),
438                   LegalityQuery(G_SELECT, {LLT::scalable_vector(2, 32), s1}));
439     EXPECT_ACTION(MoreElements, 1, LLT::scalable_vector(4, 1),
440                   LegalityQuery(G_SELECT, {LLT::scalable_vector(4, 32), s1}));
441     EXPECT_ACTION(MoreElements, 1, LLT::scalable_vector(2, s1),
442                   LegalityQuery(G_SELECT, {LLT::scalable_vector(2, p0), s1}));
443 
444     EXPECT_ACTION(FewerElements, 0, v2s32, LegalityQuery(G_ADD, {v4s32}));
445     EXPECT_ACTION(FewerElements, 0, s32, LegalityQuery(G_ADD, {v8s32}));
446 
447     EXPECT_ACTION(FewerElements, 0, LLT::scalable_vector(2, 16),
448                   LegalityQuery(G_ADD, {LLT::scalable_vector(4, 16)}));
449     EXPECT_ACTION(FewerElements, 0, s16,
450                   LegalityQuery(G_ADD, {LLT::scalable_vector(8, 16)}));
451   }
452 
453   // Test minScalarEltSameAsIf
454   {
455     LegalizerInfo LI;
456     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
457 
458     LI.getActionDefinitionsBuilder(G_SELECT).minScalarEltSameAsIf(
459         all(isVector(0), isVector(1)), 1, 0);
460     LegacyInfo.computeTables();
461     LLT p1 = LLT::pointer(1, 32);
462     LLT v2p1 = LLT::fixed_vector(2, p1);
463 
464     EXPECT_ACTION(WidenScalar, 1, v2s32, LegalityQuery(G_SELECT, {v2p0, v2s1}));
465     EXPECT_ACTION(WidenScalar, 1, v2s32, LegalityQuery(G_SELECT, {v2p1, v2s1}));
466   }
467 }
468 
TEST(LegalizerInfoTest,MMOAlignment)469 TEST(LegalizerInfoTest, MMOAlignment) {
470   using namespace TargetOpcode;
471 
472   const LLT s32 = LLT::scalar(32);
473   const LLT p0 = LLT::pointer(0, 64);
474 
475   {
476     LegalizerInfo LI;
477     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
478     LI.getActionDefinitionsBuilder(G_LOAD)
479       .legalForTypesWithMemDesc({{s32, p0, s32, 32}});
480 
481     LegacyInfo.computeTables();
482 
483     EXPECT_ACTION(Legal, 0, LLT(),
484                   LegalityQuery(G_LOAD, {s32, p0},
485                                 LegalityQuery::MemDesc{
486                                   s32, 32, AtomicOrdering::NotAtomic}));
487     EXPECT_ACTION(Unsupported, 0, LLT(),
488                   LegalityQuery(G_LOAD, {s32, p0},
489                                 LegalityQuery::MemDesc{
490                                   s32, 16, AtomicOrdering::NotAtomic }));
491     EXPECT_ACTION(Unsupported, 0, LLT(),
492                   LegalityQuery(G_LOAD, {s32, p0},
493                                 LegalityQuery::MemDesc{
494                                   s32, 8, AtomicOrdering::NotAtomic}));
495   }
496 
497   // Test that the maximum supported alignment value isn't truncated
498   {
499     // Maximum IR defined alignment in bytes.
500     const uint64_t MaxAlignment = UINT64_C(1) << 29;
501     const uint64_t MaxAlignInBits = 8 * MaxAlignment;
502     LegalizerInfo LI;
503     auto &LegacyInfo = LI.getLegacyLegalizerInfo();
504     LI.getActionDefinitionsBuilder(G_LOAD)
505       .legalForTypesWithMemDesc({{s32, p0, s32, MaxAlignInBits}});
506 
507     LegacyInfo.computeTables();
508 
509     EXPECT_ACTION(Legal, 0, LLT(),
510                   LegalityQuery(G_LOAD, {s32, p0},
511                                 LegalityQuery::MemDesc{s32,
512                                     MaxAlignInBits, AtomicOrdering::NotAtomic}));
513     EXPECT_ACTION(Unsupported, 0, LLT(),
514                   LegalityQuery(G_LOAD, {s32, p0},
515                                 LegalityQuery::MemDesc{
516                                   s32, 8, AtomicOrdering::NotAtomic }));
517   }
518 }
519 
520 // This code sequence doesn't do anything, but it covers a previously uncovered
521 // codepath that used to crash in MSVC x86_32 debug mode.
TEST(LegalizerInfoTest,MSVCDebugMiscompile)522 TEST(LegalizerInfoTest, MSVCDebugMiscompile) {
523   const LLT S1 = LLT::scalar(1);
524   const LLT P0 = LLT::pointer(0, 32);
525   LegalizerInfo LI;
526   auto Builder = LI.getActionDefinitionsBuilder(TargetOpcode::G_PTRTOINT);
527   (void)Builder.legalForCartesianProduct({S1}, {P0});
528 }
529