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