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/GlobalISel/Utils.h"
23 #include "llvm/CodeGen/MachineBasicBlock.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineInstr.h"
26 #include "llvm/CodeGen/MachineInstrBuilder.h"
27 #include "llvm/CodeGen/MachineOperand.h"
28 #include "llvm/CodeGen/MachineRegisterInfo.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/raw_ostream.h"
33 #define DEBUG_TYPE "X86-isel"
37 #ifndef LLVM_BUILD_GLOBAL_ISEL
38 #error "You shouldn't build this"
43 #define GET_GLOBALISEL_PREDICATE_BITSET
44 #include "X86GenGlobalISel.inc"
45 #undef GET_GLOBALISEL_PREDICATE_BITSET
47 class X86InstructionSelector : public InstructionSelector {
49 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
50 const X86RegisterBankInfo &RBI);
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 suported by Tablegen-erated instruction selection.
60 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
61 uint64_t Alignment) const;
63 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
64 MachineFunction &MF) const;
65 bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
66 MachineFunction &MF) const;
67 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
68 MachineFunction &MF) const;
69 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
70 MachineFunction &MF) const;
71 bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
72 MachineFunction &MF) const;
73 bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
74 MachineFunction &MF) const;
76 bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
77 MachineFunction &MF) const;
79 const X86TargetMachine &TM;
80 const X86Subtarget &STI;
81 const X86InstrInfo &TII;
82 const X86RegisterInfo &TRI;
83 const X86RegisterBankInfo &RBI;
85 #define GET_GLOBALISEL_PREDICATES_DECL
86 #include "X86GenGlobalISel.inc"
87 #undef GET_GLOBALISEL_PREDICATES_DECL
89 #define GET_GLOBALISEL_TEMPORARIES_DECL
90 #include "X86GenGlobalISel.inc"
91 #undef GET_GLOBALISEL_TEMPORARIES_DECL
94 } // end anonymous namespace
96 #define GET_GLOBALISEL_IMPL
97 #include "X86GenGlobalISel.inc"
98 #undef GET_GLOBALISEL_IMPL
100 X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
101 const X86Subtarget &STI,
102 const X86RegisterBankInfo &RBI)
103 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
104 TRI(*STI.getRegisterInfo()), RBI(RBI),
105 #define GET_GLOBALISEL_PREDICATES_INIT
106 #include "X86GenGlobalISel.inc"
107 #undef GET_GLOBALISEL_PREDICATES_INIT
108 #define GET_GLOBALISEL_TEMPORARIES_INIT
109 #include "X86GenGlobalISel.inc"
110 #undef GET_GLOBALISEL_TEMPORARIES_INIT
114 // FIXME: This should be target-independent, inferred from the types declared
115 // for each class in the bank.
116 static const TargetRegisterClass *
117 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
118 if (RB.getID() == X86::GPRRegBankID) {
119 if (Ty.getSizeInBits() <= 8)
120 return &X86::GR8RegClass;
121 if (Ty.getSizeInBits() == 16)
122 return &X86::GR16RegClass;
123 if (Ty.getSizeInBits() == 32)
124 return &X86::GR32RegClass;
125 if (Ty.getSizeInBits() == 64)
126 return &X86::GR64RegClass;
128 if (RB.getID() == X86::VECRRegBankID) {
129 if (Ty.getSizeInBits() == 32)
130 return &X86::FR32XRegClass;
131 if (Ty.getSizeInBits() == 64)
132 return &X86::FR64XRegClass;
133 if (Ty.getSizeInBits() == 128)
134 return &X86::VR128XRegClass;
135 if (Ty.getSizeInBits() == 256)
136 return &X86::VR256XRegClass;
137 if (Ty.getSizeInBits() == 512)
138 return &X86::VR512RegClass;
141 llvm_unreachable("Unknown RegBank!");
144 // Set X86 Opcode and constrain DestReg.
145 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
146 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
147 const RegisterBankInfo &RBI) {
149 unsigned DstReg = I.getOperand(0).getReg();
150 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
151 assert(I.isCopy() && "Generic operators do not allow physical registers");
155 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
156 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 // Change the physical register
177 if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
178 if (RC == &X86::GR32RegClass)
179 I.getOperand(1).setSubReg(X86::sub_32bit);
180 else if (RC == &X86::GR16RegClass)
181 I.getOperand(1).setSubReg(X86::sub_16bit);
182 else if (RC == &X86::GR8RegClass)
183 I.getOperand(1).setSubReg(X86::sub_8bit);
185 I.getOperand(1).substPhysReg(SrcReg, TRI);
188 case X86::VECRRegBankID:
189 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
192 llvm_unreachable("Unknown RegBank!");
195 // No need to constrain SrcReg. It will get constrained when
196 // we hit another of its use or its defs.
197 // Copies do not have constraints.
198 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
199 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
200 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
201 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
206 I.setDesc(TII.get(X86::COPY));
210 bool X86InstructionSelector::select(MachineInstr &I) const {
211 assert(I.getParent() && "Instruction should be in a basic block!");
212 assert(I.getParent()->getParent() && "Instruction should be in a function!");
214 MachineBasicBlock &MBB = *I.getParent();
215 MachineFunction &MF = *MBB.getParent();
216 MachineRegisterInfo &MRI = MF.getRegInfo();
218 unsigned Opcode = I.getOpcode();
219 if (!isPreISelGenericOpcode(Opcode)) {
220 // Certain non-generic instructions also need some special handling.
223 return selectCopy(I, TII, MRI, TRI, RBI);
225 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
229 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
230 "Generic instruction has unexpected implicit operands\n");
235 DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
237 // TODO: This should be implemented by tblgen.
238 if (selectLoadStoreOp(I, MRI, MF))
240 if (selectFrameIndexOrGep(I, MRI, MF))
242 if (selectConstant(I, MRI, MF))
244 if (selectTrunc(I, MRI, MF))
246 if (selectZext(I, MRI, MF))
248 if (selectCmp(I, MRI, MF))
250 if (selectUadde(I, MRI, MF))
256 unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
258 uint64_t Alignment) const {
259 bool Isload = (Opc == TargetOpcode::G_LOAD);
260 bool HasAVX = STI.hasAVX();
261 bool HasAVX512 = STI.hasAVX512();
262 bool HasVLX = STI.hasVLX();
264 if (Ty == LLT::scalar(8)) {
265 if (X86::GPRRegBankID == RB.getID())
266 return Isload ? X86::MOV8rm : X86::MOV8mr;
267 } else if (Ty == LLT::scalar(16)) {
268 if (X86::GPRRegBankID == RB.getID())
269 return Isload ? X86::MOV16rm : X86::MOV16mr;
270 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
271 if (X86::GPRRegBankID == RB.getID())
272 return Isload ? X86::MOV32rm : X86::MOV32mr;
273 if (X86::VECRRegBankID == RB.getID())
274 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
275 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
276 : (HasAVX512 ? X86::VMOVSSZmr
277 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
278 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
279 if (X86::GPRRegBankID == RB.getID())
280 return Isload ? X86::MOV64rm : X86::MOV64mr;
281 if (X86::VECRRegBankID == RB.getID())
282 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
283 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
284 : (HasAVX512 ? X86::VMOVSDZmr
285 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
286 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
288 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
290 ? X86::VMOVAPSZ128rm_NOVLX
291 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
292 : (HasVLX ? X86::VMOVAPSZ128mr
294 ? X86::VMOVAPSZ128mr_NOVLX
295 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
297 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
299 ? X86::VMOVUPSZ128rm_NOVLX
300 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
301 : (HasVLX ? X86::VMOVUPSZ128mr
303 ? X86::VMOVUPSZ128mr_NOVLX
304 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
309 bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
310 MachineRegisterInfo &MRI,
311 MachineFunction &MF) const {
313 unsigned Opc = I.getOpcode();
315 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
318 const unsigned DefReg = I.getOperand(0).getReg();
319 LLT Ty = MRI.getType(DefReg);
320 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
322 auto &MemOp = **I.memoperands_begin();
323 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
327 I.setDesc(TII.get(NewOpc));
328 MachineInstrBuilder MIB(MF, I);
329 if (Opc == TargetOpcode::G_LOAD)
332 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
334 addOffset(MIB, 0).addUse(DefReg);
336 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
339 bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
340 MachineRegisterInfo &MRI,
341 MachineFunction &MF) const {
342 unsigned Opc = I.getOpcode();
344 if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
347 const unsigned DefReg = I.getOperand(0).getReg();
348 LLT Ty = MRI.getType(DefReg);
350 // Use LEA to calculate frame index and GEP
352 if (Ty == LLT::pointer(0, 64))
353 NewOpc = X86::LEA64r;
354 else if (Ty == LLT::pointer(0, 32))
355 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
357 llvm_unreachable("Can't select G_FRAME_INDEX/G_GEP, unsupported type.");
359 I.setDesc(TII.get(NewOpc));
360 MachineInstrBuilder MIB(MF, I);
362 if (Opc == TargetOpcode::G_FRAME_INDEX) {
365 MachineOperand &InxOp = I.getOperand(2);
366 I.addOperand(InxOp); // set IndexReg
367 InxOp.ChangeToImmediate(1); // set Scale
368 MIB.addImm(0).addReg(0);
371 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
374 bool X86InstructionSelector::selectConstant(MachineInstr &I,
375 MachineRegisterInfo &MRI,
376 MachineFunction &MF) const {
377 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
380 const unsigned DefReg = I.getOperand(0).getReg();
381 LLT Ty = MRI.getType(DefReg);
383 assert(Ty.isScalar() && "invalid element type.");
386 if (I.getOperand(1).isCImm()) {
387 Val = I.getOperand(1).getCImm()->getZExtValue();
388 I.getOperand(1).ChangeToImmediate(Val);
389 } else if (I.getOperand(1).isImm()) {
390 Val = I.getOperand(1).getImm();
392 llvm_unreachable("Unsupported operand type.");
395 switch (Ty.getSizeInBits()) {
397 NewOpc = X86::MOV8ri;
400 NewOpc = X86::MOV16ri;
403 NewOpc = X86::MOV32ri;
406 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
408 NewOpc = X86::MOV64ri32;
410 NewOpc = X86::MOV64ri;
414 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
417 I.setDesc(TII.get(NewOpc));
418 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
421 bool X86InstructionSelector::selectTrunc(MachineInstr &I,
422 MachineRegisterInfo &MRI,
423 MachineFunction &MF) const {
424 if (I.getOpcode() != TargetOpcode::G_TRUNC)
427 const unsigned DstReg = I.getOperand(0).getReg();
428 const unsigned SrcReg = I.getOperand(1).getReg();
430 const LLT DstTy = MRI.getType(DstReg);
431 const LLT SrcTy = MRI.getType(SrcReg);
433 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
434 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
436 if (DstRB.getID() != SrcRB.getID()) {
437 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
441 if (DstRB.getID() != X86::GPRRegBankID)
444 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
448 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
453 if (DstRC == SrcRC) {
454 // Nothing to be done
455 SubIdx = X86::NoSubRegister;
456 } else if (DstRC == &X86::GR32RegClass) {
457 SubIdx = X86::sub_32bit;
458 } else if (DstRC == &X86::GR16RegClass) {
459 SubIdx = X86::sub_16bit;
460 } else if (DstRC == &X86::GR8RegClass) {
461 SubIdx = X86::sub_8bit;
466 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
468 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
469 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
470 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
474 I.getOperand(1).setSubReg(SubIdx);
476 I.setDesc(TII.get(X86::COPY));
480 bool X86InstructionSelector::selectZext(MachineInstr &I,
481 MachineRegisterInfo &MRI,
482 MachineFunction &MF) const {
483 if (I.getOpcode() != TargetOpcode::G_ZEXT)
486 const unsigned DstReg = I.getOperand(0).getReg();
487 const unsigned SrcReg = I.getOperand(1).getReg();
489 const LLT DstTy = MRI.getType(DstReg);
490 const LLT SrcTy = MRI.getType(SrcReg);
492 if (SrcTy == LLT::scalar(1)) {
495 if (DstTy == LLT::scalar(32))
496 AndOpc = X86::AND32ri8;
497 else if (DstTy == LLT::scalar(64))
498 AndOpc = X86::AND64ri8;
502 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
504 MRI.createVirtualRegister(getRegClassForTypeOnBank(DstTy, RegBank));
506 BuildMI(*I.getParent(), I, I.getDebugLoc(),
507 TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
510 .addImm(X86::sub_8bit);
512 MachineInstr &AndInst =
513 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
517 constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
526 bool X86InstructionSelector::selectCmp(MachineInstr &I,
527 MachineRegisterInfo &MRI,
528 MachineFunction &MF) const {
529 if (I.getOpcode() != TargetOpcode::G_ICMP)
534 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
535 (CmpInst::Predicate)I.getOperand(1).getPredicate());
536 unsigned OpSet = X86::getSETFromCond(CC);
538 unsigned LHS = I.getOperand(2).getReg();
539 unsigned RHS = I.getOperand(3).getReg();
545 LLT Ty = MRI.getType(LHS);
547 switch (Ty.getSizeInBits()) {
554 OpCmp = X86::CMP16rr;
557 OpCmp = X86::CMP32rr;
560 OpCmp = X86::CMP64rr;
564 MachineInstr &CmpInst =
565 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
569 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
570 TII.get(OpSet), I.getOperand(0).getReg());
572 constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
573 constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
579 bool X86InstructionSelector::selectUadde(MachineInstr &I,
580 MachineRegisterInfo &MRI,
581 MachineFunction &MF) const {
582 if (I.getOpcode() != TargetOpcode::G_UADDE)
585 const unsigned DstReg = I.getOperand(0).getReg();
586 const unsigned CarryOutReg = I.getOperand(1).getReg();
587 const unsigned Op0Reg = I.getOperand(2).getReg();
588 const unsigned Op1Reg = I.getOperand(3).getReg();
589 unsigned CarryInReg = I.getOperand(4).getReg();
591 const LLT DstTy = MRI.getType(DstReg);
593 if (DstTy != LLT::scalar(32))
596 // find CarryIn def instruction.
597 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
598 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
599 CarryInReg = Def->getOperand(1).getReg();
600 Def = MRI.getVRegDef(CarryInReg);
604 if (Def->getOpcode() == TargetOpcode::G_UADDE) {
605 // carry set by prev ADD.
607 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
610 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
613 Opcode = X86::ADC32rr;
614 } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
615 // carry is constant, support only 0.
619 Opcode = X86::ADD32rr;
623 MachineInstr &AddInst =
624 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
628 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
629 .addReg(X86::EFLAGS);
631 if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
632 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
639 InstructionSelector *
640 llvm::createX86InstructionSelector(const X86TargetMachine &TM,
641 X86Subtarget &Subtarget,
642 X86RegisterBankInfo &RBI) {
643 return new X86InstructionSelector(TM, Subtarget, RBI);