blob: 0f01bc4d1a8ded949ac6ee540133fb9e52ae4985 [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"
Igor Bregera8ba5722017-03-23 15:25:57 +000016#include "X86InstrBuilder.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000017#include "X86InstrInfo.h"
18#include "X86RegisterBankInfo.h"
19#include "X86RegisterInfo.h"
20#include "X86Subtarget.h"
21#include "X86TargetMachine.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/MachineRegisterInfo.h"
27#include "llvm/IR/Type.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/raw_ostream.h"
30
31#define DEBUG_TYPE "X86-isel"
32
33using namespace llvm;
34
35#ifndef LLVM_BUILD_GLOBAL_ISEL
36#error "You shouldn't build this"
37#endif
38
Daniel Sanders8a4bae92017-03-14 21:32:08 +000039#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000040#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +000041#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000042
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +000043X86InstructionSelector::X86InstructionSelector(const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +000044 const X86RegisterBankInfo &RBI)
Igor Breger321cf3c2017-03-03 08:06:46 +000045 : InstructionSelector(), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanders8a4bae92017-03-14 21:32:08 +000046 TRI(*STI.getRegisterInfo()), RBI(RBI)
47#define GET_GLOBALISEL_TEMPORARIES_INIT
48#include "X86GenGlobalISel.inc"
49#undef GET_GLOBALISEL_TEMPORARIES_INIT
50{
51}
Igor Bregerf7359d82017-02-22 12:25:09 +000052
53// FIXME: This should be target-independent, inferred from the types declared
54// for each class in the bank.
55static const TargetRegisterClass *
56getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
57 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger321cf3c2017-03-03 08:06:46 +000058 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +000059 return &X86::GR32RegClass;
60 if (Ty.getSizeInBits() == 64)
61 return &X86::GR64RegClass;
62 }
Igor Breger321cf3c2017-03-03 08:06:46 +000063 if (RB.getID() == X86::VECRRegBankID) {
64 if (Ty.getSizeInBits() == 32)
65 return &X86::FR32XRegClass;
66 if (Ty.getSizeInBits() == 64)
67 return &X86::FR64XRegClass;
68 if (Ty.getSizeInBits() == 128)
69 return &X86::VR128XRegClass;
70 if (Ty.getSizeInBits() == 256)
71 return &X86::VR256XRegClass;
72 if (Ty.getSizeInBits() == 512)
73 return &X86::VR512RegClass;
74 }
Igor Bregerf7359d82017-02-22 12:25:09 +000075
76 llvm_unreachable("Unknown RegBank!");
77}
78
79// Set X86 Opcode and constrain DestReg.
80static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
81 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
82 const RegisterBankInfo &RBI) {
83
84 unsigned DstReg = I.getOperand(0).getReg();
85 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
86 assert(I.isCopy() && "Generic operators do not allow physical registers");
87 return true;
88 }
89
90 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
91 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +000092 (void)DstSize;
Igor Bregerf7359d82017-02-22 12:25:09 +000093 unsigned SrcReg = I.getOperand(1).getReg();
94 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
95 (void)SrcSize;
96 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
97 "No phys reg on generic operators");
98 assert((DstSize == SrcSize ||
99 // Copies are a mean to setup initial types, the number of
100 // bits may not exactly match.
101 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
102 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
103 "Copy with different width?!");
104
105 const TargetRegisterClass *RC = nullptr;
106
107 switch (RegBank.getID()) {
108 case X86::GPRRegBankID:
109 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
110 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
111 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000112 case X86::VECRRegBankID:
113 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
114 break;
Igor Bregerf7359d82017-02-22 12:25:09 +0000115 default:
116 llvm_unreachable("Unknown RegBank!");
117 }
118
119 // No need to constrain SrcReg. It will get constrained when
120 // we hit another of its use or its defs.
121 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000122 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000123 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
124 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000125 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
126 << " operand\n");
127 return false;
128 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000129 }
130 I.setDesc(TII.get(X86::COPY));
131 return true;
132}
133
134bool X86InstructionSelector::select(MachineInstr &I) const {
135 assert(I.getParent() && "Instruction should be in a basic block!");
136 assert(I.getParent()->getParent() && "Instruction should be in a function!");
137
138 MachineBasicBlock &MBB = *I.getParent();
139 MachineFunction &MF = *MBB.getParent();
140 MachineRegisterInfo &MRI = MF.getRegInfo();
141
142 unsigned Opcode = I.getOpcode();
143 if (!isPreISelGenericOpcode(Opcode)) {
144 // Certain non-generic instructions also need some special handling.
145
146 if (I.isCopy())
147 return selectCopy(I, TII, MRI, TRI, RBI);
148
149 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
150 return true;
151 }
152
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000153 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
154 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000155
Igor Breger8a924be2017-03-23 12:13:29 +0000156 // TODO: This should be implemented by tblgen, pattern with predicate not
157 // supported yet.
Igor Bregera8ba5722017-03-23 15:25:57 +0000158 if (selectBinaryOp(I, MRI, MF))
159 return true;
160 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000161 return true;
Igor Breger531a2032017-03-26 08:11:12 +0000162 if (selectFrameIndex(I, MRI, MF))
163 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000164
Igor Bregerf7359d82017-02-22 12:25:09 +0000165 return selectImpl(I);
166}
Igor Breger321cf3c2017-03-03 08:06:46 +0000167
168unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
169 const RegisterBank &RB) const {
170
171 if (X86::VECRRegBankID != RB.getID())
172 return TargetOpcode::G_FADD;
173
174 if (Ty == LLT::scalar(32)) {
175 if (STI.hasAVX512()) {
176 return X86::VADDSSZrr;
177 } else if (STI.hasAVX()) {
178 return X86::VADDSSrr;
179 } else if (STI.hasSSE1()) {
180 return X86::ADDSSrr;
181 }
182 } else if (Ty == LLT::scalar(64)) {
183 if (STI.hasAVX512()) {
184 return X86::VADDSDZrr;
185 } else if (STI.hasAVX()) {
186 return X86::VADDSDrr;
187 } else if (STI.hasSSE2()) {
188 return X86::ADDSDrr;
189 }
190 } else if (Ty == LLT::vector(4, 32)) {
191 if ((STI.hasAVX512()) && (STI.hasVLX())) {
192 return X86::VADDPSZ128rr;
193 } else if (STI.hasAVX()) {
194 return X86::VADDPSrr;
195 } else if (STI.hasSSE1()) {
196 return X86::ADDPSrr;
197 }
198 }
199
200 return TargetOpcode::G_FADD;
201}
202
203unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
204 const RegisterBank &RB) const {
205
206 if (X86::VECRRegBankID != RB.getID())
207 return TargetOpcode::G_FSUB;
208
209 if (Ty == LLT::scalar(32)) {
210 if (STI.hasAVX512()) {
211 return X86::VSUBSSZrr;
212 } else if (STI.hasAVX()) {
213 return X86::VSUBSSrr;
214 } else if (STI.hasSSE1()) {
215 return X86::SUBSSrr;
216 }
217 } else if (Ty == LLT::scalar(64)) {
218 if (STI.hasAVX512()) {
219 return X86::VSUBSDZrr;
220 } else if (STI.hasAVX()) {
221 return X86::VSUBSDrr;
222 } else if (STI.hasSSE2()) {
223 return X86::SUBSDrr;
224 }
225 } else if (Ty == LLT::vector(4, 32)) {
226 if ((STI.hasAVX512()) && (STI.hasVLX())) {
227 return X86::VSUBPSZ128rr;
228 } else if (STI.hasAVX()) {
229 return X86::VSUBPSrr;
230 } else if (STI.hasSSE1()) {
231 return X86::SUBPSrr;
232 }
233 }
234
235 return TargetOpcode::G_FSUB;
236}
237
238unsigned X86InstructionSelector::getAddOp(LLT &Ty,
239 const RegisterBank &RB) const {
240
241 if (X86::VECRRegBankID != RB.getID())
242 return TargetOpcode::G_ADD;
243
244 if (Ty == LLT::vector(4, 32)) {
245 if (STI.hasAVX512() && STI.hasVLX()) {
246 return X86::VPADDDZ128rr;
247 } else if (STI.hasAVX()) {
248 return X86::VPADDDrr;
249 } else if (STI.hasSSE2()) {
250 return X86::PADDDrr;
251 }
252 }
253
254 return TargetOpcode::G_ADD;
255}
256
257unsigned X86InstructionSelector::getSubOp(LLT &Ty,
258 const RegisterBank &RB) const {
259
260 if (X86::VECRRegBankID != RB.getID())
261 return TargetOpcode::G_SUB;
262
263 if (Ty == LLT::vector(4, 32)) {
264 if (STI.hasAVX512() && STI.hasVLX()) {
265 return X86::VPSUBDZ128rr;
266 } else if (STI.hasAVX()) {
267 return X86::VPSUBDrr;
268 } else if (STI.hasSSE2()) {
269 return X86::PSUBDrr;
270 }
271 }
272
273 return TargetOpcode::G_SUB;
274}
275
276bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
Igor Bregera8ba5722017-03-23 15:25:57 +0000277 MachineRegisterInfo &MRI,
278 MachineFunction &MF) const {
Igor Breger321cf3c2017-03-03 08:06:46 +0000279
Igor Breger321cf3c2017-03-03 08:06:46 +0000280 const unsigned DefReg = I.getOperand(0).getReg();
Igor Bregera8ba5722017-03-23 15:25:57 +0000281 LLT Ty = MRI.getType(DefReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000282 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
283
284 unsigned NewOpc = I.getOpcode();
285
Igor Bregera8ba5722017-03-23 15:25:57 +0000286 switch (NewOpc) {
Igor Breger321cf3c2017-03-03 08:06:46 +0000287 case TargetOpcode::G_FADD:
288 NewOpc = getFAddOp(Ty, RB);
289 break;
290 case TargetOpcode::G_FSUB:
291 NewOpc = getFSubOp(Ty, RB);
292 break;
293 case TargetOpcode::G_ADD:
294 NewOpc = getAddOp(Ty, RB);
295 break;
296 case TargetOpcode::G_SUB:
297 NewOpc = getSubOp(Ty, RB);
298 break;
299 default:
300 break;
301 }
302
303 if (NewOpc == I.getOpcode())
304 return false;
305
306 I.setDesc(TII.get(NewOpc));
307
308 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
309}
Igor Bregera8ba5722017-03-23 15:25:57 +0000310
311unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
312 unsigned Opc,
313 uint64_t Alignment) const {
314 bool Isload = (Opc == TargetOpcode::G_LOAD);
315 bool HasAVX = STI.hasAVX();
316 bool HasAVX512 = STI.hasAVX512();
317 bool HasVLX = STI.hasVLX();
318
319 if (Ty == LLT::scalar(8)) {
320 if (X86::GPRRegBankID == RB.getID())
321 return Isload ? X86::MOV8rm : X86::MOV8mr;
322 } else if (Ty == LLT::scalar(16)) {
323 if (X86::GPRRegBankID == RB.getID())
324 return Isload ? X86::MOV16rm : X86::MOV16mr;
325 } else if (Ty == LLT::scalar(32)) {
326 if (X86::GPRRegBankID == RB.getID())
327 return Isload ? X86::MOV32rm : X86::MOV32mr;
328 if (X86::VECRRegBankID == RB.getID())
329 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
330 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
331 : (HasAVX512 ? X86::VMOVSSZmr
332 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
333 } else if (Ty == LLT::scalar(64)) {
334 if (X86::GPRRegBankID == RB.getID())
335 return Isload ? X86::MOV64rm : X86::MOV64mr;
336 if (X86::VECRRegBankID == RB.getID())
337 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
338 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
339 : (HasAVX512 ? X86::VMOVSDZmr
340 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
341 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
342 if (Alignment >= 16)
343 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
344 : HasAVX512
345 ? X86::VMOVAPSZ128rm_NOVLX
346 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
347 : (HasVLX ? X86::VMOVAPSZ128mr
348 : HasAVX512
349 ? X86::VMOVAPSZ128mr_NOVLX
350 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
351 else
352 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
353 : HasAVX512
354 ? X86::VMOVUPSZ128rm_NOVLX
355 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
356 : (HasVLX ? X86::VMOVUPSZ128mr
357 : HasAVX512
358 ? X86::VMOVUPSZ128mr_NOVLX
359 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
360 }
361 return Opc;
362}
363
364bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
365 MachineRegisterInfo &MRI,
366 MachineFunction &MF) const {
367
368 unsigned Opc = I.getOpcode();
369
370 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
371 return false;
372
373 const unsigned DefReg = I.getOperand(0).getReg();
374 LLT Ty = MRI.getType(DefReg);
375 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
376
377 auto &MemOp = **I.memoperands_begin();
378 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
379 if (NewOpc == Opc)
380 return false;
381
382 I.setDesc(TII.get(NewOpc));
383 MachineInstrBuilder MIB(MF, I);
384 if (Opc == TargetOpcode::G_LOAD)
385 addOffset(MIB, 0);
386 else {
387 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
388 I.RemoveOperand(0);
389 addOffset(MIB, 0).addUse(DefReg);
390 }
391 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
392}
393
Igor Breger531a2032017-03-26 08:11:12 +0000394bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
395 MachineRegisterInfo &MRI,
396 MachineFunction &MF) const {
397 if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX)
398 return false;
399
400 const unsigned DefReg = I.getOperand(0).getReg();
401 LLT Ty = MRI.getType(DefReg);
402
403 // Use LEA to calculate frame index.
404 unsigned NewOpc;
405 if (Ty == LLT::pointer(0, 64))
406 NewOpc = X86::LEA64r;
407 else if (Ty == LLT::pointer(0, 32))
408 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
409 else
410 llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type.");
411
412 I.setDesc(TII.get(NewOpc));
413 MachineInstrBuilder MIB(MF, I);
414 addOffset(MIB, 0);
415
416 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
417}