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 "X86InstructionSelector.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/MachineBasicBlock.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/CodeGen/MachineInstr.h"
24 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #include "llvm/CodeGen/MachineRegisterInfo.h"
26 #include "llvm/IR/Type.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/raw_ostream.h"
29 
30 #define DEBUG_TYPE "X86-isel"
31 
32 using namespace llvm;
33 
34 #ifndef LLVM_BUILD_GLOBAL_ISEL
35 #error "You shouldn't build this"
36 #endif
37 
38 #include "X86GenGlobalISel.inc"
39 
40 X86InstructionSelector::X86InstructionSelector(const X86Subtarget &STI,
41                                                const X86RegisterBankInfo &RBI)
42     : InstructionSelector(), STI(STI), TII(*STI.getInstrInfo()),
43       TRI(*STI.getRegisterInfo()), RBI(RBI) {}
44 
45 // FIXME: This should be target-independent, inferred from the types declared
46 // for each class in the bank.
47 static const TargetRegisterClass *
48 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
49   if (RB.getID() == X86::GPRRegBankID) {
50     if (Ty.getSizeInBits() == 32)
51       return &X86::GR32RegClass;
52     if (Ty.getSizeInBits() == 64)
53       return &X86::GR64RegClass;
54   }
55   if (RB.getID() == X86::VECRRegBankID) {
56     if (Ty.getSizeInBits() == 32)
57       return &X86::FR32XRegClass;
58     if (Ty.getSizeInBits() == 64)
59       return &X86::FR64XRegClass;
60     if (Ty.getSizeInBits() == 128)
61       return &X86::VR128XRegClass;
62     if (Ty.getSizeInBits() == 256)
63       return &X86::VR256XRegClass;
64     if (Ty.getSizeInBits() == 512)
65       return &X86::VR512RegClass;
66   }
67 
68   llvm_unreachable("Unknown RegBank!");
69 }
70 
71 // Set X86 Opcode and constrain DestReg.
72 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
73                        MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
74                        const RegisterBankInfo &RBI) {
75 
76   unsigned DstReg = I.getOperand(0).getReg();
77   if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
78     assert(I.isCopy() && "Generic operators do not allow physical registers");
79     return true;
80   }
81 
82   const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
83   const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
84   (void)DstSize;
85   unsigned SrcReg = I.getOperand(1).getReg();
86   const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
87   (void)SrcSize;
88   assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
89          "No phys reg on generic operators");
90   assert((DstSize == SrcSize ||
91           // Copies are a mean to setup initial types, the number of
92           // bits may not exactly match.
93           (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
94            DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
95          "Copy with different width?!");
96 
97   const TargetRegisterClass *RC = nullptr;
98 
99   switch (RegBank.getID()) {
100   case X86::GPRRegBankID:
101     assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
102     RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
103     break;
104   case X86::VECRRegBankID:
105     RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
106     break;
107   default:
108     llvm_unreachable("Unknown RegBank!");
109   }
110 
111   // No need to constrain SrcReg. It will get constrained when
112   // we hit another of its use or its defs.
113   // Copies do not have constraints.
114   const TargetRegisterClass *OldRC  = MRI.getRegClassOrNull(DstReg);
115   if (!OldRC || !RC->hasSubClassEq(OldRC)) {
116     if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
117         DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
118                      << " operand\n");
119         return false;
120       }
121   }
122   I.setDesc(TII.get(X86::COPY));
123   return true;
124 }
125 
126 bool X86InstructionSelector::select(MachineInstr &I) const {
127   assert(I.getParent() && "Instruction should be in a basic block!");
128   assert(I.getParent()->getParent() && "Instruction should be in a function!");
129 
130   MachineBasicBlock &MBB = *I.getParent();
131   MachineFunction &MF = *MBB.getParent();
132   MachineRegisterInfo &MRI = MF.getRegInfo();
133 
134   unsigned Opcode = I.getOpcode();
135   if (!isPreISelGenericOpcode(Opcode)) {
136     // Certain non-generic instructions also need some special handling.
137 
138     if (I.isCopy())
139       return selectCopy(I, TII, MRI, TRI, RBI);
140 
141     // TODO: handle more cases - LOAD_STACK_GUARD, PHI
142     return true;
143   }
144 
145   assert(I.getNumOperands() == I.getNumExplicitOperands() &&
146          "Generic instruction has unexpected implicit operands\n");
147 
148   // TODO: This should be implemented by tblgen, pattern with predicate not supported yet.
149   if (selectBinaryOp(I, MRI))
150     return true;
151 
152   return selectImpl(I);
153 }
154 
155 unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
156                                            const RegisterBank &RB) const {
157 
158   if (X86::VECRRegBankID != RB.getID())
159     return TargetOpcode::G_FADD;
160 
161   if (Ty == LLT::scalar(32)) {
162     if (STI.hasAVX512()) {
163       return X86::VADDSSZrr;
164     } else if (STI.hasAVX()) {
165       return X86::VADDSSrr;
166     } else if (STI.hasSSE1()) {
167       return X86::ADDSSrr;
168     }
169   } else if (Ty == LLT::scalar(64)) {
170     if (STI.hasAVX512()) {
171       return X86::VADDSDZrr;
172     } else if (STI.hasAVX()) {
173       return X86::VADDSDrr;
174     } else if (STI.hasSSE2()) {
175       return X86::ADDSDrr;
176     }
177   } else if (Ty == LLT::vector(4, 32)) {
178     if ((STI.hasAVX512()) && (STI.hasVLX())) {
179       return X86::VADDPSZ128rr;
180     } else if (STI.hasAVX()) {
181       return X86::VADDPSrr;
182     } else if (STI.hasSSE1()) {
183       return X86::ADDPSrr;
184     }
185   }
186 
187   return TargetOpcode::G_FADD;
188 }
189 
190 unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
191                                            const RegisterBank &RB) const {
192 
193   if (X86::VECRRegBankID != RB.getID())
194     return TargetOpcode::G_FSUB;
195 
196   if (Ty == LLT::scalar(32)) {
197     if (STI.hasAVX512()) {
198       return X86::VSUBSSZrr;
199     } else if (STI.hasAVX()) {
200       return X86::VSUBSSrr;
201     } else if (STI.hasSSE1()) {
202       return X86::SUBSSrr;
203     }
204   } else if (Ty == LLT::scalar(64)) {
205     if (STI.hasAVX512()) {
206       return X86::VSUBSDZrr;
207     } else if (STI.hasAVX()) {
208       return X86::VSUBSDrr;
209     } else if (STI.hasSSE2()) {
210       return X86::SUBSDrr;
211     }
212   } else if (Ty == LLT::vector(4, 32)) {
213     if ((STI.hasAVX512()) && (STI.hasVLX())) {
214       return X86::VSUBPSZ128rr;
215     } else if (STI.hasAVX()) {
216       return X86::VSUBPSrr;
217     } else if (STI.hasSSE1()) {
218       return X86::SUBPSrr;
219     }
220   }
221 
222   return TargetOpcode::G_FSUB;
223 }
224 
225 unsigned X86InstructionSelector::getAddOp(LLT &Ty,
226                                           const RegisterBank &RB) const {
227 
228   if (X86::VECRRegBankID != RB.getID())
229     return TargetOpcode::G_ADD;
230 
231   if (Ty == LLT::vector(4, 32)) {
232     if (STI.hasAVX512() && STI.hasVLX()) {
233       return X86::VPADDDZ128rr;
234     } else if (STI.hasAVX()) {
235       return X86::VPADDDrr;
236     } else if (STI.hasSSE2()) {
237       return X86::PADDDrr;
238     }
239   }
240 
241   return TargetOpcode::G_ADD;
242 }
243 
244 unsigned X86InstructionSelector::getSubOp(LLT &Ty,
245                                           const RegisterBank &RB) const {
246 
247   if (X86::VECRRegBankID != RB.getID())
248     return TargetOpcode::G_SUB;
249 
250   if (Ty == LLT::vector(4, 32)) {
251     if (STI.hasAVX512() && STI.hasVLX()) {
252       return X86::VPSUBDZ128rr;
253     } else if (STI.hasAVX()) {
254       return X86::VPSUBDrr;
255     } else if (STI.hasSSE2()) {
256       return X86::PSUBDrr;
257     }
258   }
259 
260   return TargetOpcode::G_SUB;
261 }
262 
263 bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
264                                             MachineRegisterInfo &MRI) const {
265 
266   LLT Ty = MRI.getType(I.getOperand(0).getReg());
267   const unsigned DefReg = I.getOperand(0).getReg();
268   const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
269 
270   unsigned NewOpc = I.getOpcode();
271 
272   switch (I.getOpcode()) {
273   case TargetOpcode::G_FADD:
274     NewOpc = getFAddOp(Ty, RB);
275     break;
276   case TargetOpcode::G_FSUB:
277     NewOpc = getFSubOp(Ty, RB);
278     break;
279   case TargetOpcode::G_ADD:
280     NewOpc = getAddOp(Ty, RB);
281     break;
282   case TargetOpcode::G_SUB:
283     NewOpc = getSubOp(Ty, RB);
284     break;
285   default:
286     break;
287   }
288 
289   if (NewOpc == I.getOpcode())
290     return false;
291 
292   I.setDesc(TII.get(NewOpc));
293 
294   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
295 }
296 
297