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/TargetOpcodes.h" 18 #include "llvm/CodeGen/ValueTypes.h" 19 #include "llvm/IR/DerivedTypes.h" 20 #include "llvm/IR/Type.h" 21 22 using namespace llvm; 23 using namespace TargetOpcode; 24 using namespace LegalizeActions; 25 26 /// FIXME: The following static functions are SizeChangeStrategy functions 27 /// that are meant to temporarily mimic the behaviour of the old legalization 28 /// based on doubling/halving non-legal types as closely as possible. This is 29 /// not entirly possible as only legalizing the types that are exactly a power 30 /// of 2 times the size of the legal types would require specifying all those 31 /// sizes explicitly. 32 /// In practice, not specifying those isn't a problem, and the below functions 33 /// should disappear quickly as we add support for legalizing non-power-of-2 34 /// sized types further. 35 static void 36 addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result, 37 const LegalizerInfo::SizeAndActionsVec &v) { 38 for (unsigned i = 0; i < v.size(); ++i) { 39 result.push_back(v[i]); 40 if (i + 1 < v[i].first && i + 1 < v.size() && 41 v[i + 1].first != v[i].first + 1) 42 result.push_back({v[i].first + 1, Unsupported}); 43 } 44 } 45 46 static LegalizerInfo::SizeAndActionsVec 47 widen_1(const LegalizerInfo::SizeAndActionsVec &v) { 48 assert(v.size() >= 1); 49 assert(v[0].first > 1); 50 LegalizerInfo::SizeAndActionsVec result = {{1, WidenScalar}, 51 {2, Unsupported}}; 52 addAndInterleaveWithUnsupported(result, v); 53 auto Largest = result.back().first; 54 result.push_back({Largest + 1, Unsupported}); 55 return result; 56 } 57 58 X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, 59 const X86TargetMachine &TM) 60 : Subtarget(STI), TM(TM) { 61 62 setLegalizerInfo32bit(); 63 setLegalizerInfo64bit(); 64 setLegalizerInfoSSE1(); 65 setLegalizerInfoSSE2(); 66 setLegalizerInfoSSE41(); 67 setLegalizerInfoAVX(); 68 setLegalizerInfoAVX2(); 69 setLegalizerInfoAVX512(); 70 setLegalizerInfoAVX512DQ(); 71 setLegalizerInfoAVX512BW(); 72 73 setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1); 74 for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR}) 75 setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1); 76 for (unsigned MemOp : {G_LOAD, G_STORE}) 77 setLegalizeScalarToDifferentSizeStrategy(MemOp, 0, 78 narrowToSmallerAndWidenToSmallest); 79 setLegalizeScalarToDifferentSizeStrategy( 80 G_GEP, 1, widenToLargerTypesUnsupportedOtherwise); 81 setLegalizeScalarToDifferentSizeStrategy( 82 G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest); 83 84 computeTables(); 85 verify(*STI.getInstrInfo()); 86 } 87 88 void X86LegalizerInfo::setLegalizerInfo32bit() { 89 90 const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0)); 91 const LLT s1 = LLT::scalar(1); 92 const LLT s8 = LLT::scalar(8); 93 const LLT s16 = LLT::scalar(16); 94 const LLT s32 = LLT::scalar(32); 95 const LLT s64 = LLT::scalar(64); 96 const LLT s128 = LLT::scalar(128); 97 98 for (auto Ty : {p0, s1, s8, s16, s32}) 99 setAction({G_IMPLICIT_DEF, Ty}, Legal); 100 101 for (auto Ty : {s8, s16, s32, p0}) 102 setAction({G_PHI, Ty}, Legal); 103 104 for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) 105 for (auto Ty : {s8, s16, s32}) 106 setAction({BinOp, Ty}, Legal); 107 108 for (unsigned Op : {G_UADDE}) { 109 setAction({Op, s32}, Legal); 110 setAction({Op, 1, s1}, Legal); 111 } 112 113 for (unsigned MemOp : {G_LOAD, G_STORE}) { 114 for (auto Ty : {s8, s16, s32, p0}) 115 setAction({MemOp, Ty}, Legal); 116 117 // And everything's fine in addrspace 0. 118 setAction({MemOp, 1, p0}, Legal); 119 } 120 121 // Pointer-handling 122 setAction({G_FRAME_INDEX, p0}, Legal); 123 setAction({G_GLOBAL_VALUE, p0}, Legal); 124 125 setAction({G_GEP, p0}, Legal); 126 setAction({G_GEP, 1, s32}, Legal); 127 128 if (!Subtarget.is64Bit()) { 129 getActionDefinitionsBuilder(G_PTRTOINT) 130 .legalForCartesianProduct({s1, s8, s16, s32}, {p0}) 131 .maxScalar(0, s32) 132 .widenScalarToNextPow2(0, /*Min*/ 8); 133 getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}}); 134 135 // Shifts and SDIV 136 getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR, G_SDIV}) 137 .legalFor({s8, s16, s32}) 138 .clampScalar(0, s8, s32); 139 } 140 141 // Control-flow 142 setAction({G_BRCOND, s1}, Legal); 143 144 // Constants 145 for (auto Ty : {s8, s16, s32, p0}) 146 setAction({TargetOpcode::G_CONSTANT, Ty}, Legal); 147 148 // Extensions 149 for (auto Ty : {s8, s16, s32}) { 150 setAction({G_ZEXT, Ty}, Legal); 151 setAction({G_SEXT, Ty}, Legal); 152 setAction({G_ANYEXT, Ty}, Legal); 153 } 154 setAction({G_ANYEXT, s128}, Legal); 155 156 // Comparison 157 setAction({G_ICMP, s1}, Legal); 158 159 for (auto Ty : {s8, s16, s32, p0}) 160 setAction({G_ICMP, 1, Ty}, Legal); 161 162 // Merge/Unmerge 163 for (const auto &Ty : {s16, s32, s64}) { 164 setAction({G_MERGE_VALUES, Ty}, Legal); 165 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 166 } 167 for (const auto &Ty : {s8, s16, s32}) { 168 setAction({G_MERGE_VALUES, 1, Ty}, Legal); 169 setAction({G_UNMERGE_VALUES, Ty}, Legal); 170 } 171 } 172 173 void X86LegalizerInfo::setLegalizerInfo64bit() { 174 175 if (!Subtarget.is64Bit()) 176 return; 177 178 const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0)); 179 const LLT s1 = LLT::scalar(1); 180 const LLT s8 = LLT::scalar(8); 181 const LLT s16 = LLT::scalar(16); 182 const LLT s32 = LLT::scalar(32); 183 const LLT s64 = LLT::scalar(64); 184 const LLT s128 = LLT::scalar(128); 185 186 setAction({G_IMPLICIT_DEF, s64}, Legal); 187 // Need to have that, as tryFoldImplicitDef will create this pattern: 188 // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF 189 setAction({G_IMPLICIT_DEF, s128}, Legal); 190 191 setAction({G_PHI, s64}, Legal); 192 193 for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) 194 setAction({BinOp, s64}, Legal); 195 196 for (unsigned MemOp : {G_LOAD, G_STORE}) 197 setAction({MemOp, s64}, Legal); 198 199 // Pointer-handling 200 setAction({G_GEP, 1, s64}, Legal); 201 getActionDefinitionsBuilder(G_PTRTOINT) 202 .legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0}) 203 .maxScalar(0, s64) 204 .widenScalarToNextPow2(0, /*Min*/ 8); 205 getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s64}}); 206 207 // Constants 208 setAction({TargetOpcode::G_CONSTANT, s64}, Legal); 209 210 // Extensions 211 for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) { 212 setAction({extOp, s64}, Legal); 213 } 214 215 getActionDefinitionsBuilder(G_SITOFP) 216 .legalForCartesianProduct({s32, s64}) 217 .clampScalar(1, s32, s64) 218 .widenScalarToNextPow2(1) 219 .clampScalar(0, s32, s64) 220 .widenScalarToNextPow2(0); 221 222 // Comparison 223 setAction({G_ICMP, 1, s64}, Legal); 224 225 // Shifts and SDIV 226 getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR, G_SDIV}) 227 .legalFor({s8, s16, s32, s64}) 228 .clampScalar(0, s8, s64); 229 230 // Merge/Unmerge 231 setAction({G_MERGE_VALUES, s128}, Legal); 232 setAction({G_UNMERGE_VALUES, 1, s128}, Legal); 233 setAction({G_MERGE_VALUES, 1, s128}, Legal); 234 setAction({G_UNMERGE_VALUES, s128}, Legal); 235 } 236 237 void X86LegalizerInfo::setLegalizerInfoSSE1() { 238 if (!Subtarget.hasSSE1()) 239 return; 240 241 const LLT s32 = LLT::scalar(32); 242 const LLT s64 = LLT::scalar(64); 243 const LLT v4s32 = LLT::vector(4, 32); 244 const LLT v2s64 = LLT::vector(2, 64); 245 246 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV}) 247 for (auto Ty : {s32, v4s32}) 248 setAction({BinOp, Ty}, Legal); 249 250 for (unsigned MemOp : {G_LOAD, G_STORE}) 251 for (auto Ty : {v4s32, v2s64}) 252 setAction({MemOp, Ty}, Legal); 253 254 // Constants 255 setAction({TargetOpcode::G_FCONSTANT, s32}, Legal); 256 257 // Merge/Unmerge 258 for (const auto &Ty : {v4s32, v2s64}) { 259 setAction({G_MERGE_VALUES, Ty}, Legal); 260 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 261 } 262 setAction({G_MERGE_VALUES, 1, s64}, Legal); 263 setAction({G_UNMERGE_VALUES, s64}, Legal); 264 } 265 266 void X86LegalizerInfo::setLegalizerInfoSSE2() { 267 if (!Subtarget.hasSSE2()) 268 return; 269 270 const LLT s32 = LLT::scalar(32); 271 const LLT s64 = LLT::scalar(64); 272 const LLT v16s8 = LLT::vector(16, 8); 273 const LLT v8s16 = LLT::vector(8, 16); 274 const LLT v4s32 = LLT::vector(4, 32); 275 const LLT v2s64 = LLT::vector(2, 64); 276 277 const LLT v32s8 = LLT::vector(32, 8); 278 const LLT v16s16 = LLT::vector(16, 16); 279 const LLT v8s32 = LLT::vector(8, 32); 280 const LLT v4s64 = LLT::vector(4, 64); 281 282 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV}) 283 for (auto Ty : {s64, v2s64}) 284 setAction({BinOp, Ty}, Legal); 285 286 for (unsigned BinOp : {G_ADD, G_SUB}) 287 for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) 288 setAction({BinOp, Ty}, Legal); 289 290 setAction({G_MUL, v8s16}, Legal); 291 292 setAction({G_FPEXT, s64}, Legal); 293 setAction({G_FPEXT, 1, s32}, Legal); 294 295 // Constants 296 setAction({TargetOpcode::G_FCONSTANT, s64}, Legal); 297 298 // Merge/Unmerge 299 for (const auto &Ty : 300 {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) { 301 setAction({G_MERGE_VALUES, Ty}, Legal); 302 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 303 } 304 for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) { 305 setAction({G_MERGE_VALUES, 1, Ty}, Legal); 306 setAction({G_UNMERGE_VALUES, Ty}, Legal); 307 } 308 } 309 310 void X86LegalizerInfo::setLegalizerInfoSSE41() { 311 if (!Subtarget.hasSSE41()) 312 return; 313 314 const LLT v4s32 = LLT::vector(4, 32); 315 316 setAction({G_MUL, v4s32}, Legal); 317 } 318 319 void X86LegalizerInfo::setLegalizerInfoAVX() { 320 if (!Subtarget.hasAVX()) 321 return; 322 323 const LLT v16s8 = LLT::vector(16, 8); 324 const LLT v8s16 = LLT::vector(8, 16); 325 const LLT v4s32 = LLT::vector(4, 32); 326 const LLT v2s64 = LLT::vector(2, 64); 327 328 const LLT v32s8 = LLT::vector(32, 8); 329 const LLT v64s8 = LLT::vector(64, 8); 330 const LLT v16s16 = LLT::vector(16, 16); 331 const LLT v32s16 = LLT::vector(32, 16); 332 const LLT v8s32 = LLT::vector(8, 32); 333 const LLT v16s32 = LLT::vector(16, 32); 334 const LLT v4s64 = LLT::vector(4, 64); 335 const LLT v8s64 = LLT::vector(8, 64); 336 337 for (unsigned MemOp : {G_LOAD, G_STORE}) 338 for (auto Ty : {v8s32, v4s64}) 339 setAction({MemOp, Ty}, Legal); 340 341 for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) { 342 setAction({G_INSERT, Ty}, Legal); 343 setAction({G_EXTRACT, 1, Ty}, Legal); 344 } 345 for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) { 346 setAction({G_INSERT, 1, Ty}, Legal); 347 setAction({G_EXTRACT, Ty}, Legal); 348 } 349 // Merge/Unmerge 350 for (const auto &Ty : 351 {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) { 352 setAction({G_MERGE_VALUES, Ty}, Legal); 353 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 354 } 355 for (const auto &Ty : 356 {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) { 357 setAction({G_MERGE_VALUES, 1, Ty}, Legal); 358 setAction({G_UNMERGE_VALUES, Ty}, Legal); 359 } 360 } 361 362 void X86LegalizerInfo::setLegalizerInfoAVX2() { 363 if (!Subtarget.hasAVX2()) 364 return; 365 366 const LLT v32s8 = LLT::vector(32, 8); 367 const LLT v16s16 = LLT::vector(16, 16); 368 const LLT v8s32 = LLT::vector(8, 32); 369 const LLT v4s64 = LLT::vector(4, 64); 370 371 const LLT v64s8 = LLT::vector(64, 8); 372 const LLT v32s16 = LLT::vector(32, 16); 373 const LLT v16s32 = LLT::vector(16, 32); 374 const LLT v8s64 = LLT::vector(8, 64); 375 376 for (unsigned BinOp : {G_ADD, G_SUB}) 377 for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) 378 setAction({BinOp, Ty}, Legal); 379 380 for (auto Ty : {v16s16, v8s32}) 381 setAction({G_MUL, Ty}, Legal); 382 383 // Merge/Unmerge 384 for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) { 385 setAction({G_MERGE_VALUES, Ty}, Legal); 386 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 387 } 388 for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) { 389 setAction({G_MERGE_VALUES, 1, Ty}, Legal); 390 setAction({G_UNMERGE_VALUES, Ty}, Legal); 391 } 392 } 393 394 void X86LegalizerInfo::setLegalizerInfoAVX512() { 395 if (!Subtarget.hasAVX512()) 396 return; 397 398 const LLT v16s8 = LLT::vector(16, 8); 399 const LLT v8s16 = LLT::vector(8, 16); 400 const LLT v4s32 = LLT::vector(4, 32); 401 const LLT v2s64 = LLT::vector(2, 64); 402 403 const LLT v32s8 = LLT::vector(32, 8); 404 const LLT v16s16 = LLT::vector(16, 16); 405 const LLT v8s32 = LLT::vector(8, 32); 406 const LLT v4s64 = LLT::vector(4, 64); 407 408 const LLT v64s8 = LLT::vector(64, 8); 409 const LLT v32s16 = LLT::vector(32, 16); 410 const LLT v16s32 = LLT::vector(16, 32); 411 const LLT v8s64 = LLT::vector(8, 64); 412 413 for (unsigned BinOp : {G_ADD, G_SUB}) 414 for (auto Ty : {v16s32, v8s64}) 415 setAction({BinOp, Ty}, Legal); 416 417 setAction({G_MUL, v16s32}, Legal); 418 419 for (unsigned MemOp : {G_LOAD, G_STORE}) 420 for (auto Ty : {v16s32, v8s64}) 421 setAction({MemOp, Ty}, Legal); 422 423 for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) { 424 setAction({G_INSERT, Ty}, Legal); 425 setAction({G_EXTRACT, 1, Ty}, Legal); 426 } 427 for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) { 428 setAction({G_INSERT, 1, Ty}, Legal); 429 setAction({G_EXTRACT, Ty}, Legal); 430 } 431 432 /************ VLX *******************/ 433 if (!Subtarget.hasVLX()) 434 return; 435 436 for (auto Ty : {v4s32, v8s32}) 437 setAction({G_MUL, Ty}, Legal); 438 } 439 440 void X86LegalizerInfo::setLegalizerInfoAVX512DQ() { 441 if (!(Subtarget.hasAVX512() && Subtarget.hasDQI())) 442 return; 443 444 const LLT v8s64 = LLT::vector(8, 64); 445 446 setAction({G_MUL, v8s64}, Legal); 447 448 /************ VLX *******************/ 449 if (!Subtarget.hasVLX()) 450 return; 451 452 const LLT v2s64 = LLT::vector(2, 64); 453 const LLT v4s64 = LLT::vector(4, 64); 454 455 for (auto Ty : {v2s64, v4s64}) 456 setAction({G_MUL, Ty}, Legal); 457 } 458 459 void X86LegalizerInfo::setLegalizerInfoAVX512BW() { 460 if (!(Subtarget.hasAVX512() && Subtarget.hasBWI())) 461 return; 462 463 const LLT v64s8 = LLT::vector(64, 8); 464 const LLT v32s16 = LLT::vector(32, 16); 465 466 for (unsigned BinOp : {G_ADD, G_SUB}) 467 for (auto Ty : {v64s8, v32s16}) 468 setAction({BinOp, Ty}, Legal); 469 470 setAction({G_MUL, v32s16}, Legal); 471 472 /************ VLX *******************/ 473 if (!Subtarget.hasVLX()) 474 return; 475 476 const LLT v8s16 = LLT::vector(8, 16); 477 const LLT v16s16 = LLT::vector(16, 16); 478 479 for (auto Ty : {v8s16, v16s16}) 480 setAction({G_MUL, Ty}, Legal); 481 } 482