1 //===- X86InstructionSelector.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 InstructionSelector class for 11 /// X86. 12 /// \todo This should be generated by TableGen. 13 //===----------------------------------------------------------------------===// 14 15 #include "X86InstrBuilder.h" 16 #include "X86InstrInfo.h" 17 #include "X86RegisterBankInfo.h" 18 #include "X86RegisterInfo.h" 19 #include "X86Subtarget.h" 20 #include "X86TargetMachine.h" 21 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 22 #include "llvm/CodeGen/MachineBasicBlock.h" 23 #include "llvm/CodeGen/MachineFunction.h" 24 #include "llvm/CodeGen/MachineInstr.h" 25 #include "llvm/CodeGen/MachineInstrBuilder.h" 26 #include "llvm/CodeGen/MachineOperand.h" 27 #include "llvm/CodeGen/MachineRegisterInfo.h" 28 #include "llvm/IR/Type.h" 29 #include "llvm/Support/Debug.h" 30 #include "llvm/Support/raw_ostream.h" 31 32 #define DEBUG_TYPE "X86-isel" 33 34 using namespace llvm; 35 36 #ifndef LLVM_BUILD_GLOBAL_ISEL 37 #error "You shouldn't build this" 38 #endif 39 40 namespace { 41 42 class X86InstructionSelector : public InstructionSelector { 43 public: 44 X86InstructionSelector(const X86Subtarget &STI, 45 const X86RegisterBankInfo &RBI); 46 47 bool select(MachineInstr &I) const override; 48 49 private: 50 /// tblgen-erated 'select' implementation, used as the initial selector for 51 /// the patterns that don't require complex C++. 52 bool selectImpl(MachineInstr &I) const; 53 54 // TODO: remove after selectImpl support pattern with a predicate. 55 unsigned getFAddOp(LLT &Ty, const RegisterBank &RB) const; 56 unsigned getFSubOp(LLT &Ty, const RegisterBank &RB) const; 57 unsigned getAddOp(LLT &Ty, const RegisterBank &RB) const; 58 unsigned getSubOp(LLT &Ty, const RegisterBank &RB) const; 59 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc, 60 uint64_t Alignment) const; 61 62 bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI, 63 MachineFunction &MF) const; 64 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI, 65 MachineFunction &MF) const; 66 bool selectFrameIndex(MachineInstr &I, MachineRegisterInfo &MRI, 67 MachineFunction &MF) const; 68 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI, 69 MachineFunction &MF) const; 70 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI, 71 MachineFunction &MF) const; 72 73 const X86Subtarget &STI; 74 const X86InstrInfo &TII; 75 const X86RegisterInfo &TRI; 76 const X86RegisterBankInfo &RBI; 77 78 #define GET_GLOBALISEL_TEMPORARIES_DECL 79 #include "X86GenGlobalISel.inc" 80 #undef GET_GLOBALISEL_TEMPORARIES_DECL 81 }; 82 83 } // end anonymous namespace 84 85 #define GET_GLOBALISEL_IMPL 86 #include "X86GenGlobalISel.inc" 87 #undef GET_GLOBALISEL_IMPL 88 89 X86InstructionSelector::X86InstructionSelector(const X86Subtarget &STI, 90 const X86RegisterBankInfo &RBI) 91 : InstructionSelector(), STI(STI), TII(*STI.getInstrInfo()), 92 TRI(*STI.getRegisterInfo()), RBI(RBI) 93 #define GET_GLOBALISEL_TEMPORARIES_INIT 94 #include "X86GenGlobalISel.inc" 95 #undef GET_GLOBALISEL_TEMPORARIES_INIT 96 { 97 } 98 99 // FIXME: This should be target-independent, inferred from the types declared 100 // for each class in the bank. 101 static const TargetRegisterClass * 102 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) { 103 if (RB.getID() == X86::GPRRegBankID) { 104 if (Ty.getSizeInBits() <= 8) 105 return &X86::GR8RegClass; 106 if (Ty.getSizeInBits() == 16) 107 return &X86::GR16RegClass; 108 if (Ty.getSizeInBits() == 32) 109 return &X86::GR32RegClass; 110 if (Ty.getSizeInBits() == 64) 111 return &X86::GR64RegClass; 112 } 113 if (RB.getID() == X86::VECRRegBankID) { 114 if (Ty.getSizeInBits() == 32) 115 return &X86::FR32XRegClass; 116 if (Ty.getSizeInBits() == 64) 117 return &X86::FR64XRegClass; 118 if (Ty.getSizeInBits() == 128) 119 return &X86::VR128XRegClass; 120 if (Ty.getSizeInBits() == 256) 121 return &X86::VR256XRegClass; 122 if (Ty.getSizeInBits() == 512) 123 return &X86::VR512RegClass; 124 } 125 126 llvm_unreachable("Unknown RegBank!"); 127 } 128 129 // Set X86 Opcode and constrain DestReg. 130 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, 131 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 132 const RegisterBankInfo &RBI) { 133 134 unsigned DstReg = I.getOperand(0).getReg(); 135 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) { 136 assert(I.isCopy() && "Generic operators do not allow physical registers"); 137 return true; 138 } 139 140 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI); 141 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); 142 (void)DstSize; 143 unsigned SrcReg = I.getOperand(1).getReg(); 144 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI); 145 (void)SrcSize; 146 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) && 147 "No phys reg on generic operators"); 148 assert((DstSize == SrcSize || 149 // Copies are a mean to setup initial types, the number of 150 // bits may not exactly match. 151 (TargetRegisterInfo::isPhysicalRegister(SrcReg) && 152 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) && 153 "Copy with different width?!"); 154 155 const TargetRegisterClass *RC = nullptr; 156 157 switch (RegBank.getID()) { 158 case X86::GPRRegBankID: 159 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values."); 160 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank); 161 break; 162 case X86::VECRRegBankID: 163 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank); 164 break; 165 default: 166 llvm_unreachable("Unknown RegBank!"); 167 } 168 169 // No need to constrain SrcReg. It will get constrained when 170 // we hit another of its use or its defs. 171 // Copies do not have constraints. 172 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg); 173 if (!OldRC || !RC->hasSubClassEq(OldRC)) { 174 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 175 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 176 << " operand\n"); 177 return false; 178 } 179 } 180 I.setDesc(TII.get(X86::COPY)); 181 return true; 182 } 183 184 bool X86InstructionSelector::select(MachineInstr &I) const { 185 assert(I.getParent() && "Instruction should be in a basic block!"); 186 assert(I.getParent()->getParent() && "Instruction should be in a function!"); 187 188 MachineBasicBlock &MBB = *I.getParent(); 189 MachineFunction &MF = *MBB.getParent(); 190 MachineRegisterInfo &MRI = MF.getRegInfo(); 191 192 unsigned Opcode = I.getOpcode(); 193 if (!isPreISelGenericOpcode(Opcode)) { 194 // Certain non-generic instructions also need some special handling. 195 196 if (I.isCopy()) 197 return selectCopy(I, TII, MRI, TRI, RBI); 198 199 // TODO: handle more cases - LOAD_STACK_GUARD, PHI 200 return true; 201 } 202 203 assert(I.getNumOperands() == I.getNumExplicitOperands() && 204 "Generic instruction has unexpected implicit operands\n"); 205 206 // TODO: This should be implemented by tblgen, pattern with predicate not 207 // supported yet. 208 if (selectBinaryOp(I, MRI, MF)) 209 return true; 210 if (selectLoadStoreOp(I, MRI, MF)) 211 return true; 212 if (selectFrameIndex(I, MRI, MF)) 213 return true; 214 if (selectConstant(I, MRI, MF)) 215 return true; 216 if (selectTrunc(I, MRI, MF)) 217 return true; 218 219 return selectImpl(I); 220 } 221 222 unsigned X86InstructionSelector::getFAddOp(LLT &Ty, 223 const RegisterBank &RB) const { 224 225 if (X86::VECRRegBankID != RB.getID()) 226 return TargetOpcode::G_FADD; 227 228 if (Ty == LLT::scalar(32)) { 229 if (STI.hasAVX512()) { 230 return X86::VADDSSZrr; 231 } else if (STI.hasAVX()) { 232 return X86::VADDSSrr; 233 } else if (STI.hasSSE1()) { 234 return X86::ADDSSrr; 235 } 236 } else if (Ty == LLT::scalar(64)) { 237 if (STI.hasAVX512()) { 238 return X86::VADDSDZrr; 239 } else if (STI.hasAVX()) { 240 return X86::VADDSDrr; 241 } else if (STI.hasSSE2()) { 242 return X86::ADDSDrr; 243 } 244 } else if (Ty == LLT::vector(4, 32)) { 245 if ((STI.hasAVX512()) && (STI.hasVLX())) { 246 return X86::VADDPSZ128rr; 247 } else if (STI.hasAVX()) { 248 return X86::VADDPSrr; 249 } else if (STI.hasSSE1()) { 250 return X86::ADDPSrr; 251 } 252 } 253 254 return TargetOpcode::G_FADD; 255 } 256 257 unsigned X86InstructionSelector::getFSubOp(LLT &Ty, 258 const RegisterBank &RB) const { 259 260 if (X86::VECRRegBankID != RB.getID()) 261 return TargetOpcode::G_FSUB; 262 263 if (Ty == LLT::scalar(32)) { 264 if (STI.hasAVX512()) { 265 return X86::VSUBSSZrr; 266 } else if (STI.hasAVX()) { 267 return X86::VSUBSSrr; 268 } else if (STI.hasSSE1()) { 269 return X86::SUBSSrr; 270 } 271 } else if (Ty == LLT::scalar(64)) { 272 if (STI.hasAVX512()) { 273 return X86::VSUBSDZrr; 274 } else if (STI.hasAVX()) { 275 return X86::VSUBSDrr; 276 } else if (STI.hasSSE2()) { 277 return X86::SUBSDrr; 278 } 279 } else if (Ty == LLT::vector(4, 32)) { 280 if ((STI.hasAVX512()) && (STI.hasVLX())) { 281 return X86::VSUBPSZ128rr; 282 } else if (STI.hasAVX()) { 283 return X86::VSUBPSrr; 284 } else if (STI.hasSSE1()) { 285 return X86::SUBPSrr; 286 } 287 } 288 289 return TargetOpcode::G_FSUB; 290 } 291 292 unsigned X86InstructionSelector::getAddOp(LLT &Ty, 293 const RegisterBank &RB) const { 294 295 if (X86::VECRRegBankID != RB.getID()) 296 return TargetOpcode::G_ADD; 297 298 if (Ty == LLT::vector(4, 32)) { 299 if (STI.hasAVX512() && STI.hasVLX()) { 300 return X86::VPADDDZ128rr; 301 } else if (STI.hasAVX()) { 302 return X86::VPADDDrr; 303 } else if (STI.hasSSE2()) { 304 return X86::PADDDrr; 305 } 306 } 307 308 return TargetOpcode::G_ADD; 309 } 310 311 unsigned X86InstructionSelector::getSubOp(LLT &Ty, 312 const RegisterBank &RB) const { 313 314 if (X86::VECRRegBankID != RB.getID()) 315 return TargetOpcode::G_SUB; 316 317 if (Ty == LLT::vector(4, 32)) { 318 if (STI.hasAVX512() && STI.hasVLX()) { 319 return X86::VPSUBDZ128rr; 320 } else if (STI.hasAVX()) { 321 return X86::VPSUBDrr; 322 } else if (STI.hasSSE2()) { 323 return X86::PSUBDrr; 324 } 325 } 326 327 return TargetOpcode::G_SUB; 328 } 329 330 bool X86InstructionSelector::selectBinaryOp(MachineInstr &I, 331 MachineRegisterInfo &MRI, 332 MachineFunction &MF) const { 333 334 const unsigned DefReg = I.getOperand(0).getReg(); 335 LLT Ty = MRI.getType(DefReg); 336 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI); 337 338 unsigned NewOpc = I.getOpcode(); 339 340 switch (NewOpc) { 341 case TargetOpcode::G_FADD: 342 NewOpc = getFAddOp(Ty, RB); 343 break; 344 case TargetOpcode::G_FSUB: 345 NewOpc = getFSubOp(Ty, RB); 346 break; 347 case TargetOpcode::G_ADD: 348 NewOpc = getAddOp(Ty, RB); 349 break; 350 case TargetOpcode::G_SUB: 351 NewOpc = getSubOp(Ty, RB); 352 break; 353 default: 354 break; 355 } 356 357 if (NewOpc == I.getOpcode()) 358 return false; 359 360 I.setDesc(TII.get(NewOpc)); 361 362 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 363 } 364 365 unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB, 366 unsigned Opc, 367 uint64_t Alignment) const { 368 bool Isload = (Opc == TargetOpcode::G_LOAD); 369 bool HasAVX = STI.hasAVX(); 370 bool HasAVX512 = STI.hasAVX512(); 371 bool HasVLX = STI.hasVLX(); 372 373 if (Ty == LLT::scalar(8)) { 374 if (X86::GPRRegBankID == RB.getID()) 375 return Isload ? X86::MOV8rm : X86::MOV8mr; 376 } else if (Ty == LLT::scalar(16)) { 377 if (X86::GPRRegBankID == RB.getID()) 378 return Isload ? X86::MOV16rm : X86::MOV16mr; 379 } else if (Ty == LLT::scalar(32)) { 380 if (X86::GPRRegBankID == RB.getID()) 381 return Isload ? X86::MOV32rm : X86::MOV32mr; 382 if (X86::VECRRegBankID == RB.getID()) 383 return Isload ? (HasAVX512 ? X86::VMOVSSZrm 384 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm) 385 : (HasAVX512 ? X86::VMOVSSZmr 386 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr); 387 } else if (Ty == LLT::scalar(64)) { 388 if (X86::GPRRegBankID == RB.getID()) 389 return Isload ? X86::MOV64rm : X86::MOV64mr; 390 if (X86::VECRRegBankID == RB.getID()) 391 return Isload ? (HasAVX512 ? X86::VMOVSDZrm 392 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm) 393 : (HasAVX512 ? X86::VMOVSDZmr 394 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr); 395 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) { 396 if (Alignment >= 16) 397 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm 398 : HasAVX512 399 ? X86::VMOVAPSZ128rm_NOVLX 400 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm) 401 : (HasVLX ? X86::VMOVAPSZ128mr 402 : HasAVX512 403 ? X86::VMOVAPSZ128mr_NOVLX 404 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr); 405 else 406 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm 407 : HasAVX512 408 ? X86::VMOVUPSZ128rm_NOVLX 409 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm) 410 : (HasVLX ? X86::VMOVUPSZ128mr 411 : HasAVX512 412 ? X86::VMOVUPSZ128mr_NOVLX 413 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr); 414 } 415 return Opc; 416 } 417 418 bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I, 419 MachineRegisterInfo &MRI, 420 MachineFunction &MF) const { 421 422 unsigned Opc = I.getOpcode(); 423 424 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD) 425 return false; 426 427 const unsigned DefReg = I.getOperand(0).getReg(); 428 LLT Ty = MRI.getType(DefReg); 429 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI); 430 431 auto &MemOp = **I.memoperands_begin(); 432 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment()); 433 if (NewOpc == Opc) 434 return false; 435 436 I.setDesc(TII.get(NewOpc)); 437 MachineInstrBuilder MIB(MF, I); 438 if (Opc == TargetOpcode::G_LOAD) 439 addOffset(MIB, 0); 440 else { 441 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL) 442 I.RemoveOperand(0); 443 addOffset(MIB, 0).addUse(DefReg); 444 } 445 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 446 } 447 448 bool X86InstructionSelector::selectFrameIndex(MachineInstr &I, 449 MachineRegisterInfo &MRI, 450 MachineFunction &MF) const { 451 if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX) 452 return false; 453 454 const unsigned DefReg = I.getOperand(0).getReg(); 455 LLT Ty = MRI.getType(DefReg); 456 457 // Use LEA to calculate frame index. 458 unsigned NewOpc; 459 if (Ty == LLT::pointer(0, 64)) 460 NewOpc = X86::LEA64r; 461 else if (Ty == LLT::pointer(0, 32)) 462 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r; 463 else 464 llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type."); 465 466 I.setDesc(TII.get(NewOpc)); 467 MachineInstrBuilder MIB(MF, I); 468 addOffset(MIB, 0); 469 470 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 471 } 472 473 bool X86InstructionSelector::selectConstant(MachineInstr &I, 474 MachineRegisterInfo &MRI, 475 MachineFunction &MF) const { 476 if (I.getOpcode() != TargetOpcode::G_CONSTANT) 477 return false; 478 479 const unsigned DefReg = I.getOperand(0).getReg(); 480 LLT Ty = MRI.getType(DefReg); 481 482 assert(Ty.isScalar() && "invalid element type."); 483 484 uint64_t Val = 0; 485 if (I.getOperand(1).isCImm()) { 486 Val = I.getOperand(1).getCImm()->getZExtValue(); 487 I.getOperand(1).ChangeToImmediate(Val); 488 } else if (I.getOperand(1).isImm()) { 489 Val = I.getOperand(1).getImm(); 490 } else 491 llvm_unreachable("Unsupported operand type."); 492 493 unsigned NewOpc; 494 switch (Ty.getSizeInBits()) { 495 case 8: 496 NewOpc = X86::MOV8ri; 497 break; 498 case 16: 499 NewOpc = X86::MOV16ri; 500 break; 501 case 32: 502 NewOpc = X86::MOV32ri; 503 break; 504 case 64: { 505 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used 506 if (isInt<32>(Val)) 507 NewOpc = X86::MOV64ri32; 508 else 509 NewOpc = X86::MOV64ri; 510 break; 511 } 512 default: 513 llvm_unreachable("Can't select G_CONSTANT, unsupported type."); 514 } 515 516 I.setDesc(TII.get(NewOpc)); 517 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 518 } 519 520 bool X86InstructionSelector::selectTrunc(MachineInstr &I, 521 MachineRegisterInfo &MRI, 522 MachineFunction &MF) const { 523 if (I.getOpcode() != TargetOpcode::G_TRUNC) 524 return false; 525 526 const unsigned DstReg = I.getOperand(0).getReg(); 527 const unsigned SrcReg = I.getOperand(1).getReg(); 528 529 const LLT DstTy = MRI.getType(DstReg); 530 const LLT SrcTy = MRI.getType(SrcReg); 531 532 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI); 533 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI); 534 535 if (DstRB.getID() != SrcRB.getID()) { 536 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n"); 537 return false; 538 } 539 540 if (DstRB.getID() != X86::GPRRegBankID) 541 return false; 542 543 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB); 544 if (!DstRC) 545 return false; 546 547 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB); 548 if (!SrcRC) 549 return false; 550 551 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) || 552 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) { 553 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n"); 554 return false; 555 } 556 557 if (DstRC == SrcRC) { 558 // Nothing to be done 559 } else if (DstRC == &X86::GR32RegClass) { 560 I.getOperand(1).setSubReg(X86::sub_32bit); 561 } else if (DstRC == &X86::GR16RegClass) { 562 I.getOperand(1).setSubReg(X86::sub_16bit); 563 } else if (DstRC == &X86::GR8RegClass) { 564 I.getOperand(1).setSubReg(X86::sub_8bit); 565 } else { 566 return false; 567 } 568 569 I.setDesc(TII.get(X86::COPY)); 570 return true; 571 } 572 573 InstructionSelector * 574 llvm::createX86InstructionSelector(X86Subtarget &Subtarget, 575 X86RegisterBankInfo &RBI) { 576 return new X86InstructionSelector(Subtarget, RBI); 577 } 578