xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp (revision 9ade5592d96a68bbe1b9a16099b0575c32db7905)
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 &
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";
32   }
33   return OS;
34 }
35 
36 std::ostream &
37 operator<<(std::ostream &OS, const llvm::LLT Ty) {
38   std::string Repr;
39   raw_string_ostream SS{Repr};
40   Ty.print(SS);
41   OS << SS.str();
42   return OS;
43 }
44 }
45 
46 namespace {
47 
48 
49 TEST(LegalizerInfoTest, ScalarRISC) {
50   using namespace TargetOpcode;
51   LegalizerInfo L;
52   // Typical RISCy set of operations based on AArch64.
53   for (unsigned Op : {G_ADD, G_SUB}) {
54     for (unsigned Size : {32, 64})
55       L.setAction({Op, 0, LLT::scalar(Size)}, Legal);
56     L.setLegalizeScalarToDifferentSizeStrategy(
57         Op, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest);
58   }
59 
60   L.computeTables();
61 
62   for (unsigned opcode : {G_ADD, G_SUB}) {
63     // Check we infer the correct types and actually do what we're told.
64     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(8)}}),
65               LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
66     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(16)}}),
67               LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
68     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(32)}}),
69               LegalizerInfo::LegalizeActionStep(Legal, 0, LLT{}));
70     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(64)}}),
71               LegalizerInfo::LegalizeActionStep(Legal, 0, LLT{}));
72 
73     // Make sure the default for over-sized types applies.
74     ASSERT_EQ(
75         L.getAction({opcode, {LLT::scalar(128)}}),
76         LegalizerInfo::LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64)));
77     // Make sure we also handle unusual sizes
78     ASSERT_EQ(
79         L.getAction({opcode, {LLT::scalar(1)}}),
80         LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
81     ASSERT_EQ(
82         L.getAction({opcode, {LLT::scalar(31)}}),
83         LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
84     ASSERT_EQ(
85         L.getAction({opcode, {LLT::scalar(33)}}),
86         LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(64)));
87     ASSERT_EQ(
88         L.getAction({opcode, {LLT::scalar(63)}}),
89         LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(64)));
90     ASSERT_EQ(
91         L.getAction({opcode, {LLT::scalar(65)}}),
92         LegalizerInfo::LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64)));
93   }
94 }
95 
96 TEST(LegalizerInfoTest, VectorRISC) {
97   using namespace TargetOpcode;
98   LegalizerInfo L;
99   // Typical RISCy set of operations based on ARM.
100   L.setAction({G_ADD, LLT::vector(8, 8)}, Legal);
101   L.setAction({G_ADD, LLT::vector(16, 8)}, Legal);
102   L.setAction({G_ADD, LLT::vector(4, 16)}, Legal);
103   L.setAction({G_ADD, LLT::vector(8, 16)}, Legal);
104   L.setAction({G_ADD, LLT::vector(2, 32)}, Legal);
105   L.setAction({G_ADD, LLT::vector(4, 32)}, Legal);
106 
107   L.setLegalizeVectorElementToDifferentSizeStrategy(
108       G_ADD, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
109 
110   L.setAction({G_ADD, 0, LLT::scalar(32)}, Legal);
111 
112   L.computeTables();
113 
114   // Check we infer the correct types and actually do what we're told for some
115   // simple cases.
116   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 8)}}),
117             LegalizerInfo::LegalizeActionStep(Legal, 0, LLT{}));
118   ASSERT_EQ(
119       L.getAction({G_ADD, {LLT::vector(8, 7)}}),
120       LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::vector(8, 8)));
121   ASSERT_EQ(
122       L.getAction({G_ADD, {LLT::vector(2, 8)}}),
123       LegalizerInfo::LegalizeActionStep(MoreElements, 0, LLT::vector(8, 8)));
124   ASSERT_EQ(
125       L.getAction({G_ADD, {LLT::vector(8, 32)}}),
126       LegalizerInfo::LegalizeActionStep(FewerElements, 0, LLT::vector(4, 32)));
127   // Check a few non-power-of-2 sizes:
128   ASSERT_EQ(
129       L.getAction({G_ADD, {LLT::vector(3, 3)}}),
130       LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::vector(3, 8)));
131   ASSERT_EQ(
132       L.getAction({G_ADD, {LLT::vector(3, 8)}}),
133       LegalizerInfo::LegalizeActionStep(MoreElements, 0, LLT::vector(8, 8)));
134 }
135 
136 TEST(LegalizerInfoTest, MultipleTypes) {
137   using namespace TargetOpcode;
138   LegalizerInfo L;
139   LLT p0 = LLT::pointer(0, 64);
140   LLT s64 = LLT::scalar(64);
141 
142   // Typical RISCy set of operations based on AArch64.
143   L.setAction({G_PTRTOINT, 0, s64}, Legal);
144   L.setAction({G_PTRTOINT, 1, p0}, Legal);
145 
146   L.setLegalizeScalarToDifferentSizeStrategy(
147       G_PTRTOINT, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest);
148 
149   L.computeTables();
150 
151   // Check we infer the correct types and actually do what we're told.
152   ASSERT_EQ(L.getAction({G_PTRTOINT, {s64, p0}}),
153             LegalizerInfo::LegalizeActionStep(Legal, 0, LLT{}));
154 
155   // Make sure we also handle unusual sizes
156   ASSERT_EQ(
157       L.getAction({G_PTRTOINT, {LLT::scalar(65), s64}}),
158       LegalizerInfo::LegalizeActionStep(NarrowScalar, 0, s64));
159   ASSERT_EQ(
160       L.getAction({G_PTRTOINT, {s64, LLT::pointer(0, 32)}}),
161       LegalizerInfo::LegalizeActionStep(Unsupported, 1, LLT::pointer(0, 32)));
162 }
163 
164 TEST(LegalizerInfoTest, MultipleSteps) {
165   using namespace TargetOpcode;
166   LegalizerInfo L;
167   LLT s32 = LLT::scalar(32);
168   LLT s64 = LLT::scalar(64);
169 
170   L.setLegalizeScalarToDifferentSizeStrategy(
171       G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
172   L.setAction({G_UREM, 0, s32}, Lower);
173   L.setAction({G_UREM, 0, s64}, Lower);
174 
175   L.computeTables();
176 
177   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(16)}}),
178             LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
179   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(32)}}),
180             LegalizerInfo::LegalizeActionStep(Lower, 0, LLT::scalar(32)));
181 }
182 
183 TEST(LegalizerInfoTest, SizeChangeStrategy) {
184   using namespace TargetOpcode;
185   LegalizerInfo L;
186   for (unsigned Size : {1, 8, 16, 32})
187     L.setAction({G_UREM, 0, LLT::scalar(Size)}, Legal);
188 
189   L.setLegalizeScalarToDifferentSizeStrategy(
190       G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
191   L.computeTables();
192 
193   // Check we infer the correct types and actually do what we're told.
194   for (unsigned Size : {1, 8, 16, 32}) {
195     ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(Size)}}),
196               LegalizerInfo::LegalizeActionStep(Legal, 0, LLT{}));
197   }
198   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(2)}}),
199             LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(8)));
200   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(7)}}),
201             LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(8)));
202   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(9)}}),
203             LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(16)));
204   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(17)}}),
205             LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
206   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(31)}}),
207             LegalizerInfo::LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
208   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(33)}}),
209             LegalizerInfo::LegalizeActionStep(Unsupported, 0, LLT::scalar(33)));
210 }
211 }
212