X86LegalizerInfo.cpp revision 344779
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 22using namespace llvm; 23using namespace TargetOpcode; 24using 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. 35static void 36addAndInterleaveWithUnsupported(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 46static LegalizerInfo::SizeAndActionsVec 47widen_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 58X86LegalizerInfo::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 88void 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( 137 {G_SHL, G_LSHR, G_ASHR, G_SDIV, G_SREM, G_UDIV, G_UREM}) 138 .legalFor({s8, s16, s32}) 139 .clampScalar(0, s8, s32); 140 } 141 142 // Control-flow 143 setAction({G_BRCOND, s1}, Legal); 144 145 // Constants 146 for (auto Ty : {s8, s16, s32, p0}) 147 setAction({TargetOpcode::G_CONSTANT, Ty}, Legal); 148 149 // Extensions 150 for (auto Ty : {s8, s16, s32}) { 151 setAction({G_ZEXT, Ty}, Legal); 152 setAction({G_SEXT, Ty}, Legal); 153 setAction({G_ANYEXT, Ty}, Legal); 154 } 155 setAction({G_ANYEXT, s128}, Legal); 156 157 // Comparison 158 setAction({G_ICMP, s1}, Legal); 159 160 for (auto Ty : {s8, s16, s32, p0}) 161 setAction({G_ICMP, 1, Ty}, Legal); 162 163 // Merge/Unmerge 164 for (const auto &Ty : {s16, s32, s64}) { 165 setAction({G_MERGE_VALUES, Ty}, Legal); 166 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 167 } 168 for (const auto &Ty : {s8, s16, s32}) { 169 setAction({G_MERGE_VALUES, 1, Ty}, Legal); 170 setAction({G_UNMERGE_VALUES, Ty}, Legal); 171 } 172} 173 174void X86LegalizerInfo::setLegalizerInfo64bit() { 175 176 if (!Subtarget.is64Bit()) 177 return; 178 179 const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0)); 180 const LLT s1 = LLT::scalar(1); 181 const LLT s8 = LLT::scalar(8); 182 const LLT s16 = LLT::scalar(16); 183 const LLT s32 = LLT::scalar(32); 184 const LLT s64 = LLT::scalar(64); 185 const LLT s128 = LLT::scalar(128); 186 187 setAction({G_IMPLICIT_DEF, s64}, Legal); 188 // Need to have that, as tryFoldImplicitDef will create this pattern: 189 // s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF 190 setAction({G_IMPLICIT_DEF, s128}, Legal); 191 192 setAction({G_PHI, s64}, Legal); 193 194 for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) 195 setAction({BinOp, s64}, Legal); 196 197 for (unsigned MemOp : {G_LOAD, G_STORE}) 198 setAction({MemOp, s64}, Legal); 199 200 // Pointer-handling 201 setAction({G_GEP, 1, s64}, Legal); 202 getActionDefinitionsBuilder(G_PTRTOINT) 203 .legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0}) 204 .maxScalar(0, s64) 205 .widenScalarToNextPow2(0, /*Min*/ 8); 206 getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s64}}); 207 208 // Constants 209 setAction({TargetOpcode::G_CONSTANT, s64}, Legal); 210 211 // Extensions 212 for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) { 213 setAction({extOp, s64}, Legal); 214 } 215 216 getActionDefinitionsBuilder(G_SITOFP) 217 .legalForCartesianProduct({s32, s64}) 218 .clampScalar(1, s32, s64) 219 .widenScalarToNextPow2(1) 220 .clampScalar(0, s32, s64) 221 .widenScalarToNextPow2(0); 222 223 getActionDefinitionsBuilder(G_FPTOSI) 224 .legalForCartesianProduct({s32, s64}) 225 .clampScalar(1, s32, s64) 226 .widenScalarToNextPow2(0) 227 .clampScalar(0, s32, s64) 228 .widenScalarToNextPow2(1); 229 230 // Comparison 231 setAction({G_ICMP, 1, s64}, Legal); 232 233 getActionDefinitionsBuilder(G_FCMP) 234 .legalForCartesianProduct({s8}, {s32, s64}) 235 .clampScalar(0, s8, s8) 236 .clampScalar(1, s32, s64) 237 .widenScalarToNextPow2(1); 238 239 // Shifts and SDIV 240 getActionDefinitionsBuilder( 241 {G_SHL, G_LSHR, G_ASHR, G_SDIV, G_SREM, G_UDIV, G_UREM}) 242 .legalFor({s8, s16, s32, s64}) 243 .clampScalar(0, s8, s64); 244 245 // Merge/Unmerge 246 setAction({G_MERGE_VALUES, s128}, Legal); 247 setAction({G_UNMERGE_VALUES, 1, s128}, Legal); 248 setAction({G_MERGE_VALUES, 1, s128}, Legal); 249 setAction({G_UNMERGE_VALUES, s128}, Legal); 250} 251 252void X86LegalizerInfo::setLegalizerInfoSSE1() { 253 if (!Subtarget.hasSSE1()) 254 return; 255 256 const LLT s32 = LLT::scalar(32); 257 const LLT s64 = LLT::scalar(64); 258 const LLT v4s32 = LLT::vector(4, 32); 259 const LLT v2s64 = LLT::vector(2, 64); 260 261 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV}) 262 for (auto Ty : {s32, v4s32}) 263 setAction({BinOp, Ty}, Legal); 264 265 for (unsigned MemOp : {G_LOAD, G_STORE}) 266 for (auto Ty : {v4s32, v2s64}) 267 setAction({MemOp, Ty}, Legal); 268 269 // Constants 270 setAction({TargetOpcode::G_FCONSTANT, s32}, Legal); 271 272 // Merge/Unmerge 273 for (const auto &Ty : {v4s32, v2s64}) { 274 setAction({G_CONCAT_VECTORS, Ty}, Legal); 275 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 276 } 277 setAction({G_MERGE_VALUES, 1, s64}, Legal); 278 setAction({G_UNMERGE_VALUES, s64}, Legal); 279} 280 281void X86LegalizerInfo::setLegalizerInfoSSE2() { 282 if (!Subtarget.hasSSE2()) 283 return; 284 285 const LLT s32 = LLT::scalar(32); 286 const LLT s64 = LLT::scalar(64); 287 const LLT v16s8 = LLT::vector(16, 8); 288 const LLT v8s16 = LLT::vector(8, 16); 289 const LLT v4s32 = LLT::vector(4, 32); 290 const LLT v2s64 = LLT::vector(2, 64); 291 292 const LLT v32s8 = LLT::vector(32, 8); 293 const LLT v16s16 = LLT::vector(16, 16); 294 const LLT v8s32 = LLT::vector(8, 32); 295 const LLT v4s64 = LLT::vector(4, 64); 296 297 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV}) 298 for (auto Ty : {s64, v2s64}) 299 setAction({BinOp, Ty}, Legal); 300 301 for (unsigned BinOp : {G_ADD, G_SUB}) 302 for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) 303 setAction({BinOp, Ty}, Legal); 304 305 setAction({G_MUL, v8s16}, Legal); 306 307 setAction({G_FPEXT, s64}, Legal); 308 setAction({G_FPEXT, 1, s32}, Legal); 309 310 setAction({G_FPTRUNC, s32}, Legal); 311 setAction({G_FPTRUNC, 1, s64}, Legal); 312 313 // Constants 314 setAction({TargetOpcode::G_FCONSTANT, s64}, Legal); 315 316 // Merge/Unmerge 317 for (const auto &Ty : 318 {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) { 319 setAction({G_CONCAT_VECTORS, Ty}, Legal); 320 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 321 } 322 for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) { 323 setAction({G_CONCAT_VECTORS, 1, Ty}, Legal); 324 setAction({G_UNMERGE_VALUES, Ty}, Legal); 325 } 326} 327 328void X86LegalizerInfo::setLegalizerInfoSSE41() { 329 if (!Subtarget.hasSSE41()) 330 return; 331 332 const LLT v4s32 = LLT::vector(4, 32); 333 334 setAction({G_MUL, v4s32}, Legal); 335} 336 337void X86LegalizerInfo::setLegalizerInfoAVX() { 338 if (!Subtarget.hasAVX()) 339 return; 340 341 const LLT v16s8 = LLT::vector(16, 8); 342 const LLT v8s16 = LLT::vector(8, 16); 343 const LLT v4s32 = LLT::vector(4, 32); 344 const LLT v2s64 = LLT::vector(2, 64); 345 346 const LLT v32s8 = LLT::vector(32, 8); 347 const LLT v64s8 = LLT::vector(64, 8); 348 const LLT v16s16 = LLT::vector(16, 16); 349 const LLT v32s16 = LLT::vector(32, 16); 350 const LLT v8s32 = LLT::vector(8, 32); 351 const LLT v16s32 = LLT::vector(16, 32); 352 const LLT v4s64 = LLT::vector(4, 64); 353 const LLT v8s64 = LLT::vector(8, 64); 354 355 for (unsigned MemOp : {G_LOAD, G_STORE}) 356 for (auto Ty : {v8s32, v4s64}) 357 setAction({MemOp, Ty}, Legal); 358 359 for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) { 360 setAction({G_INSERT, Ty}, Legal); 361 setAction({G_EXTRACT, 1, Ty}, Legal); 362 } 363 for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) { 364 setAction({G_INSERT, 1, Ty}, Legal); 365 setAction({G_EXTRACT, Ty}, Legal); 366 } 367 // Merge/Unmerge 368 for (const auto &Ty : 369 {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) { 370 setAction({G_CONCAT_VECTORS, Ty}, Legal); 371 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 372 } 373 for (const auto &Ty : 374 {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) { 375 setAction({G_CONCAT_VECTORS, 1, Ty}, Legal); 376 setAction({G_UNMERGE_VALUES, Ty}, Legal); 377 } 378} 379 380void X86LegalizerInfo::setLegalizerInfoAVX2() { 381 if (!Subtarget.hasAVX2()) 382 return; 383 384 const LLT v32s8 = LLT::vector(32, 8); 385 const LLT v16s16 = LLT::vector(16, 16); 386 const LLT v8s32 = LLT::vector(8, 32); 387 const LLT v4s64 = LLT::vector(4, 64); 388 389 const LLT v64s8 = LLT::vector(64, 8); 390 const LLT v32s16 = LLT::vector(32, 16); 391 const LLT v16s32 = LLT::vector(16, 32); 392 const LLT v8s64 = LLT::vector(8, 64); 393 394 for (unsigned BinOp : {G_ADD, G_SUB}) 395 for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) 396 setAction({BinOp, Ty}, Legal); 397 398 for (auto Ty : {v16s16, v8s32}) 399 setAction({G_MUL, Ty}, Legal); 400 401 // Merge/Unmerge 402 for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) { 403 setAction({G_CONCAT_VECTORS, Ty}, Legal); 404 setAction({G_UNMERGE_VALUES, 1, Ty}, Legal); 405 } 406 for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) { 407 setAction({G_CONCAT_VECTORS, 1, Ty}, Legal); 408 setAction({G_UNMERGE_VALUES, Ty}, Legal); 409 } 410} 411 412void X86LegalizerInfo::setLegalizerInfoAVX512() { 413 if (!Subtarget.hasAVX512()) 414 return; 415 416 const LLT v16s8 = LLT::vector(16, 8); 417 const LLT v8s16 = LLT::vector(8, 16); 418 const LLT v4s32 = LLT::vector(4, 32); 419 const LLT v2s64 = LLT::vector(2, 64); 420 421 const LLT v32s8 = LLT::vector(32, 8); 422 const LLT v16s16 = LLT::vector(16, 16); 423 const LLT v8s32 = LLT::vector(8, 32); 424 const LLT v4s64 = LLT::vector(4, 64); 425 426 const LLT v64s8 = LLT::vector(64, 8); 427 const LLT v32s16 = LLT::vector(32, 16); 428 const LLT v16s32 = LLT::vector(16, 32); 429 const LLT v8s64 = LLT::vector(8, 64); 430 431 for (unsigned BinOp : {G_ADD, G_SUB}) 432 for (auto Ty : {v16s32, v8s64}) 433 setAction({BinOp, Ty}, Legal); 434 435 setAction({G_MUL, v16s32}, Legal); 436 437 for (unsigned MemOp : {G_LOAD, G_STORE}) 438 for (auto Ty : {v16s32, v8s64}) 439 setAction({MemOp, Ty}, Legal); 440 441 for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) { 442 setAction({G_INSERT, Ty}, Legal); 443 setAction({G_EXTRACT, 1, Ty}, Legal); 444 } 445 for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) { 446 setAction({G_INSERT, 1, Ty}, Legal); 447 setAction({G_EXTRACT, Ty}, Legal); 448 } 449 450 /************ VLX *******************/ 451 if (!Subtarget.hasVLX()) 452 return; 453 454 for (auto Ty : {v4s32, v8s32}) 455 setAction({G_MUL, Ty}, Legal); 456} 457 458void X86LegalizerInfo::setLegalizerInfoAVX512DQ() { 459 if (!(Subtarget.hasAVX512() && Subtarget.hasDQI())) 460 return; 461 462 const LLT v8s64 = LLT::vector(8, 64); 463 464 setAction({G_MUL, v8s64}, Legal); 465 466 /************ VLX *******************/ 467 if (!Subtarget.hasVLX()) 468 return; 469 470 const LLT v2s64 = LLT::vector(2, 64); 471 const LLT v4s64 = LLT::vector(4, 64); 472 473 for (auto Ty : {v2s64, v4s64}) 474 setAction({G_MUL, Ty}, Legal); 475} 476 477void X86LegalizerInfo::setLegalizerInfoAVX512BW() { 478 if (!(Subtarget.hasAVX512() && Subtarget.hasBWI())) 479 return; 480 481 const LLT v64s8 = LLT::vector(64, 8); 482 const LLT v32s16 = LLT::vector(32, 16); 483 484 for (unsigned BinOp : {G_ADD, G_SUB}) 485 for (auto Ty : {v64s8, v32s16}) 486 setAction({BinOp, Ty}, Legal); 487 488 setAction({G_MUL, v32s16}, Legal); 489 490 /************ VLX *******************/ 491 if (!Subtarget.hasVLX()) 492 return; 493 494 const LLT v8s16 = LLT::vector(8, 16); 495 const LLT v16s16 = LLT::vector(16, 16); 496 497 for (auto Ty : {v8s16, v16s16}) 498 setAction({G_MUL, Ty}, Legal); 499} 500