blob: 6cc5e8b63597502644483cb0e4eec7826e0b6e98 [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
Igor Bregera8ba5722017-03-23 15:25:57 +000015#include "X86InstrBuilder.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000016#include "X86InstrInfo.h"
17#include "X86RegisterBankInfo.h"
18#include "X86RegisterInfo.h"
19#include "X86Subtarget.h"
20#include "X86TargetMachine.h"
Igor Breger3b97ea32017-04-12 12:54:54 +000021#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000022#include "llvm/CodeGen/MachineBasicBlock.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineInstr.h"
25#include "llvm/CodeGen/MachineInstrBuilder.h"
Daniel Sanders0b5293f2017-04-06 09:49:34 +000026#include "llvm/CodeGen/MachineOperand.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000027#include "llvm/CodeGen/MachineRegisterInfo.h"
28#include "llvm/IR/Type.h"
29#include "llvm/Support/Debug.h"
30#include "llvm/Support/raw_ostream.h"
31
32#define DEBUG_TYPE "X86-isel"
33
34using namespace llvm;
35
36#ifndef LLVM_BUILD_GLOBAL_ISEL
37#error "You shouldn't build this"
38#endif
39
Daniel Sanders0b5293f2017-04-06 09:49:34 +000040namespace {
41
42class X86InstructionSelector : public InstructionSelector {
43public:
44 X86InstructionSelector(const X86Subtarget &STI,
45 const X86RegisterBankInfo &RBI);
46
47 bool select(MachineInstr &I) const override;
48
49private:
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;
53
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;
61
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;
Igor Breger3b97ea32017-04-12 12:54:54 +000068 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
69 MachineFunction &MF) const;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000070
71 const X86Subtarget &STI;
72 const X86InstrInfo &TII;
73 const X86RegisterInfo &TRI;
74 const X86RegisterBankInfo &RBI;
75
76#define GET_GLOBALISEL_TEMPORARIES_DECL
77#include "X86GenGlobalISel.inc"
78#undef GET_GLOBALISEL_TEMPORARIES_DECL
79};
80
81} // end anonymous namespace
82
Daniel Sanders8a4bae92017-03-14 21:32:08 +000083#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000084#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +000085#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000086
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +000087X86InstructionSelector::X86InstructionSelector(const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +000088 const X86RegisterBankInfo &RBI)
Igor Breger321cf3c2017-03-03 08:06:46 +000089 : InstructionSelector(), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanders8a4bae92017-03-14 21:32:08 +000090 TRI(*STI.getRegisterInfo()), RBI(RBI)
91#define GET_GLOBALISEL_TEMPORARIES_INIT
92#include "X86GenGlobalISel.inc"
93#undef GET_GLOBALISEL_TEMPORARIES_INIT
94{
95}
Igor Bregerf7359d82017-02-22 12:25:09 +000096
97// FIXME: This should be target-independent, inferred from the types declared
98// for each class in the bank.
99static const TargetRegisterClass *
100getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
101 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger321cf3c2017-03-03 08:06:46 +0000102 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000103 return &X86::GR32RegClass;
104 if (Ty.getSizeInBits() == 64)
105 return &X86::GR64RegClass;
106 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000107 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;
118 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000119
120 llvm_unreachable("Unknown RegBank!");
121}
122
123// Set X86 Opcode and constrain DestReg.
124static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
125 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
126 const RegisterBankInfo &RBI) {
127
128 unsigned DstReg = I.getOperand(0).getReg();
129 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
130 assert(I.isCopy() && "Generic operators do not allow physical registers");
131 return true;
132 }
133
134 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
135 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000136 (void)DstSize;
Igor Bregerf7359d82017-02-22 12:25:09 +0000137 unsigned SrcReg = I.getOperand(1).getReg();
138 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
139 (void)SrcSize;
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?!");
148
149 const TargetRegisterClass *RC = nullptr;
150
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);
155 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000156 case X86::VECRRegBankID:
157 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
158 break;
Igor Bregerf7359d82017-02-22 12:25:09 +0000159 default:
160 llvm_unreachable("Unknown RegBank!");
161 }
162
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.
Igor Breger8a924be2017-03-23 12:13:29 +0000166 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000167 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
168 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000169 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
170 << " operand\n");
171 return false;
172 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000173 }
174 I.setDesc(TII.get(X86::COPY));
175 return true;
176}
177
178bool 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!");
181
182 MachineBasicBlock &MBB = *I.getParent();
183 MachineFunction &MF = *MBB.getParent();
184 MachineRegisterInfo &MRI = MF.getRegInfo();
185
186 unsigned Opcode = I.getOpcode();
187 if (!isPreISelGenericOpcode(Opcode)) {
188 // Certain non-generic instructions also need some special handling.
189
190 if (I.isCopy())
191 return selectCopy(I, TII, MRI, TRI, RBI);
192
193 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
194 return true;
195 }
196
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000197 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
198 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000199
Igor Breger8a924be2017-03-23 12:13:29 +0000200 // TODO: This should be implemented by tblgen, pattern with predicate not
201 // supported yet.
Igor Bregera8ba5722017-03-23 15:25:57 +0000202 if (selectBinaryOp(I, MRI, MF))
203 return true;
204 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000205 return true;
Igor Breger531a2032017-03-26 08:11:12 +0000206 if (selectFrameIndex(I, MRI, MF))
207 return true;
Igor Breger3b97ea32017-04-12 12:54:54 +0000208 if (selectConstant(I, MRI, MF))
209 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000210
Igor Bregerf7359d82017-02-22 12:25:09 +0000211 return selectImpl(I);
212}
Igor Breger321cf3c2017-03-03 08:06:46 +0000213
214unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
215 const RegisterBank &RB) const {
216
217 if (X86::VECRRegBankID != RB.getID())
218 return TargetOpcode::G_FADD;
219
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()) {
226 return X86::ADDSSrr;
227 }
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()) {
234 return X86::ADDSDrr;
235 }
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()) {
242 return X86::ADDPSrr;
243 }
244 }
245
246 return TargetOpcode::G_FADD;
247}
248
249unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
250 const RegisterBank &RB) const {
251
252 if (X86::VECRRegBankID != RB.getID())
253 return TargetOpcode::G_FSUB;
254
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()) {
261 return X86::SUBSSrr;
262 }
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()) {
269 return X86::SUBSDrr;
270 }
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()) {
277 return X86::SUBPSrr;
278 }
279 }
280
281 return TargetOpcode::G_FSUB;
282}
283
284unsigned X86InstructionSelector::getAddOp(LLT &Ty,
285 const RegisterBank &RB) const {
286
287 if (X86::VECRRegBankID != RB.getID())
288 return TargetOpcode::G_ADD;
289
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()) {
296 return X86::PADDDrr;
297 }
298 }
299
300 return TargetOpcode::G_ADD;
301}
302
303unsigned X86InstructionSelector::getSubOp(LLT &Ty,
304 const RegisterBank &RB) const {
305
306 if (X86::VECRRegBankID != RB.getID())
307 return TargetOpcode::G_SUB;
308
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()) {
315 return X86::PSUBDrr;
316 }
317 }
318
319 return TargetOpcode::G_SUB;
320}
321
322bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
Igor Bregera8ba5722017-03-23 15:25:57 +0000323 MachineRegisterInfo &MRI,
324 MachineFunction &MF) const {
Igor Breger321cf3c2017-03-03 08:06:46 +0000325
Igor Breger321cf3c2017-03-03 08:06:46 +0000326 const unsigned DefReg = I.getOperand(0).getReg();
Igor Bregera8ba5722017-03-23 15:25:57 +0000327 LLT Ty = MRI.getType(DefReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000328 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
329
330 unsigned NewOpc = I.getOpcode();
331
Igor Bregera8ba5722017-03-23 15:25:57 +0000332 switch (NewOpc) {
Igor Breger321cf3c2017-03-03 08:06:46 +0000333 case TargetOpcode::G_FADD:
334 NewOpc = getFAddOp(Ty, RB);
335 break;
336 case TargetOpcode::G_FSUB:
337 NewOpc = getFSubOp(Ty, RB);
338 break;
339 case TargetOpcode::G_ADD:
340 NewOpc = getAddOp(Ty, RB);
341 break;
342 case TargetOpcode::G_SUB:
343 NewOpc = getSubOp(Ty, RB);
344 break;
345 default:
346 break;
347 }
348
349 if (NewOpc == I.getOpcode())
350 return false;
351
352 I.setDesc(TII.get(NewOpc));
353
354 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
355}
Igor Bregera8ba5722017-03-23 15:25:57 +0000356
357unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
358 unsigned Opc,
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();
364
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) {
388 if (Alignment >= 16)
389 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
390 : HasAVX512
391 ? X86::VMOVAPSZ128rm_NOVLX
392 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
393 : (HasVLX ? X86::VMOVAPSZ128mr
394 : HasAVX512
395 ? X86::VMOVAPSZ128mr_NOVLX
396 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
397 else
398 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
399 : HasAVX512
400 ? X86::VMOVUPSZ128rm_NOVLX
401 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
402 : (HasVLX ? X86::VMOVUPSZ128mr
403 : HasAVX512
404 ? X86::VMOVUPSZ128mr_NOVLX
405 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
406 }
407 return Opc;
408}
409
410bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
411 MachineRegisterInfo &MRI,
412 MachineFunction &MF) const {
413
414 unsigned Opc = I.getOpcode();
415
416 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
417 return false;
418
419 const unsigned DefReg = I.getOperand(0).getReg();
420 LLT Ty = MRI.getType(DefReg);
421 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
422
423 auto &MemOp = **I.memoperands_begin();
424 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
425 if (NewOpc == Opc)
426 return false;
427
428 I.setDesc(TII.get(NewOpc));
429 MachineInstrBuilder MIB(MF, I);
430 if (Opc == TargetOpcode::G_LOAD)
431 addOffset(MIB, 0);
432 else {
433 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
434 I.RemoveOperand(0);
435 addOffset(MIB, 0).addUse(DefReg);
436 }
437 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
438}
439
Igor Breger531a2032017-03-26 08:11:12 +0000440bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
441 MachineRegisterInfo &MRI,
442 MachineFunction &MF) const {
443 if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX)
444 return false;
445
446 const unsigned DefReg = I.getOperand(0).getReg();
447 LLT Ty = MRI.getType(DefReg);
448
449 // Use LEA to calculate frame index.
450 unsigned NewOpc;
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;
455 else
456 llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type.");
457
458 I.setDesc(TII.get(NewOpc));
459 MachineInstrBuilder MIB(MF, I);
460 addOffset(MIB, 0);
461
462 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
463}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000464
Igor Breger3b97ea32017-04-12 12:54:54 +0000465bool X86InstructionSelector::selectConstant(MachineInstr &I,
466 MachineRegisterInfo &MRI,
467 MachineFunction &MF) const {
468 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
469 return false;
470
471 const unsigned DefReg = I.getOperand(0).getReg();
472 LLT Ty = MRI.getType(DefReg);
473
474 assert(Ty.isScalar() && "invalid element type.");
475
476 uint64_t Val = 0;
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();
482 } else
483 llvm_unreachable("Unsupported operand type.");
484
485 unsigned NewOpc;
486 switch (Ty.getSizeInBits()) {
487 case 8:
488 NewOpc = X86::MOV8ri;
489 break;
490 case 16:
491 NewOpc = X86::MOV16ri;
492 break;
493 case 32:
494 NewOpc = X86::MOV32ri;
495 break;
496 case 64: {
497 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
498 if (isInt<32>(Val))
499 NewOpc = X86::MOV64ri32;
500 else
501 NewOpc = X86::MOV64ri;
502 break;
503 }
504 default:
505 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
506 }
507
508 I.setDesc(TII.get(NewOpc));
509 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
510}
511
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000512InstructionSelector *
513llvm::createX86InstructionSelector(X86Subtarget &Subtarget,
514 X86RegisterBankInfo &RBI) {
515 return new X86InstructionSelector(Subtarget, RBI);
516}