xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp (revision d5b7a00fd53398211a048e534ad43b32d474cf7c)
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/Target/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               std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
65     ASSERT_EQ(L.getAction({opcode, LLT::scalar(16)}),
66               std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
67     ASSERT_EQ(L.getAction({opcode, LLT::scalar(32)}),
68               std::make_pair(LegalizerInfo::Legal, LLT::scalar(32)));
69     ASSERT_EQ(L.getAction({opcode, LLT::scalar(64)}),
70               std::make_pair(LegalizerInfo::Legal, LLT::scalar(64)));
71 
72     // Make sure the default for over-sized types applies.
73     ASSERT_EQ(L.getAction({opcode, LLT::scalar(128)}),
74               std::make_pair(LegalizerInfo::NarrowScalar, LLT::scalar(64)));
75     // Make sure we also handle unusual sizes
76     ASSERT_EQ(L.getAction({opcode, LLT::scalar(1)}),
77               std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
78     ASSERT_EQ(L.getAction({opcode, LLT::scalar(31)}),
79               std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
80     ASSERT_EQ(L.getAction({opcode, LLT::scalar(33)}),
81               std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(64)));
82     ASSERT_EQ(L.getAction({opcode, LLT::scalar(63)}),
83               std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(64)));
84     ASSERT_EQ(L.getAction({opcode, LLT::scalar(65)}),
85               std::make_pair(LegalizerInfo::NarrowScalar, 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             std::make_pair(LegalizerInfo::Legal, LLT::vector(8, 8)));
111   ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 7)}),
112             std::make_pair(LegalizerInfo::WidenScalar, LLT::vector(8, 8)));
113   ASSERT_EQ(L.getAction({G_ADD, LLT::vector(2, 8)}),
114             std::make_pair(LegalizerInfo::MoreElements, LLT::vector(8, 8)));
115   ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 32)}),
116             std::make_pair(LegalizerInfo::FewerElements, 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             std::make_pair(LegalizerInfo::WidenScalar, LLT::vector(3, 8)));
120   ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 8)}),
121             std::make_pair(LegalizerInfo::MoreElements, 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, 0, s64}),
141             std::make_pair(LegalizerInfo::Legal, s64));
142   ASSERT_EQ(L.getAction({G_PTRTOINT, 1, p0}),
143             std::make_pair(LegalizerInfo::Legal, p0));
144   // Make sure we also handle unusual sizes
145   ASSERT_EQ(L.getAction({G_PTRTOINT, 0, LLT::scalar(65)}),
146             std::make_pair(LegalizerInfo::NarrowScalar, s64));
147   ASSERT_EQ(L.getAction({G_PTRTOINT, 1, LLT::pointer(0, 32)}),
148             std::make_pair(LegalizerInfo::Unsupported, LLT::pointer(0, 32)));
149 }
150 
151 TEST(LegalizerInfoTest, MultipleSteps) {
152   using namespace TargetOpcode;
153   LegalizerInfo L;
154   LLT s32 = LLT::scalar(32);
155   LLT s64 = LLT::scalar(64);
156 
157   L.setLegalizeScalarToDifferentSizeStrategy(
158       G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
159   L.setAction({G_UREM, 0, s32}, LegalizerInfo::Lower);
160   L.setAction({G_UREM, 0, s64}, LegalizerInfo::Lower);
161 
162   L.computeTables();
163 
164   ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(16)}),
165             std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
166   ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(32)}),
167             std::make_pair(LegalizerInfo::Lower, LLT::scalar(32)));
168 }
169 
170 TEST(LegalizerInfoTest, SizeChangeStrategy) {
171   using namespace TargetOpcode;
172   LegalizerInfo L;
173   for (unsigned Size : {1, 8, 16, 32})
174     L.setAction({G_UREM, 0, LLT::scalar(Size)}, LegalizerInfo::Legal);
175 
176   L.setLegalizeScalarToDifferentSizeStrategy(
177       G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
178   L.computeTables();
179 
180   // Check we infer the correct types and actually do what we're told.
181   for (unsigned Size : {1, 8, 16, 32}) {
182     ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(Size)}),
183               std::make_pair(LegalizerInfo::Legal, LLT::scalar(Size)));
184   }
185   ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(2)}),
186             std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(8)));
187   ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(7)}),
188             std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(8)));
189   ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(9)}),
190             std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(16)));
191   ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(17)}),
192             std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
193   ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(31)}),
194             std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
195   ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(33)}),
196             std::make_pair(LegalizerInfo::Unsupported, LLT::scalar(33)));
197 }
198 }
199