1 //===- llvm/unittest/CodeGen/GlobalISel/LegalizerInfoTest.cpp -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
11 #include "llvm/CodeGen/TargetOpcodes.h"
12 #include "gtest/gtest.h"
13 
14 using namespace llvm;
15 using namespace LegalizeActions;
16 
17 // Define a couple of pretty printers to help debugging when things go wrong.
18 namespace llvm {
19 std::ostream &
operator <<(std::ostream & OS,const LegalizeAction Act)20 operator<<(std::ostream &OS, const LegalizeAction Act) {
21   switch (Act) {
22   case Lower: OS << "Lower"; break;
23   case Legal: OS << "Legal"; break;
24   case NarrowScalar: OS << "NarrowScalar"; break;
25   case WidenScalar:  OS << "WidenScalar"; break;
26   case FewerElements:  OS << "FewerElements"; break;
27   case MoreElements:  OS << "MoreElements"; break;
28   case Libcall: OS << "Libcall"; break;
29   case Custom: OS << "Custom"; break;
30   case Unsupported: OS << "Unsupported"; break;
31   case NotFound: OS << "NotFound"; break;
32   case UseLegacyRules: OS << "UseLegacyRules"; break;
33   }
34   return OS;
35 }
36 
37 std::ostream &
operator <<(std::ostream & OS,const llvm::LLT Ty)38 operator<<(std::ostream &OS, const llvm::LLT Ty) {
39   std::string Repr;
40   raw_string_ostream SS{Repr};
41   Ty.print(SS);
42   OS << SS.str();
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   // Typical RISCy set of operations based on AArch64.
54   for (unsigned Op : {G_ADD, G_SUB}) {
55     for (unsigned Size : {32, 64})
56       L.setAction({Op, 0, LLT::scalar(Size)}, Legal);
57     L.setLegalizeScalarToDifferentSizeStrategy(
58         Op, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest);
59   }
60 
61   L.computeTables();
62 
63   for (unsigned opcode : {G_ADD, G_SUB}) {
64     // Check we infer the correct types and actually do what we're told.
65     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(8)}}),
66               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
67     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(16)}}),
68               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
69     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(32)}}),
70               LegalizeActionStep(Legal, 0, LLT{}));
71     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(64)}}),
72               LegalizeActionStep(Legal, 0, LLT{}));
73 
74     // Make sure the default for over-sized types applies.
75     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(128)}}),
76               LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64)));
77     // Make sure we also handle unusual sizes
78     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(1)}}),
79               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
80     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(31)}}),
81               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
82     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(33)}}),
83               LegalizeActionStep(WidenScalar, 0, LLT::scalar(64)));
84     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(63)}}),
85               LegalizeActionStep(WidenScalar, 0, LLT::scalar(64)));
86     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(65)}}),
87               LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64)));
88   }
89 }
90 
TEST(LegalizerInfoTest,VectorRISC)91 TEST(LegalizerInfoTest, VectorRISC) {
92   using namespace TargetOpcode;
93   LegalizerInfo L;
94   // Typical RISCy set of operations based on ARM.
95   L.setAction({G_ADD, LLT::vector(8, 8)}, Legal);
96   L.setAction({G_ADD, LLT::vector(16, 8)}, Legal);
97   L.setAction({G_ADD, LLT::vector(4, 16)}, Legal);
98   L.setAction({G_ADD, LLT::vector(8, 16)}, Legal);
99   L.setAction({G_ADD, LLT::vector(2, 32)}, Legal);
100   L.setAction({G_ADD, LLT::vector(4, 32)}, Legal);
101 
102   L.setLegalizeVectorElementToDifferentSizeStrategy(
103       G_ADD, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
104 
105   L.setAction({G_ADD, 0, LLT::scalar(32)}, Legal);
106 
107   L.computeTables();
108 
109   // Check we infer the correct types and actually do what we're told for some
110   // simple cases.
111   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 8)}}),
112             LegalizeActionStep(Legal, 0, LLT{}));
113   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 7)}}),
114             LegalizeActionStep(WidenScalar, 0, LLT::vector(8, 8)));
115   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(2, 8)}}),
116             LegalizeActionStep(MoreElements, 0, LLT::vector(8, 8)));
117   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 32)}}),
118             LegalizeActionStep(FewerElements, 0, LLT::vector(4, 32)));
119   // Check a few non-power-of-2 sizes:
120   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(3, 3)}}),
121             LegalizeActionStep(WidenScalar, 0, LLT::vector(3, 8)));
122   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(3, 8)}}),
123             LegalizeActionStep(MoreElements, 0, LLT::vector(8, 8)));
124 }
125 
TEST(LegalizerInfoTest,MultipleTypes)126 TEST(LegalizerInfoTest, MultipleTypes) {
127   using namespace TargetOpcode;
128   LegalizerInfo L;
129   LLT p0 = LLT::pointer(0, 64);
130   LLT s64 = LLT::scalar(64);
131 
132   // Typical RISCy set of operations based on AArch64.
133   L.setAction({G_PTRTOINT, 0, s64}, Legal);
134   L.setAction({G_PTRTOINT, 1, p0}, Legal);
135 
136   L.setLegalizeScalarToDifferentSizeStrategy(
137       G_PTRTOINT, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest);
138 
139   L.computeTables();
140 
141   // Check we infer the correct types and actually do what we're told.
142   ASSERT_EQ(L.getAction({G_PTRTOINT, {s64, p0}}),
143             LegalizeActionStep(Legal, 0, LLT{}));
144 
145   // Make sure we also handle unusual sizes
146   ASSERT_EQ(
147       L.getAction({G_PTRTOINT, {LLT::scalar(65), s64}}),
148       LegalizeActionStep(NarrowScalar, 0, s64));
149   ASSERT_EQ(
150       L.getAction({G_PTRTOINT, {s64, LLT::pointer(0, 32)}}),
151       LegalizeActionStep(Unsupported, 1, LLT::pointer(0, 32)));
152 }
153 
TEST(LegalizerInfoTest,MultipleSteps)154 TEST(LegalizerInfoTest, MultipleSteps) {
155   using namespace TargetOpcode;
156   LegalizerInfo L;
157   LLT s32 = LLT::scalar(32);
158   LLT s64 = LLT::scalar(64);
159 
160   L.setLegalizeScalarToDifferentSizeStrategy(
161       G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
162   L.setAction({G_UREM, 0, s32}, Lower);
163   L.setAction({G_UREM, 0, s64}, Lower);
164 
165   L.computeTables();
166 
167   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(16)}}),
168             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
169   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(32)}}),
170             LegalizeActionStep(Lower, 0, LLT::scalar(32)));
171 }
172 
TEST(LegalizerInfoTest,SizeChangeStrategy)173 TEST(LegalizerInfoTest, SizeChangeStrategy) {
174   using namespace TargetOpcode;
175   LegalizerInfo L;
176   for (unsigned Size : {1, 8, 16, 32})
177     L.setAction({G_UREM, 0, LLT::scalar(Size)}, Legal);
178 
179   L.setLegalizeScalarToDifferentSizeStrategy(
180       G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
181   L.computeTables();
182 
183   // Check we infer the correct types and actually do what we're told.
184   for (unsigned Size : {1, 8, 16, 32}) {
185     ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(Size)}}),
186               LegalizeActionStep(Legal, 0, LLT{}));
187   }
188   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(2)}}),
189             LegalizeActionStep(WidenScalar, 0, LLT::scalar(8)));
190   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(7)}}),
191             LegalizeActionStep(WidenScalar, 0, LLT::scalar(8)));
192   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(9)}}),
193             LegalizeActionStep(WidenScalar, 0, LLT::scalar(16)));
194   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(17)}}),
195             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
196   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(31)}}),
197             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
198   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(33)}}),
199             LegalizeActionStep(Unsupported, 0, LLT::scalar(33)));
200 }
201 }
202