blob: 60aefafa5955b16f6aeb28c69088002411657b36 [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
Daniel Sanderse7b0d662017-04-21 15:59:56 +000042#define GET_GLOBALISEL_PREDICATE_BITSET
43#include "X86GenGlobalISel.inc"
44#undef GET_GLOBALISEL_PREDICATE_BITSET
45
Daniel Sanders0b5293f2017-04-06 09:49:34 +000046class X86InstructionSelector : public InstructionSelector {
47public:
Daniel Sanderse7b0d662017-04-21 15:59:56 +000048 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
Daniel Sanders0b5293f2017-04-06 09:49:34 +000049 const X86RegisterBankInfo &RBI);
50
51 bool select(MachineInstr &I) const override;
52
53private:
54 /// tblgen-erated 'select' implementation, used as the initial selector for
55 /// the patterns that don't require complex C++.
56 bool selectImpl(MachineInstr &I) const;
57
58 // TODO: remove after selectImpl support pattern with a predicate.
59 unsigned getFAddOp(LLT &Ty, const RegisterBank &RB) const;
60 unsigned getFSubOp(LLT &Ty, const RegisterBank &RB) const;
61 unsigned getAddOp(LLT &Ty, const RegisterBank &RB) const;
62 unsigned getSubOp(LLT &Ty, const RegisterBank &RB) const;
63 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
64 uint64_t Alignment) const;
65
66 bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI,
67 MachineFunction &MF) const;
68 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
69 MachineFunction &MF) const;
70 bool selectFrameIndex(MachineInstr &I, MachineRegisterInfo &MRI,
71 MachineFunction &MF) const;
Igor Breger3b97ea32017-04-12 12:54:54 +000072 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
73 MachineFunction &MF) const;
Igor Breger4fdf1e42017-04-19 11:34:59 +000074 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
75 MachineFunction &MF) const;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000076
Daniel Sanderse7b0d662017-04-21 15:59:56 +000077 const X86TargetMachine &TM;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000078 const X86Subtarget &STI;
79 const X86InstrInfo &TII;
80 const X86RegisterInfo &TRI;
81 const X86RegisterBankInfo &RBI;
Daniel Sanderse7b0d662017-04-21 15:59:56 +000082
Daniel Sanderse9fdba32017-04-29 17:30:09 +000083#define GET_GLOBALISEL_PREDICATES_DECL
84#include "X86GenGlobalISel.inc"
85#undef GET_GLOBALISEL_PREDICATES_DECL
Daniel Sanders0b5293f2017-04-06 09:49:34 +000086
87#define GET_GLOBALISEL_TEMPORARIES_DECL
88#include "X86GenGlobalISel.inc"
89#undef GET_GLOBALISEL_TEMPORARIES_DECL
90};
91
92} // end anonymous namespace
93
Daniel Sanders8a4bae92017-03-14 21:32:08 +000094#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000095#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +000096#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000097
Daniel Sanderse7b0d662017-04-21 15:59:56 +000098X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
99 const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +0000100 const X86RegisterBankInfo &RBI)
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000101 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000102 TRI(*STI.getRegisterInfo()), RBI(RBI),
103#define GET_GLOBALISEL_PREDICATES_INIT
104#include "X86GenGlobalISel.inc"
105#undef GET_GLOBALISEL_PREDICATES_INIT
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000106#define GET_GLOBALISEL_TEMPORARIES_INIT
107#include "X86GenGlobalISel.inc"
108#undef GET_GLOBALISEL_TEMPORARIES_INIT
109{
110}
Igor Bregerf7359d82017-02-22 12:25:09 +0000111
112// FIXME: This should be target-independent, inferred from the types declared
113// for each class in the bank.
114static const TargetRegisterClass *
115getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
116 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger4fdf1e42017-04-19 11:34:59 +0000117 if (Ty.getSizeInBits() <= 8)
118 return &X86::GR8RegClass;
119 if (Ty.getSizeInBits() == 16)
120 return &X86::GR16RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000121 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000122 return &X86::GR32RegClass;
123 if (Ty.getSizeInBits() == 64)
124 return &X86::GR64RegClass;
125 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000126 if (RB.getID() == X86::VECRRegBankID) {
127 if (Ty.getSizeInBits() == 32)
128 return &X86::FR32XRegClass;
129 if (Ty.getSizeInBits() == 64)
130 return &X86::FR64XRegClass;
131 if (Ty.getSizeInBits() == 128)
132 return &X86::VR128XRegClass;
133 if (Ty.getSizeInBits() == 256)
134 return &X86::VR256XRegClass;
135 if (Ty.getSizeInBits() == 512)
136 return &X86::VR512RegClass;
137 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000138
139 llvm_unreachable("Unknown RegBank!");
140}
141
142// Set X86 Opcode and constrain DestReg.
143static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
144 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
145 const RegisterBankInfo &RBI) {
146
147 unsigned DstReg = I.getOperand(0).getReg();
148 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
149 assert(I.isCopy() && "Generic operators do not allow physical registers");
150 return true;
151 }
152
153 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
154 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
155 unsigned SrcReg = I.getOperand(1).getReg();
156 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
Igor Breger360d0f22017-04-27 08:02:03 +0000157
Igor Bregerf7359d82017-02-22 12:25:09 +0000158 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
159 "No phys reg on generic operators");
160 assert((DstSize == SrcSize ||
161 // Copies are a mean to setup initial types, the number of
162 // bits may not exactly match.
163 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
164 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
165 "Copy with different width?!");
166
167 const TargetRegisterClass *RC = nullptr;
168
169 switch (RegBank.getID()) {
170 case X86::GPRRegBankID:
171 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
172 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
Igor Breger360d0f22017-04-27 08:02:03 +0000173
174 // Change the physical register
175 if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
176 if (RC == &X86::GR32RegClass)
177 I.getOperand(1).setSubReg(X86::sub_32bit);
178 else if (RC == &X86::GR16RegClass)
179 I.getOperand(1).setSubReg(X86::sub_16bit);
180 else if (RC == &X86::GR8RegClass)
181 I.getOperand(1).setSubReg(X86::sub_8bit);
182
183 I.getOperand(1).substPhysReg(SrcReg, TRI);
184 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000185 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000186 case X86::VECRRegBankID:
187 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
188 break;
Igor Bregerf7359d82017-02-22 12:25:09 +0000189 default:
190 llvm_unreachable("Unknown RegBank!");
191 }
192
193 // No need to constrain SrcReg. It will get constrained when
194 // we hit another of its use or its defs.
195 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000196 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000197 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
198 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000199 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
200 << " operand\n");
201 return false;
202 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000203 }
204 I.setDesc(TII.get(X86::COPY));
205 return true;
206}
207
208bool X86InstructionSelector::select(MachineInstr &I) const {
209 assert(I.getParent() && "Instruction should be in a basic block!");
210 assert(I.getParent()->getParent() && "Instruction should be in a function!");
211
212 MachineBasicBlock &MBB = *I.getParent();
213 MachineFunction &MF = *MBB.getParent();
214 MachineRegisterInfo &MRI = MF.getRegInfo();
215
216 unsigned Opcode = I.getOpcode();
217 if (!isPreISelGenericOpcode(Opcode)) {
218 // Certain non-generic instructions also need some special handling.
219
220 if (I.isCopy())
221 return selectCopy(I, TII, MRI, TRI, RBI);
222
223 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
224 return true;
225 }
226
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000227 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
228 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000229
Igor Breger8a924be2017-03-23 12:13:29 +0000230 // TODO: This should be implemented by tblgen, pattern with predicate not
231 // supported yet.
Igor Bregera8ba5722017-03-23 15:25:57 +0000232 if (selectBinaryOp(I, MRI, MF))
233 return true;
234 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000235 return true;
Igor Breger531a2032017-03-26 08:11:12 +0000236 if (selectFrameIndex(I, MRI, MF))
237 return true;
Igor Breger3b97ea32017-04-12 12:54:54 +0000238 if (selectConstant(I, MRI, MF))
239 return true;
Igor Breger4fdf1e42017-04-19 11:34:59 +0000240 if (selectTrunc(I, MRI, MF))
241 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000242
Igor Bregerf7359d82017-02-22 12:25:09 +0000243 return selectImpl(I);
244}
Igor Breger321cf3c2017-03-03 08:06:46 +0000245
246unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
247 const RegisterBank &RB) const {
248
249 if (X86::VECRRegBankID != RB.getID())
250 return TargetOpcode::G_FADD;
251
252 if (Ty == LLT::scalar(32)) {
253 if (STI.hasAVX512()) {
254 return X86::VADDSSZrr;
255 } else if (STI.hasAVX()) {
256 return X86::VADDSSrr;
257 } else if (STI.hasSSE1()) {
258 return X86::ADDSSrr;
259 }
260 } else if (Ty == LLT::scalar(64)) {
261 if (STI.hasAVX512()) {
262 return X86::VADDSDZrr;
263 } else if (STI.hasAVX()) {
264 return X86::VADDSDrr;
265 } else if (STI.hasSSE2()) {
266 return X86::ADDSDrr;
267 }
268 } else if (Ty == LLT::vector(4, 32)) {
269 if ((STI.hasAVX512()) && (STI.hasVLX())) {
270 return X86::VADDPSZ128rr;
271 } else if (STI.hasAVX()) {
272 return X86::VADDPSrr;
273 } else if (STI.hasSSE1()) {
274 return X86::ADDPSrr;
275 }
276 }
277
278 return TargetOpcode::G_FADD;
279}
280
281unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
282 const RegisterBank &RB) const {
283
284 if (X86::VECRRegBankID != RB.getID())
285 return TargetOpcode::G_FSUB;
286
287 if (Ty == LLT::scalar(32)) {
288 if (STI.hasAVX512()) {
289 return X86::VSUBSSZrr;
290 } else if (STI.hasAVX()) {
291 return X86::VSUBSSrr;
292 } else if (STI.hasSSE1()) {
293 return X86::SUBSSrr;
294 }
295 } else if (Ty == LLT::scalar(64)) {
296 if (STI.hasAVX512()) {
297 return X86::VSUBSDZrr;
298 } else if (STI.hasAVX()) {
299 return X86::VSUBSDrr;
300 } else if (STI.hasSSE2()) {
301 return X86::SUBSDrr;
302 }
303 } else if (Ty == LLT::vector(4, 32)) {
304 if ((STI.hasAVX512()) && (STI.hasVLX())) {
305 return X86::VSUBPSZ128rr;
306 } else if (STI.hasAVX()) {
307 return X86::VSUBPSrr;
308 } else if (STI.hasSSE1()) {
309 return X86::SUBPSrr;
310 }
311 }
312
313 return TargetOpcode::G_FSUB;
314}
315
316unsigned X86InstructionSelector::getAddOp(LLT &Ty,
317 const RegisterBank &RB) const {
318
319 if (X86::VECRRegBankID != RB.getID())
320 return TargetOpcode::G_ADD;
321
322 if (Ty == LLT::vector(4, 32)) {
323 if (STI.hasAVX512() && STI.hasVLX()) {
324 return X86::VPADDDZ128rr;
325 } else if (STI.hasAVX()) {
326 return X86::VPADDDrr;
327 } else if (STI.hasSSE2()) {
328 return X86::PADDDrr;
329 }
330 }
331
332 return TargetOpcode::G_ADD;
333}
334
335unsigned X86InstructionSelector::getSubOp(LLT &Ty,
336 const RegisterBank &RB) const {
337
338 if (X86::VECRRegBankID != RB.getID())
339 return TargetOpcode::G_SUB;
340
341 if (Ty == LLT::vector(4, 32)) {
342 if (STI.hasAVX512() && STI.hasVLX()) {
343 return X86::VPSUBDZ128rr;
344 } else if (STI.hasAVX()) {
345 return X86::VPSUBDrr;
346 } else if (STI.hasSSE2()) {
347 return X86::PSUBDrr;
348 }
349 }
350
351 return TargetOpcode::G_SUB;
352}
353
354bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
Igor Bregera8ba5722017-03-23 15:25:57 +0000355 MachineRegisterInfo &MRI,
356 MachineFunction &MF) const {
Igor Breger321cf3c2017-03-03 08:06:46 +0000357
Igor Breger321cf3c2017-03-03 08:06:46 +0000358 const unsigned DefReg = I.getOperand(0).getReg();
Igor Bregera8ba5722017-03-23 15:25:57 +0000359 LLT Ty = MRI.getType(DefReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000360 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
361
362 unsigned NewOpc = I.getOpcode();
363
Igor Bregera8ba5722017-03-23 15:25:57 +0000364 switch (NewOpc) {
Igor Breger321cf3c2017-03-03 08:06:46 +0000365 case TargetOpcode::G_FADD:
366 NewOpc = getFAddOp(Ty, RB);
367 break;
368 case TargetOpcode::G_FSUB:
369 NewOpc = getFSubOp(Ty, RB);
370 break;
371 case TargetOpcode::G_ADD:
372 NewOpc = getAddOp(Ty, RB);
373 break;
374 case TargetOpcode::G_SUB:
375 NewOpc = getSubOp(Ty, RB);
376 break;
377 default:
378 break;
379 }
380
381 if (NewOpc == I.getOpcode())
382 return false;
383
384 I.setDesc(TII.get(NewOpc));
385
386 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
387}
Igor Bregera8ba5722017-03-23 15:25:57 +0000388
389unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
390 unsigned Opc,
391 uint64_t Alignment) const {
392 bool Isload = (Opc == TargetOpcode::G_LOAD);
393 bool HasAVX = STI.hasAVX();
394 bool HasAVX512 = STI.hasAVX512();
395 bool HasVLX = STI.hasVLX();
396
397 if (Ty == LLT::scalar(8)) {
398 if (X86::GPRRegBankID == RB.getID())
399 return Isload ? X86::MOV8rm : X86::MOV8mr;
400 } else if (Ty == LLT::scalar(16)) {
401 if (X86::GPRRegBankID == RB.getID())
402 return Isload ? X86::MOV16rm : X86::MOV16mr;
Igor Bregera9edb882017-05-01 06:08:32 +0000403 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000404 if (X86::GPRRegBankID == RB.getID())
405 return Isload ? X86::MOV32rm : X86::MOV32mr;
406 if (X86::VECRRegBankID == RB.getID())
407 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
408 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
409 : (HasAVX512 ? X86::VMOVSSZmr
410 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
Igor Bregera9edb882017-05-01 06:08:32 +0000411 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000412 if (X86::GPRRegBankID == RB.getID())
413 return Isload ? X86::MOV64rm : X86::MOV64mr;
414 if (X86::VECRRegBankID == RB.getID())
415 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
416 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
417 : (HasAVX512 ? X86::VMOVSDZmr
418 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
419 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
420 if (Alignment >= 16)
421 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
422 : HasAVX512
423 ? X86::VMOVAPSZ128rm_NOVLX
424 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
425 : (HasVLX ? X86::VMOVAPSZ128mr
426 : HasAVX512
427 ? X86::VMOVAPSZ128mr_NOVLX
428 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
429 else
430 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
431 : HasAVX512
432 ? X86::VMOVUPSZ128rm_NOVLX
433 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
434 : (HasVLX ? X86::VMOVUPSZ128mr
435 : HasAVX512
436 ? X86::VMOVUPSZ128mr_NOVLX
437 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
438 }
439 return Opc;
440}
441
442bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
443 MachineRegisterInfo &MRI,
444 MachineFunction &MF) const {
445
446 unsigned Opc = I.getOpcode();
447
448 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
449 return false;
450
451 const unsigned DefReg = I.getOperand(0).getReg();
452 LLT Ty = MRI.getType(DefReg);
453 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
454
455 auto &MemOp = **I.memoperands_begin();
456 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
457 if (NewOpc == Opc)
458 return false;
459
460 I.setDesc(TII.get(NewOpc));
461 MachineInstrBuilder MIB(MF, I);
462 if (Opc == TargetOpcode::G_LOAD)
463 addOffset(MIB, 0);
464 else {
465 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
466 I.RemoveOperand(0);
467 addOffset(MIB, 0).addUse(DefReg);
468 }
469 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
470}
471
Igor Breger531a2032017-03-26 08:11:12 +0000472bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
473 MachineRegisterInfo &MRI,
474 MachineFunction &MF) const {
475 if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX)
476 return false;
477
478 const unsigned DefReg = I.getOperand(0).getReg();
479 LLT Ty = MRI.getType(DefReg);
480
481 // Use LEA to calculate frame index.
482 unsigned NewOpc;
483 if (Ty == LLT::pointer(0, 64))
484 NewOpc = X86::LEA64r;
485 else if (Ty == LLT::pointer(0, 32))
486 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
487 else
488 llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type.");
489
490 I.setDesc(TII.get(NewOpc));
491 MachineInstrBuilder MIB(MF, I);
492 addOffset(MIB, 0);
493
494 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
495}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000496
Igor Breger3b97ea32017-04-12 12:54:54 +0000497bool X86InstructionSelector::selectConstant(MachineInstr &I,
498 MachineRegisterInfo &MRI,
499 MachineFunction &MF) const {
500 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
501 return false;
502
503 const unsigned DefReg = I.getOperand(0).getReg();
504 LLT Ty = MRI.getType(DefReg);
505
506 assert(Ty.isScalar() && "invalid element type.");
507
508 uint64_t Val = 0;
509 if (I.getOperand(1).isCImm()) {
510 Val = I.getOperand(1).getCImm()->getZExtValue();
511 I.getOperand(1).ChangeToImmediate(Val);
512 } else if (I.getOperand(1).isImm()) {
513 Val = I.getOperand(1).getImm();
514 } else
515 llvm_unreachable("Unsupported operand type.");
516
517 unsigned NewOpc;
518 switch (Ty.getSizeInBits()) {
519 case 8:
520 NewOpc = X86::MOV8ri;
521 break;
522 case 16:
523 NewOpc = X86::MOV16ri;
524 break;
525 case 32:
526 NewOpc = X86::MOV32ri;
527 break;
528 case 64: {
529 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
530 if (isInt<32>(Val))
531 NewOpc = X86::MOV64ri32;
532 else
533 NewOpc = X86::MOV64ri;
534 break;
535 }
536 default:
537 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
538 }
539
540 I.setDesc(TII.get(NewOpc));
541 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
542}
543
Igor Breger4fdf1e42017-04-19 11:34:59 +0000544bool X86InstructionSelector::selectTrunc(MachineInstr &I,
545 MachineRegisterInfo &MRI,
546 MachineFunction &MF) const {
547 if (I.getOpcode() != TargetOpcode::G_TRUNC)
548 return false;
549
550 const unsigned DstReg = I.getOperand(0).getReg();
551 const unsigned SrcReg = I.getOperand(1).getReg();
552
553 const LLT DstTy = MRI.getType(DstReg);
554 const LLT SrcTy = MRI.getType(SrcReg);
555
556 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
557 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
558
559 if (DstRB.getID() != SrcRB.getID()) {
560 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
561 return false;
562 }
563
564 if (DstRB.getID() != X86::GPRRegBankID)
565 return false;
566
567 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
568 if (!DstRC)
569 return false;
570
571 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
572 if (!SrcRC)
573 return false;
574
575 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
576 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
577 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
578 return false;
579 }
580
581 if (DstRC == SrcRC) {
582 // Nothing to be done
583 } else if (DstRC == &X86::GR32RegClass) {
584 I.getOperand(1).setSubReg(X86::sub_32bit);
585 } else if (DstRC == &X86::GR16RegClass) {
586 I.getOperand(1).setSubReg(X86::sub_16bit);
587 } else if (DstRC == &X86::GR8RegClass) {
588 I.getOperand(1).setSubReg(X86::sub_8bit);
589 } else {
590 return false;
591 }
592
593 I.setDesc(TII.get(X86::COPY));
594 return true;
595}
596
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000597InstructionSelector *
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000598llvm::createX86InstructionSelector(const X86TargetMachine &TM,
599 X86Subtarget &Subtarget,
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000600 X86RegisterBankInfo &RBI) {
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000601 return new X86InstructionSelector(TM, Subtarget, RBI);
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000602}