1 //===- X86LegalizerInfo.cpp --------------------------------------*- C++ -*-==// 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 /// \file 10 /// This file implements the targeting of the Machinelegalizer class for X86. 11 /// \todo This should be generated by TableGen. 12 //===----------------------------------------------------------------------===// 13 14 #include "X86LegalizerInfo.h" 15 #include "X86Subtarget.h" 16 #include "X86TargetMachine.h" 17 #include "llvm/CodeGen/ValueTypes.h" 18 #include "llvm/IR/DerivedTypes.h" 19 #include "llvm/IR/Type.h" 20 #include "llvm/Target/TargetOpcodes.h" 21 22 using namespace llvm; 23 using namespace TargetOpcode; 24 25 /// FIXME: The following static functions are SizeChangeStrategy functions 26 /// that are meant to temporarily mimic the behaviour of the old legalization 27 /// based on doubling/halving non-legal types as closely as possible. This is 28 /// not entirly possible as only legalizing the types that are exactly a power 29 /// of 2 times the size of the legal types would require specifying all those 30 /// sizes explicitly. 31 /// In practice, not specifying those isn't a problem, and the below functions 32 /// should disappear quickly as we add support for legalizing non-power-of-2 33 /// sized types further. 34 static void 35 addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result, 36 const LegalizerInfo::SizeAndActionsVec &v) { 37 for (unsigned i = 0; i < v.size(); ++i) { 38 result.push_back(v[i]); 39 if (i + 1 < v[i].first && i + 1 < v.size() && 40 v[i + 1].first != v[i].first + 1) 41 result.push_back({v[i].first + 1, LegalizerInfo::Unsupported}); 42 } 43 } 44 45 static LegalizerInfo::SizeAndActionsVec 46 widen_1(const LegalizerInfo::SizeAndActionsVec &v) { 47 assert(v.size() >= 1); 48 assert(v[0].first > 1); 49 LegalizerInfo::SizeAndActionsVec result = {{1, LegalizerInfo::WidenScalar}, 50 {2, LegalizerInfo::Unsupported}}; 51 addAndInterleaveWithUnsupported(result, v); 52 auto Largest = result.back().first; 53 result.push_back({Largest + 1, LegalizerInfo::Unsupported}); 54 return result; 55 } 56 57 X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, 58 const X86TargetMachine &TM) 59 : Subtarget(STI), TM(TM) { 60 61 setLegalizerInfo32bit(); 62 setLegalizerInfo64bit(); 63 setLegalizerInfoSSE1(); 64 setLegalizerInfoSSE2(); 65 setLegalizerInfoSSE41(); 66 setLegalizerInfoAVX(); 67 setLegalizerInfoAVX2(); 68 setLegalizerInfoAVX512(); 69 setLegalizerInfoAVX512DQ(); 70 setLegalizerInfoAVX512BW(); 71 72 setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1); 73 for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR}) 74 setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1); 75 for (unsigned MemOp : {G_LOAD, G_STORE}) 76 setLegalizeScalarToDifferentSizeStrategy(MemOp, 0, 77 narrowToSmallerAndWidenToSmallest); 78 setLegalizeScalarToDifferentSizeStrategy( 79 G_GEP, 1, widenToLargerTypesUnsupportedOtherwise); 80 setLegalizeScalarToDifferentSizeStrategy( 81 G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest); 82 83 computeTables(); 84 } 85 86 void X86LegalizerInfo::setLegalizerInfo32bit() { 87 88 const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8); 89 const LLT s1 = LLT::scalar(1); 90 const LLT s8 = LLT::scalar(8); 91 const LLT s16 = LLT::scalar(16); 92 const LLT s32 = LLT::scalar(32); 93 94 for (auto Ty : {p0, s1, s8, s16, s32}) 95 setAction({G_IMPLICIT_DEF, Ty}, Legal); 96 97 for (auto Ty : {s8, s16, s32, p0}) 98 setAction({G_PHI, Ty}, Legal); 99 100 for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) 101 for (auto Ty : {s8, s16, s32}) 102 setAction({BinOp, Ty}, Legal); 103 104 for (unsigned Op : {G_UADDE}) { 105 setAction({Op, s32}, Legal); 106 setAction({Op, 1, s1}, Legal); 107 } 108 109 for (unsigned MemOp : {G_LOAD, G_STORE}) { 110 for (auto Ty : {s8, s16, s32, p0}) 111 setAction({MemOp, Ty}, Legal); 112 113 // And everything's fine in addrspace 0. 114 setAction({MemOp, 1, p0}, Legal); 115 } 116 117 // Pointer-handling 118 setAction({G_FRAME_INDEX, p0}, Legal); 119 setAction({G_GLOBAL_VALUE, p0}, Legal); 120 121 setAction({G_GEP, p0}, Legal); 122 setAction({G_GEP, 1, s32}, Legal); 123 124 // Control-flow 125 setAction({G_BRCOND, s1}, Legal); 126 127 // Constants 128 for (auto Ty : {s8, s16, s32, p0}) 129 setAction({TargetOpcode::G_CONSTANT, Ty}, Legal); 130 131 // Extensions 132 for (auto Ty : {s8, s16, s32}) { 133 setAction({G_ZEXT, Ty}, Legal); 134 setAction({G_SEXT, Ty}, Legal); 135 setAction({G_ANYEXT, Ty}, Legal); 136 } 137 138 // Comparison 139 setAction({G_ICMP, s1}, Legal); 140 141 for (auto Ty : {s8, s16, s32, p0}) 142 setAction({G_ICMP, 1, Ty}, Legal); 143 } 144 145 void X86LegalizerInfo::setLegalizerInfo64bit() { 146 147 if (!Subtarget.is64Bit()) 148 return; 149 150 const LLT s64 = LLT::scalar(64); 151 152 setAction({G_IMPLICIT_DEF, s64}, Legal); 153 154 setAction({G_PHI, s64}, Legal); 155 156 for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) 157 setAction({BinOp, s64}, Legal); 158 159 for (unsigned MemOp : {G_LOAD, G_STORE}) 160 setAction({MemOp, s64}, Legal); 161 162 // Pointer-handling 163 setAction({G_GEP, 1, s64}, Legal); 164 165 // Constants 166 setAction({TargetOpcode::G_CONSTANT, s64}, Legal); 167 168 // Extensions 169 for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) { 170 setAction({extOp, s64}, Legal); 171 } 172 173 // Comparison 174 setAction({G_ICMP, 1, s64}, Legal); 175 } 176 177 void X86LegalizerInfo::setLegalizerInfoSSE1() { 178 if (!Subtarget.hasSSE1()) 179 return; 180 181 const LLT s32 = LLT::scalar(32); 182 const LLT v4s32 = LLT::vector(4, 32); 183 const LLT v2s64 = LLT::vector(2, 64); 184 185 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV}) 186 for (auto Ty : {s32, v4s32}) 187 setAction({BinOp, Ty}, Legal); 188 189 for (unsigned MemOp : {G_LOAD, G_STORE}) 190 for (auto Ty : {v4s32, v2s64}) 191 setAction({MemOp, Ty}, Legal); 192 193 // Constants 194 setAction({TargetOpcode::G_FCONSTANT, s32}, Legal); 195 } 196 197 void X86LegalizerInfo::setLegalizerInfoSSE2() { 198 if (!Subtarget.hasSSE2()) 199 return; 200 201 const LLT s32 = LLT::scalar(32); 202 const LLT s64 = LLT::scalar(64); 203 const LLT v16s8 = LLT::vector(16, 8); 204 const LLT v8s16 = LLT::vector(8, 16); 205 const LLT v4s32 = LLT::vector(4, 32); 206 const LLT v2s64 = LLT::vector(2, 64); 207 208 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV}) 209 for (auto Ty : {s64, v2s64}) 210 setAction({BinOp, Ty}, Legal); 211 212 for (unsigned BinOp : {G_ADD, G_SUB}) 213 for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) 214 setAction({BinOp, Ty}, Legal); 215 216 setAction({G_MUL, v8s16}, Legal); 217 218 setAction({G_FPEXT, s64}, Legal); 219 setAction({G_FPEXT, 1, s32}, Legal); 220 221 // Constants 222 setAction({TargetOpcode::G_FCONSTANT, s64}, Legal); 223 } 224 225 void X86LegalizerInfo::setLegalizerInfoSSE41() { 226 if (!Subtarget.hasSSE41()) 227 return; 228 229 const LLT v4s32 = LLT::vector(4, 32); 230 231 setAction({G_MUL, v4s32}, Legal); 232 } 233 234 void X86LegalizerInfo::setLegalizerInfoAVX() { 235 if (!Subtarget.hasAVX()) 236 return; 237 238 const LLT v16s8 = LLT::vector(16, 8); 239 const LLT v8s16 = LLT::vector(8, 16); 240 const LLT v4s32 = LLT::vector(4, 32); 241 const LLT v2s64 = LLT::vector(2, 64); 242 243 const LLT v32s8 = LLT::vector(32, 8); 244 const LLT v16s16 = LLT::vector(16, 16); 245 const LLT v8s32 = LLT::vector(8, 32); 246 const LLT v4s64 = LLT::vector(4, 64); 247 248 for (unsigned MemOp : {G_LOAD, G_STORE}) 249 for (auto Ty : {v8s32, v4s64}) 250 setAction({MemOp, Ty}, Legal); 251 252 for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) { 253 setAction({G_INSERT, Ty}, Legal); 254 setAction({G_EXTRACT, 1, Ty}, Legal); 255 } 256 for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) { 257 setAction({G_INSERT, 1, Ty}, Legal); 258 setAction({G_EXTRACT, Ty}, Legal); 259 } 260 } 261 262 void X86LegalizerInfo::setLegalizerInfoAVX2() { 263 if (!Subtarget.hasAVX2()) 264 return; 265 266 const LLT v32s8 = LLT::vector(32, 8); 267 const LLT v16s16 = LLT::vector(16, 16); 268 const LLT v8s32 = LLT::vector(8, 32); 269 const LLT v4s64 = LLT::vector(4, 64); 270 271 for (unsigned BinOp : {G_ADD, G_SUB}) 272 for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) 273 setAction({BinOp, Ty}, Legal); 274 275 for (auto Ty : {v16s16, v8s32}) 276 setAction({G_MUL, Ty}, Legal); 277 } 278 279 void X86LegalizerInfo::setLegalizerInfoAVX512() { 280 if (!Subtarget.hasAVX512()) 281 return; 282 283 const LLT v16s8 = LLT::vector(16, 8); 284 const LLT v8s16 = LLT::vector(8, 16); 285 const LLT v4s32 = LLT::vector(4, 32); 286 const LLT v2s64 = LLT::vector(2, 64); 287 288 const LLT v32s8 = LLT::vector(32, 8); 289 const LLT v16s16 = LLT::vector(16, 16); 290 const LLT v8s32 = LLT::vector(8, 32); 291 const LLT v4s64 = LLT::vector(4, 64); 292 293 const LLT v64s8 = LLT::vector(64, 8); 294 const LLT v32s16 = LLT::vector(32, 16); 295 const LLT v16s32 = LLT::vector(16, 32); 296 const LLT v8s64 = LLT::vector(8, 64); 297 298 for (unsigned BinOp : {G_ADD, G_SUB}) 299 for (auto Ty : {v16s32, v8s64}) 300 setAction({BinOp, Ty}, Legal); 301 302 setAction({G_MUL, v16s32}, Legal); 303 304 for (unsigned MemOp : {G_LOAD, G_STORE}) 305 for (auto Ty : {v16s32, v8s64}) 306 setAction({MemOp, Ty}, Legal); 307 308 for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) { 309 setAction({G_INSERT, Ty}, Legal); 310 setAction({G_EXTRACT, 1, Ty}, Legal); 311 } 312 for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) { 313 setAction({G_INSERT, 1, Ty}, Legal); 314 setAction({G_EXTRACT, Ty}, Legal); 315 } 316 317 /************ VLX *******************/ 318 if (!Subtarget.hasVLX()) 319 return; 320 321 for (auto Ty : {v4s32, v8s32}) 322 setAction({G_MUL, Ty}, Legal); 323 } 324 325 void X86LegalizerInfo::setLegalizerInfoAVX512DQ() { 326 if (!(Subtarget.hasAVX512() && Subtarget.hasDQI())) 327 return; 328 329 const LLT v8s64 = LLT::vector(8, 64); 330 331 setAction({G_MUL, v8s64}, Legal); 332 333 /************ VLX *******************/ 334 if (!Subtarget.hasVLX()) 335 return; 336 337 const LLT v2s64 = LLT::vector(2, 64); 338 const LLT v4s64 = LLT::vector(4, 64); 339 340 for (auto Ty : {v2s64, v4s64}) 341 setAction({G_MUL, Ty}, Legal); 342 } 343 344 void X86LegalizerInfo::setLegalizerInfoAVX512BW() { 345 if (!(Subtarget.hasAVX512() && Subtarget.hasBWI())) 346 return; 347 348 const LLT v64s8 = LLT::vector(64, 8); 349 const LLT v32s16 = LLT::vector(32, 16); 350 351 for (unsigned BinOp : {G_ADD, G_SUB}) 352 for (auto Ty : {v64s8, v32s16}) 353 setAction({BinOp, Ty}, Legal); 354 355 setAction({G_MUL, v32s16}, Legal); 356 357 /************ VLX *******************/ 358 if (!Subtarget.hasVLX()) 359 return; 360 361 const LLT v8s16 = LLT::vector(8, 16); 362 const LLT v16s16 = LLT::vector(16, 16); 363 364 for (auto Ty : {v8s16, v16s16}) 365 setAction({G_MUL, Ty}, Legal); 366 } 367