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