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 class X86InstructionSelector : public InstructionSelector {
44 X86InstructionSelector(const X86Subtarget &STI,
45 const X86RegisterBankInfo &RBI);
47 bool select(MachineInstr &I) const override;
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;
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;
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;
71 const X86Subtarget &STI;
72 const X86InstrInfo &TII;
73 const X86RegisterInfo &TRI;
74 const X86RegisterBankInfo &RBI;
76 #define GET_GLOBALISEL_TEMPORARIES_DECL
77 #include "X86GenGlobalISel.inc"
78 #undef GET_GLOBALISEL_TEMPORARIES_DECL
81 } // end anonymous namespace
83 #define GET_GLOBALISEL_IMPL
84 #include "X86GenGlobalISel.inc"
85 #undef GET_GLOBALISEL_IMPL
87 X86InstructionSelector::X86InstructionSelector(const X86Subtarget &STI,
88 const X86RegisterBankInfo &RBI)
89 : InstructionSelector(), STI(STI), TII(*STI.getInstrInfo()),
90 TRI(*STI.getRegisterInfo()), RBI(RBI)
91 #define GET_GLOBALISEL_TEMPORARIES_INIT
92 #include "X86GenGlobalISel.inc"
93 #undef GET_GLOBALISEL_TEMPORARIES_INIT
97 // FIXME: This should be target-independent, inferred from the types declared
98 // for each class in the bank.
99 static const TargetRegisterClass *
100 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
101 if (RB.getID() == X86::GPRRegBankID) {
102 if (Ty.getSizeInBits() == 32)
103 return &X86::GR32RegClass;
104 if (Ty.getSizeInBits() == 64)
105 return &X86::GR64RegClass;
107 if (RB.getID() == X86::VECRRegBankID) {
108 if (Ty.getSizeInBits() == 32)
109 return &X86::FR32XRegClass;
110 if (Ty.getSizeInBits() == 64)
111 return &X86::FR64XRegClass;
112 if (Ty.getSizeInBits() == 128)
113 return &X86::VR128XRegClass;
114 if (Ty.getSizeInBits() == 256)
115 return &X86::VR256XRegClass;
116 if (Ty.getSizeInBits() == 512)
117 return &X86::VR512RegClass;
120 llvm_unreachable("Unknown RegBank!");
123 // Set X86 Opcode and constrain DestReg.
124 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
125 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
126 const RegisterBankInfo &RBI) {
128 unsigned DstReg = I.getOperand(0).getReg();
129 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
130 assert(I.isCopy() && "Generic operators do not allow physical registers");
134 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
135 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
137 unsigned SrcReg = I.getOperand(1).getReg();
138 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
140 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
141 "No phys reg on generic operators");
142 assert((DstSize == SrcSize ||
143 // Copies are a mean to setup initial types, the number of
144 // bits may not exactly match.
145 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
146 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
147 "Copy with different width?!");
149 const TargetRegisterClass *RC = nullptr;
151 switch (RegBank.getID()) {
152 case X86::GPRRegBankID:
153 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
154 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
156 case X86::VECRRegBankID:
157 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
160 llvm_unreachable("Unknown RegBank!");
163 // No need to constrain SrcReg. It will get constrained when
164 // we hit another of its use or its defs.
165 // Copies do not have constraints.
166 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
167 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
168 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
169 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
174 I.setDesc(TII.get(X86::COPY));
178 bool X86InstructionSelector::select(MachineInstr &I) const {
179 assert(I.getParent() && "Instruction should be in a basic block!");
180 assert(I.getParent()->getParent() && "Instruction should be in a function!");
182 MachineBasicBlock &MBB = *I.getParent();
183 MachineFunction &MF = *MBB.getParent();
184 MachineRegisterInfo &MRI = MF.getRegInfo();
186 unsigned Opcode = I.getOpcode();
187 if (!isPreISelGenericOpcode(Opcode)) {
188 // Certain non-generic instructions also need some special handling.
191 return selectCopy(I, TII, MRI, TRI, RBI);
193 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
197 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
198 "Generic instruction has unexpected implicit operands\n");
200 // TODO: This should be implemented by tblgen, pattern with predicate not
202 if (selectBinaryOp(I, MRI, MF))
204 if (selectLoadStoreOp(I, MRI, MF))
206 if (selectFrameIndex(I, MRI, MF))
208 if (selectConstant(I, MRI, MF))
211 return selectImpl(I);
214 unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
215 const RegisterBank &RB) const {
217 if (X86::VECRRegBankID != RB.getID())
218 return TargetOpcode::G_FADD;
220 if (Ty == LLT::scalar(32)) {
221 if (STI.hasAVX512()) {
222 return X86::VADDSSZrr;
223 } else if (STI.hasAVX()) {
224 return X86::VADDSSrr;
225 } else if (STI.hasSSE1()) {
228 } else if (Ty == LLT::scalar(64)) {
229 if (STI.hasAVX512()) {
230 return X86::VADDSDZrr;
231 } else if (STI.hasAVX()) {
232 return X86::VADDSDrr;
233 } else if (STI.hasSSE2()) {
236 } else if (Ty == LLT::vector(4, 32)) {
237 if ((STI.hasAVX512()) && (STI.hasVLX())) {
238 return X86::VADDPSZ128rr;
239 } else if (STI.hasAVX()) {
240 return X86::VADDPSrr;
241 } else if (STI.hasSSE1()) {
246 return TargetOpcode::G_FADD;
249 unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
250 const RegisterBank &RB) const {
252 if (X86::VECRRegBankID != RB.getID())
253 return TargetOpcode::G_FSUB;
255 if (Ty == LLT::scalar(32)) {
256 if (STI.hasAVX512()) {
257 return X86::VSUBSSZrr;
258 } else if (STI.hasAVX()) {
259 return X86::VSUBSSrr;
260 } else if (STI.hasSSE1()) {
263 } else if (Ty == LLT::scalar(64)) {
264 if (STI.hasAVX512()) {
265 return X86::VSUBSDZrr;
266 } else if (STI.hasAVX()) {
267 return X86::VSUBSDrr;
268 } else if (STI.hasSSE2()) {
271 } else if (Ty == LLT::vector(4, 32)) {
272 if ((STI.hasAVX512()) && (STI.hasVLX())) {
273 return X86::VSUBPSZ128rr;
274 } else if (STI.hasAVX()) {
275 return X86::VSUBPSrr;
276 } else if (STI.hasSSE1()) {
281 return TargetOpcode::G_FSUB;
284 unsigned X86InstructionSelector::getAddOp(LLT &Ty,
285 const RegisterBank &RB) const {
287 if (X86::VECRRegBankID != RB.getID())
288 return TargetOpcode::G_ADD;
290 if (Ty == LLT::vector(4, 32)) {
291 if (STI.hasAVX512() && STI.hasVLX()) {
292 return X86::VPADDDZ128rr;
293 } else if (STI.hasAVX()) {
294 return X86::VPADDDrr;
295 } else if (STI.hasSSE2()) {
300 return TargetOpcode::G_ADD;
303 unsigned X86InstructionSelector::getSubOp(LLT &Ty,
304 const RegisterBank &RB) const {
306 if (X86::VECRRegBankID != RB.getID())
307 return TargetOpcode::G_SUB;
309 if (Ty == LLT::vector(4, 32)) {
310 if (STI.hasAVX512() && STI.hasVLX()) {
311 return X86::VPSUBDZ128rr;
312 } else if (STI.hasAVX()) {
313 return X86::VPSUBDrr;
314 } else if (STI.hasSSE2()) {
319 return TargetOpcode::G_SUB;
322 bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
323 MachineRegisterInfo &MRI,
324 MachineFunction &MF) const {
326 const unsigned DefReg = I.getOperand(0).getReg();
327 LLT Ty = MRI.getType(DefReg);
328 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
330 unsigned NewOpc = I.getOpcode();
333 case TargetOpcode::G_FADD:
334 NewOpc = getFAddOp(Ty, RB);
336 case TargetOpcode::G_FSUB:
337 NewOpc = getFSubOp(Ty, RB);
339 case TargetOpcode::G_ADD:
340 NewOpc = getAddOp(Ty, RB);
342 case TargetOpcode::G_SUB:
343 NewOpc = getSubOp(Ty, RB);
349 if (NewOpc == I.getOpcode())
352 I.setDesc(TII.get(NewOpc));
354 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
357 unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
359 uint64_t Alignment) const {
360 bool Isload = (Opc == TargetOpcode::G_LOAD);
361 bool HasAVX = STI.hasAVX();
362 bool HasAVX512 = STI.hasAVX512();
363 bool HasVLX = STI.hasVLX();
365 if (Ty == LLT::scalar(8)) {
366 if (X86::GPRRegBankID == RB.getID())
367 return Isload ? X86::MOV8rm : X86::MOV8mr;
368 } else if (Ty == LLT::scalar(16)) {
369 if (X86::GPRRegBankID == RB.getID())
370 return Isload ? X86::MOV16rm : X86::MOV16mr;
371 } else if (Ty == LLT::scalar(32)) {
372 if (X86::GPRRegBankID == RB.getID())
373 return Isload ? X86::MOV32rm : X86::MOV32mr;
374 if (X86::VECRRegBankID == RB.getID())
375 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
376 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
377 : (HasAVX512 ? X86::VMOVSSZmr
378 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
379 } else if (Ty == LLT::scalar(64)) {
380 if (X86::GPRRegBankID == RB.getID())
381 return Isload ? X86::MOV64rm : X86::MOV64mr;
382 if (X86::VECRRegBankID == RB.getID())
383 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
384 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
385 : (HasAVX512 ? X86::VMOVSDZmr
386 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
387 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
389 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
391 ? X86::VMOVAPSZ128rm_NOVLX
392 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
393 : (HasVLX ? X86::VMOVAPSZ128mr
395 ? X86::VMOVAPSZ128mr_NOVLX
396 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
398 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
400 ? X86::VMOVUPSZ128rm_NOVLX
401 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
402 : (HasVLX ? X86::VMOVUPSZ128mr
404 ? X86::VMOVUPSZ128mr_NOVLX
405 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
410 bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
411 MachineRegisterInfo &MRI,
412 MachineFunction &MF) const {
414 unsigned Opc = I.getOpcode();
416 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
419 const unsigned DefReg = I.getOperand(0).getReg();
420 LLT Ty = MRI.getType(DefReg);
421 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
423 auto &MemOp = **I.memoperands_begin();
424 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
428 I.setDesc(TII.get(NewOpc));
429 MachineInstrBuilder MIB(MF, I);
430 if (Opc == TargetOpcode::G_LOAD)
433 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
435 addOffset(MIB, 0).addUse(DefReg);
437 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
440 bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
441 MachineRegisterInfo &MRI,
442 MachineFunction &MF) const {
443 if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX)
446 const unsigned DefReg = I.getOperand(0).getReg();
447 LLT Ty = MRI.getType(DefReg);
449 // Use LEA to calculate frame index.
451 if (Ty == LLT::pointer(0, 64))
452 NewOpc = X86::LEA64r;
453 else if (Ty == LLT::pointer(0, 32))
454 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
456 llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type.");
458 I.setDesc(TII.get(NewOpc));
459 MachineInstrBuilder MIB(MF, I);
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 InstructionSelector *
513 llvm::createX86InstructionSelector(X86Subtarget &Subtarget,
514 X86RegisterBankInfo &RBI) {
515 return new X86InstructionSelector(Subtarget, RBI);