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