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