1 //===- X86InstructionSelector.cpp ----------------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This file implements the targeting of the InstructionSelector class for
12 /// \todo This should be generated by TableGen.
13 //===----------------------------------------------------------------------===//
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"
32 #define DEBUG_TYPE "X86-isel"
36 #ifndef LLVM_BUILD_GLOBAL_ISEL
37 #error "You shouldn't build this"
42 #define GET_GLOBALISEL_PREDICATE_BITSET
43 #include "X86GenGlobalISel.inc"
44 #undef GET_GLOBALISEL_PREDICATE_BITSET
46 class X86InstructionSelector : public InstructionSelector {
48 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
49 const X86RegisterBankInfo &RBI);
51 void beginFunction(const MachineFunction &MF) override;
52 bool select(MachineInstr &I) const override;
55 /// tblgen-erated 'select' implementation, used as the initial selector for
56 /// the patterns that don't require complex C++.
57 bool selectImpl(MachineInstr &I) const;
59 // TODO: remove after selectImpl support pattern with a predicate.
60 unsigned getFAddOp(LLT &Ty, const RegisterBank &RB) const;
61 unsigned getFSubOp(LLT &Ty, const RegisterBank &RB) const;
62 unsigned getAddOp(LLT &Ty, const RegisterBank &RB) const;
63 unsigned getSubOp(LLT &Ty, const RegisterBank &RB) const;
64 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
65 uint64_t Alignment) const;
67 bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI,
68 MachineFunction &MF) const;
69 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
70 MachineFunction &MF) const;
71 bool selectFrameIndex(MachineInstr &I, MachineRegisterInfo &MRI,
72 MachineFunction &MF) const;
73 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
74 MachineFunction &MF) const;
75 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
76 MachineFunction &MF) const;
78 const X86TargetMachine &TM;
79 const X86Subtarget &STI;
80 const X86InstrInfo &TII;
81 const X86RegisterInfo &TRI;
82 const X86RegisterBankInfo &RBI;
86 PredicateBitset AvailableFeatures;
87 PredicateBitset computeAvailableFeatures(const MachineFunction *MF,
88 const X86Subtarget *Subtarget) const;
90 #define GET_GLOBALISEL_TEMPORARIES_DECL
91 #include "X86GenGlobalISel.inc"
92 #undef GET_GLOBALISEL_TEMPORARIES_DECL
95 } // end anonymous namespace
97 #define GET_GLOBALISEL_IMPL
98 #include "X86GenGlobalISel.inc"
99 #undef GET_GLOBALISEL_IMPL
101 X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
102 const X86Subtarget &STI,
103 const X86RegisterBankInfo &RBI)
104 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
105 TRI(*STI.getRegisterInfo()), RBI(RBI), OptForSize(false),
106 OptForMinSize(false), AvailableFeatures()
107 #define GET_GLOBALISEL_TEMPORARIES_INIT
108 #include "X86GenGlobalISel.inc"
109 #undef GET_GLOBALISEL_TEMPORARIES_INIT
113 // FIXME: This should be target-independent, inferred from the types declared
114 // for each class in the bank.
115 static const TargetRegisterClass *
116 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
117 if (RB.getID() == X86::GPRRegBankID) {
118 if (Ty.getSizeInBits() <= 8)
119 return &X86::GR8RegClass;
120 if (Ty.getSizeInBits() == 16)
121 return &X86::GR16RegClass;
122 if (Ty.getSizeInBits() == 32)
123 return &X86::GR32RegClass;
124 if (Ty.getSizeInBits() == 64)
125 return &X86::GR64RegClass;
127 if (RB.getID() == X86::VECRRegBankID) {
128 if (Ty.getSizeInBits() == 32)
129 return &X86::FR32XRegClass;
130 if (Ty.getSizeInBits() == 64)
131 return &X86::FR64XRegClass;
132 if (Ty.getSizeInBits() == 128)
133 return &X86::VR128XRegClass;
134 if (Ty.getSizeInBits() == 256)
135 return &X86::VR256XRegClass;
136 if (Ty.getSizeInBits() == 512)
137 return &X86::VR512RegClass;
140 llvm_unreachable("Unknown RegBank!");
143 // Set X86 Opcode and constrain DestReg.
144 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
145 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
146 const RegisterBankInfo &RBI) {
148 unsigned DstReg = I.getOperand(0).getReg();
149 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
150 assert(I.isCopy() && "Generic operators do not allow physical registers");
154 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
155 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
157 unsigned SrcReg = I.getOperand(1).getReg();
158 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
160 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
161 "No phys reg on generic operators");
162 assert((DstSize == SrcSize ||
163 // Copies are a mean to setup initial types, the number of
164 // bits may not exactly match.
165 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
166 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
167 "Copy with different width?!");
169 const TargetRegisterClass *RC = nullptr;
171 switch (RegBank.getID()) {
172 case X86::GPRRegBankID:
173 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
174 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
176 case X86::VECRRegBankID:
177 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
180 llvm_unreachable("Unknown RegBank!");
183 // No need to constrain SrcReg. It will get constrained when
184 // we hit another of its use or its defs.
185 // Copies do not have constraints.
186 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
187 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
188 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
189 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
194 I.setDesc(TII.get(X86::COPY));
198 void X86InstructionSelector::beginFunction(const MachineFunction &MF) {
199 OptForSize = MF.getFunction()->optForSize();
200 OptForMinSize = MF.getFunction()->optForMinSize();
201 AvailableFeatures = computeAvailableFeatures(&MF, &STI);
204 bool X86InstructionSelector::select(MachineInstr &I) const {
205 assert(I.getParent() && "Instruction should be in a basic block!");
206 assert(I.getParent()->getParent() && "Instruction should be in a function!");
208 MachineBasicBlock &MBB = *I.getParent();
209 MachineFunction &MF = *MBB.getParent();
210 MachineRegisterInfo &MRI = MF.getRegInfo();
212 unsigned Opcode = I.getOpcode();
213 if (!isPreISelGenericOpcode(Opcode)) {
214 // Certain non-generic instructions also need some special handling.
217 return selectCopy(I, TII, MRI, TRI, RBI);
219 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
223 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
224 "Generic instruction has unexpected implicit operands\n");
226 // TODO: This should be implemented by tblgen, pattern with predicate not
228 if (selectBinaryOp(I, MRI, MF))
230 if (selectLoadStoreOp(I, MRI, MF))
232 if (selectFrameIndex(I, MRI, MF))
234 if (selectConstant(I, MRI, MF))
236 if (selectTrunc(I, MRI, MF))
239 return selectImpl(I);
242 unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
243 const RegisterBank &RB) const {
245 if (X86::VECRRegBankID != RB.getID())
246 return TargetOpcode::G_FADD;
248 if (Ty == LLT::scalar(32)) {
249 if (STI.hasAVX512()) {
250 return X86::VADDSSZrr;
251 } else if (STI.hasAVX()) {
252 return X86::VADDSSrr;
253 } else if (STI.hasSSE1()) {
256 } else if (Ty == LLT::scalar(64)) {
257 if (STI.hasAVX512()) {
258 return X86::VADDSDZrr;
259 } else if (STI.hasAVX()) {
260 return X86::VADDSDrr;
261 } else if (STI.hasSSE2()) {
264 } else if (Ty == LLT::vector(4, 32)) {
265 if ((STI.hasAVX512()) && (STI.hasVLX())) {
266 return X86::VADDPSZ128rr;
267 } else if (STI.hasAVX()) {
268 return X86::VADDPSrr;
269 } else if (STI.hasSSE1()) {
274 return TargetOpcode::G_FADD;
277 unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
278 const RegisterBank &RB) const {
280 if (X86::VECRRegBankID != RB.getID())
281 return TargetOpcode::G_FSUB;
283 if (Ty == LLT::scalar(32)) {
284 if (STI.hasAVX512()) {
285 return X86::VSUBSSZrr;
286 } else if (STI.hasAVX()) {
287 return X86::VSUBSSrr;
288 } else if (STI.hasSSE1()) {
291 } else if (Ty == LLT::scalar(64)) {
292 if (STI.hasAVX512()) {
293 return X86::VSUBSDZrr;
294 } else if (STI.hasAVX()) {
295 return X86::VSUBSDrr;
296 } else if (STI.hasSSE2()) {
299 } else if (Ty == LLT::vector(4, 32)) {
300 if ((STI.hasAVX512()) && (STI.hasVLX())) {
301 return X86::VSUBPSZ128rr;
302 } else if (STI.hasAVX()) {
303 return X86::VSUBPSrr;
304 } else if (STI.hasSSE1()) {
309 return TargetOpcode::G_FSUB;
312 unsigned X86InstructionSelector::getAddOp(LLT &Ty,
313 const RegisterBank &RB) const {
315 if (X86::VECRRegBankID != RB.getID())
316 return TargetOpcode::G_ADD;
318 if (Ty == LLT::vector(4, 32)) {
319 if (STI.hasAVX512() && STI.hasVLX()) {
320 return X86::VPADDDZ128rr;
321 } else if (STI.hasAVX()) {
322 return X86::VPADDDrr;
323 } else if (STI.hasSSE2()) {
328 return TargetOpcode::G_ADD;
331 unsigned X86InstructionSelector::getSubOp(LLT &Ty,
332 const RegisterBank &RB) const {
334 if (X86::VECRRegBankID != RB.getID())
335 return TargetOpcode::G_SUB;
337 if (Ty == LLT::vector(4, 32)) {
338 if (STI.hasAVX512() && STI.hasVLX()) {
339 return X86::VPSUBDZ128rr;
340 } else if (STI.hasAVX()) {
341 return X86::VPSUBDrr;
342 } else if (STI.hasSSE2()) {
347 return TargetOpcode::G_SUB;
350 bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
351 MachineRegisterInfo &MRI,
352 MachineFunction &MF) const {
354 const unsigned DefReg = I.getOperand(0).getReg();
355 LLT Ty = MRI.getType(DefReg);
356 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
358 unsigned NewOpc = I.getOpcode();
361 case TargetOpcode::G_FADD:
362 NewOpc = getFAddOp(Ty, RB);
364 case TargetOpcode::G_FSUB:
365 NewOpc = getFSubOp(Ty, RB);
367 case TargetOpcode::G_ADD:
368 NewOpc = getAddOp(Ty, RB);
370 case TargetOpcode::G_SUB:
371 NewOpc = getSubOp(Ty, RB);
377 if (NewOpc == I.getOpcode())
380 I.setDesc(TII.get(NewOpc));
382 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
385 unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
387 uint64_t Alignment) const {
388 bool Isload = (Opc == TargetOpcode::G_LOAD);
389 bool HasAVX = STI.hasAVX();
390 bool HasAVX512 = STI.hasAVX512();
391 bool HasVLX = STI.hasVLX();
393 if (Ty == LLT::scalar(8)) {
394 if (X86::GPRRegBankID == RB.getID())
395 return Isload ? X86::MOV8rm : X86::MOV8mr;
396 } else if (Ty == LLT::scalar(16)) {
397 if (X86::GPRRegBankID == RB.getID())
398 return Isload ? X86::MOV16rm : X86::MOV16mr;
399 } else if (Ty == LLT::scalar(32)) {
400 if (X86::GPRRegBankID == RB.getID())
401 return Isload ? X86::MOV32rm : X86::MOV32mr;
402 if (X86::VECRRegBankID == RB.getID())
403 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
404 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
405 : (HasAVX512 ? X86::VMOVSSZmr
406 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
407 } else if (Ty == LLT::scalar(64)) {
408 if (X86::GPRRegBankID == RB.getID())
409 return Isload ? X86::MOV64rm : X86::MOV64mr;
410 if (X86::VECRRegBankID == RB.getID())
411 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
412 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
413 : (HasAVX512 ? X86::VMOVSDZmr
414 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
415 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
417 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
419 ? X86::VMOVAPSZ128rm_NOVLX
420 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
421 : (HasVLX ? X86::VMOVAPSZ128mr
423 ? X86::VMOVAPSZ128mr_NOVLX
424 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
426 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
428 ? X86::VMOVUPSZ128rm_NOVLX
429 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
430 : (HasVLX ? X86::VMOVUPSZ128mr
432 ? X86::VMOVUPSZ128mr_NOVLX
433 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
438 bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
439 MachineRegisterInfo &MRI,
440 MachineFunction &MF) const {
442 unsigned Opc = I.getOpcode();
444 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
447 const unsigned DefReg = I.getOperand(0).getReg();
448 LLT Ty = MRI.getType(DefReg);
449 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
451 auto &MemOp = **I.memoperands_begin();
452 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
456 I.setDesc(TII.get(NewOpc));
457 MachineInstrBuilder MIB(MF, I);
458 if (Opc == TargetOpcode::G_LOAD)
461 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
463 addOffset(MIB, 0).addUse(DefReg);
465 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
468 bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
469 MachineRegisterInfo &MRI,
470 MachineFunction &MF) const {
471 if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX)
474 const unsigned DefReg = I.getOperand(0).getReg();
475 LLT Ty = MRI.getType(DefReg);
477 // Use LEA to calculate frame index.
479 if (Ty == LLT::pointer(0, 64))
480 NewOpc = X86::LEA64r;
481 else if (Ty == LLT::pointer(0, 32))
482 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
484 llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type.");
486 I.setDesc(TII.get(NewOpc));
487 MachineInstrBuilder MIB(MF, I);
490 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
493 bool X86InstructionSelector::selectConstant(MachineInstr &I,
494 MachineRegisterInfo &MRI,
495 MachineFunction &MF) const {
496 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
499 const unsigned DefReg = I.getOperand(0).getReg();
500 LLT Ty = MRI.getType(DefReg);
502 assert(Ty.isScalar() && "invalid element type.");
505 if (I.getOperand(1).isCImm()) {
506 Val = I.getOperand(1).getCImm()->getZExtValue();
507 I.getOperand(1).ChangeToImmediate(Val);
508 } else if (I.getOperand(1).isImm()) {
509 Val = I.getOperand(1).getImm();
511 llvm_unreachable("Unsupported operand type.");
514 switch (Ty.getSizeInBits()) {
516 NewOpc = X86::MOV8ri;
519 NewOpc = X86::MOV16ri;
522 NewOpc = X86::MOV32ri;
525 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
527 NewOpc = X86::MOV64ri32;
529 NewOpc = X86::MOV64ri;
533 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
536 I.setDesc(TII.get(NewOpc));
537 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
540 bool X86InstructionSelector::selectTrunc(MachineInstr &I,
541 MachineRegisterInfo &MRI,
542 MachineFunction &MF) const {
543 if (I.getOpcode() != TargetOpcode::G_TRUNC)
546 const unsigned DstReg = I.getOperand(0).getReg();
547 const unsigned SrcReg = I.getOperand(1).getReg();
549 const LLT DstTy = MRI.getType(DstReg);
550 const LLT SrcTy = MRI.getType(SrcReg);
552 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
553 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
555 if (DstRB.getID() != SrcRB.getID()) {
556 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
560 if (DstRB.getID() != X86::GPRRegBankID)
563 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
567 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
571 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
572 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
573 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
577 if (DstRC == SrcRC) {
578 // Nothing to be done
579 } else if (DstRC == &X86::GR32RegClass) {
580 I.getOperand(1).setSubReg(X86::sub_32bit);
581 } else if (DstRC == &X86::GR16RegClass) {
582 I.getOperand(1).setSubReg(X86::sub_16bit);
583 } else if (DstRC == &X86::GR8RegClass) {
584 I.getOperand(1).setSubReg(X86::sub_8bit);
589 I.setDesc(TII.get(X86::COPY));
593 InstructionSelector *
594 llvm::createX86InstructionSelector(const X86TargetMachine &TM,
595 X86Subtarget &Subtarget,
596 X86RegisterBankInfo &RBI) {
597 return new X86InstructionSelector(TM, Subtarget, RBI);