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 bool select(MachineInstr &I) const override;
54 /// tblgen-erated 'select' implementation, used as the initial selector for
55 /// the patterns that don't require complex C++.
56 bool selectImpl(MachineInstr &I) const;
58 // TODO: remove after suported by Tablegen-erated instruction selection.
59 unsigned getFAddOp(LLT &Ty, const RegisterBank &RB) const;
60 unsigned getFSubOp(LLT &Ty, const RegisterBank &RB) const;
61 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
62 uint64_t Alignment) const;
64 bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI,
65 MachineFunction &MF) const;
66 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
67 MachineFunction &MF) const;
68 bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
69 MachineFunction &MF) const;
70 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
71 MachineFunction &MF) const;
72 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
73 MachineFunction &MF) const;
75 const X86TargetMachine &TM;
76 const X86Subtarget &STI;
77 const X86InstrInfo &TII;
78 const X86RegisterInfo &TRI;
79 const X86RegisterBankInfo &RBI;
81 #define GET_GLOBALISEL_PREDICATES_DECL
82 #include "X86GenGlobalISel.inc"
83 #undef GET_GLOBALISEL_PREDICATES_DECL
85 #define GET_GLOBALISEL_TEMPORARIES_DECL
86 #include "X86GenGlobalISel.inc"
87 #undef GET_GLOBALISEL_TEMPORARIES_DECL
90 } // end anonymous namespace
92 #define GET_GLOBALISEL_IMPL
93 #include "X86GenGlobalISel.inc"
94 #undef GET_GLOBALISEL_IMPL
96 X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
97 const X86Subtarget &STI,
98 const X86RegisterBankInfo &RBI)
99 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
100 TRI(*STI.getRegisterInfo()), RBI(RBI),
101 #define GET_GLOBALISEL_PREDICATES_INIT
102 #include "X86GenGlobalISel.inc"
103 #undef GET_GLOBALISEL_PREDICATES_INIT
104 #define GET_GLOBALISEL_TEMPORARIES_INIT
105 #include "X86GenGlobalISel.inc"
106 #undef GET_GLOBALISEL_TEMPORARIES_INIT
110 // FIXME: This should be target-independent, inferred from the types declared
111 // for each class in the bank.
112 static const TargetRegisterClass *
113 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
114 if (RB.getID() == X86::GPRRegBankID) {
115 if (Ty.getSizeInBits() <= 8)
116 return &X86::GR8RegClass;
117 if (Ty.getSizeInBits() == 16)
118 return &X86::GR16RegClass;
119 if (Ty.getSizeInBits() == 32)
120 return &X86::GR32RegClass;
121 if (Ty.getSizeInBits() == 64)
122 return &X86::GR64RegClass;
124 if (RB.getID() == X86::VECRRegBankID) {
125 if (Ty.getSizeInBits() == 32)
126 return &X86::FR32XRegClass;
127 if (Ty.getSizeInBits() == 64)
128 return &X86::FR64XRegClass;
129 if (Ty.getSizeInBits() == 128)
130 return &X86::VR128XRegClass;
131 if (Ty.getSizeInBits() == 256)
132 return &X86::VR256XRegClass;
133 if (Ty.getSizeInBits() == 512)
134 return &X86::VR512RegClass;
137 llvm_unreachable("Unknown RegBank!");
140 // Set X86 Opcode and constrain DestReg.
141 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
142 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
143 const RegisterBankInfo &RBI) {
145 unsigned DstReg = I.getOperand(0).getReg();
146 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
147 assert(I.isCopy() && "Generic operators do not allow physical registers");
151 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
152 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
153 unsigned SrcReg = I.getOperand(1).getReg();
154 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
156 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
157 "No phys reg on generic operators");
158 assert((DstSize == SrcSize ||
159 // Copies are a mean to setup initial types, the number of
160 // bits may not exactly match.
161 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
162 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
163 "Copy with different width?!");
165 const TargetRegisterClass *RC = nullptr;
167 switch (RegBank.getID()) {
168 case X86::GPRRegBankID:
169 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
170 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
172 // Change the physical register
173 if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
174 if (RC == &X86::GR32RegClass)
175 I.getOperand(1).setSubReg(X86::sub_32bit);
176 else if (RC == &X86::GR16RegClass)
177 I.getOperand(1).setSubReg(X86::sub_16bit);
178 else if (RC == &X86::GR8RegClass)
179 I.getOperand(1).setSubReg(X86::sub_8bit);
181 I.getOperand(1).substPhysReg(SrcReg, TRI);
184 case X86::VECRRegBankID:
185 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
188 llvm_unreachable("Unknown RegBank!");
191 // No need to constrain SrcReg. It will get constrained when
192 // we hit another of its use or its defs.
193 // Copies do not have constraints.
194 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
195 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
196 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
197 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
202 I.setDesc(TII.get(X86::COPY));
206 bool X86InstructionSelector::select(MachineInstr &I) const {
207 assert(I.getParent() && "Instruction should be in a basic block!");
208 assert(I.getParent()->getParent() && "Instruction should be in a function!");
210 MachineBasicBlock &MBB = *I.getParent();
211 MachineFunction &MF = *MBB.getParent();
212 MachineRegisterInfo &MRI = MF.getRegInfo();
214 unsigned Opcode = I.getOpcode();
215 if (!isPreISelGenericOpcode(Opcode)) {
216 // Certain non-generic instructions also need some special handling.
219 return selectCopy(I, TII, MRI, TRI, RBI);
221 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
225 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
226 "Generic instruction has unexpected implicit operands\n");
231 DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
233 // TODO: This should be implemented by tblgen.
234 if (selectBinaryOp(I, MRI, MF))
236 if (selectLoadStoreOp(I, MRI, MF))
238 if (selectFrameIndexOrGep(I, MRI, MF))
240 if (selectConstant(I, MRI, MF))
242 if (selectTrunc(I, MRI, MF))
248 unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
249 const RegisterBank &RB) const {
251 if (X86::VECRRegBankID != RB.getID())
252 return TargetOpcode::G_FADD;
254 if (Ty == LLT::scalar(32)) {
255 if (STI.hasAVX512()) {
256 return X86::VADDSSZrr;
257 } else if (STI.hasAVX()) {
258 return X86::VADDSSrr;
259 } else if (STI.hasSSE1()) {
262 } else if (Ty == LLT::scalar(64)) {
263 if (STI.hasAVX512()) {
264 return X86::VADDSDZrr;
265 } else if (STI.hasAVX()) {
266 return X86::VADDSDrr;
267 } else if (STI.hasSSE2()) {
270 } else if (Ty == LLT::vector(4, 32)) {
271 if ((STI.hasAVX512()) && (STI.hasVLX())) {
272 return X86::VADDPSZ128rr;
273 } else if (STI.hasAVX()) {
274 return X86::VADDPSrr;
275 } else if (STI.hasSSE1()) {
280 return TargetOpcode::G_FADD;
283 unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
284 const RegisterBank &RB) const {
286 if (X86::VECRRegBankID != RB.getID())
287 return TargetOpcode::G_FSUB;
289 if (Ty == LLT::scalar(32)) {
290 if (STI.hasAVX512()) {
291 return X86::VSUBSSZrr;
292 } else if (STI.hasAVX()) {
293 return X86::VSUBSSrr;
294 } else if (STI.hasSSE1()) {
297 } else if (Ty == LLT::scalar(64)) {
298 if (STI.hasAVX512()) {
299 return X86::VSUBSDZrr;
300 } else if (STI.hasAVX()) {
301 return X86::VSUBSDrr;
302 } else if (STI.hasSSE2()) {
305 } else if (Ty == LLT::vector(4, 32)) {
306 if ((STI.hasAVX512()) && (STI.hasVLX())) {
307 return X86::VSUBPSZ128rr;
308 } else if (STI.hasAVX()) {
309 return X86::VSUBPSrr;
310 } else if (STI.hasSSE1()) {
315 return TargetOpcode::G_FSUB;
318 bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
319 MachineRegisterInfo &MRI,
320 MachineFunction &MF) const {
322 const unsigned DefReg = I.getOperand(0).getReg();
323 LLT Ty = MRI.getType(DefReg);
324 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
326 unsigned NewOpc = I.getOpcode();
329 case TargetOpcode::G_FADD:
330 NewOpc = getFAddOp(Ty, RB);
332 case TargetOpcode::G_FSUB:
333 NewOpc = getFSubOp(Ty, RB);
339 if (NewOpc == I.getOpcode())
342 I.setDesc(TII.get(NewOpc));
344 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
347 unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
349 uint64_t Alignment) const {
350 bool Isload = (Opc == TargetOpcode::G_LOAD);
351 bool HasAVX = STI.hasAVX();
352 bool HasAVX512 = STI.hasAVX512();
353 bool HasVLX = STI.hasVLX();
355 if (Ty == LLT::scalar(8)) {
356 if (X86::GPRRegBankID == RB.getID())
357 return Isload ? X86::MOV8rm : X86::MOV8mr;
358 } else if (Ty == LLT::scalar(16)) {
359 if (X86::GPRRegBankID == RB.getID())
360 return Isload ? X86::MOV16rm : X86::MOV16mr;
361 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
362 if (X86::GPRRegBankID == RB.getID())
363 return Isload ? X86::MOV32rm : X86::MOV32mr;
364 if (X86::VECRRegBankID == RB.getID())
365 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
366 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
367 : (HasAVX512 ? X86::VMOVSSZmr
368 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
369 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
370 if (X86::GPRRegBankID == RB.getID())
371 return Isload ? X86::MOV64rm : X86::MOV64mr;
372 if (X86::VECRRegBankID == RB.getID())
373 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
374 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
375 : (HasAVX512 ? X86::VMOVSDZmr
376 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
377 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
379 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
381 ? X86::VMOVAPSZ128rm_NOVLX
382 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
383 : (HasVLX ? X86::VMOVAPSZ128mr
385 ? X86::VMOVAPSZ128mr_NOVLX
386 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
388 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
390 ? X86::VMOVUPSZ128rm_NOVLX
391 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
392 : (HasVLX ? X86::VMOVUPSZ128mr
394 ? X86::VMOVUPSZ128mr_NOVLX
395 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
400 bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
401 MachineRegisterInfo &MRI,
402 MachineFunction &MF) const {
404 unsigned Opc = I.getOpcode();
406 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
409 const unsigned DefReg = I.getOperand(0).getReg();
410 LLT Ty = MRI.getType(DefReg);
411 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
413 auto &MemOp = **I.memoperands_begin();
414 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
418 I.setDesc(TII.get(NewOpc));
419 MachineInstrBuilder MIB(MF, I);
420 if (Opc == TargetOpcode::G_LOAD)
423 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
425 addOffset(MIB, 0).addUse(DefReg);
427 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
430 bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
431 MachineRegisterInfo &MRI,
432 MachineFunction &MF) const {
433 unsigned Opc = I.getOpcode();
435 if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
438 const unsigned DefReg = I.getOperand(0).getReg();
439 LLT Ty = MRI.getType(DefReg);
441 // Use LEA to calculate frame index and GEP
443 if (Ty == LLT::pointer(0, 64))
444 NewOpc = X86::LEA64r;
445 else if (Ty == LLT::pointer(0, 32))
446 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
448 llvm_unreachable("Can't select G_FRAME_INDEX/G_GEP, unsupported type.");
450 I.setDesc(TII.get(NewOpc));
451 MachineInstrBuilder MIB(MF, I);
453 if (Opc == TargetOpcode::G_FRAME_INDEX) {
456 MachineOperand &InxOp = I.getOperand(2);
457 I.addOperand(InxOp); // set IndexReg
458 InxOp.ChangeToImmediate(1); // set Scale
459 MIB.addImm(0).addReg(0);
462 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
465 bool X86InstructionSelector::selectConstant(MachineInstr &I,
466 MachineRegisterInfo &MRI,
467 MachineFunction &MF) const {
468 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
471 const unsigned DefReg = I.getOperand(0).getReg();
472 LLT Ty = MRI.getType(DefReg);
474 assert(Ty.isScalar() && "invalid element type.");
477 if (I.getOperand(1).isCImm()) {
478 Val = I.getOperand(1).getCImm()->getZExtValue();
479 I.getOperand(1).ChangeToImmediate(Val);
480 } else if (I.getOperand(1).isImm()) {
481 Val = I.getOperand(1).getImm();
483 llvm_unreachable("Unsupported operand type.");
486 switch (Ty.getSizeInBits()) {
488 NewOpc = X86::MOV8ri;
491 NewOpc = X86::MOV16ri;
494 NewOpc = X86::MOV32ri;
497 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
499 NewOpc = X86::MOV64ri32;
501 NewOpc = X86::MOV64ri;
505 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
508 I.setDesc(TII.get(NewOpc));
509 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
512 bool X86InstructionSelector::selectTrunc(MachineInstr &I,
513 MachineRegisterInfo &MRI,
514 MachineFunction &MF) const {
515 if (I.getOpcode() != TargetOpcode::G_TRUNC)
518 const unsigned DstReg = I.getOperand(0).getReg();
519 const unsigned SrcReg = I.getOperand(1).getReg();
521 const LLT DstTy = MRI.getType(DstReg);
522 const LLT SrcTy = MRI.getType(SrcReg);
524 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
525 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
527 if (DstRB.getID() != SrcRB.getID()) {
528 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
532 if (DstRB.getID() != X86::GPRRegBankID)
535 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
539 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
543 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
544 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
545 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
549 if (DstRC == SrcRC) {
550 // Nothing to be done
551 } else if (DstRC == &X86::GR32RegClass) {
552 I.getOperand(1).setSubReg(X86::sub_32bit);
553 } else if (DstRC == &X86::GR16RegClass) {
554 I.getOperand(1).setSubReg(X86::sub_16bit);
555 } else if (DstRC == &X86::GR8RegClass) {
556 I.getOperand(1).setSubReg(X86::sub_8bit);
561 I.setDesc(TII.get(X86::COPY));
565 InstructionSelector *
566 llvm::createX86InstructionSelector(const X86TargetMachine &TM,
567 X86Subtarget &Subtarget,
568 X86RegisterBankInfo &RBI) {
569 return new X86InstructionSelector(TM, Subtarget, RBI);