blob: 38f7bc0af5c7209e6154f1112145eca8bcbfdd8d [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
Igor Breger2452ef02017-05-01 07:06:08 +000058 // TODO: remove after suported by Tablegen-erated instruction selection.
Daniel Sanders0b5293f2017-04-06 09:49:34 +000059 unsigned getFAddOp(LLT &Ty, const RegisterBank &RB) const;
60 unsigned getFSubOp(LLT &Ty, const RegisterBank &RB) const;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000061 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
62 uint64_t Alignment) const;
63
64 bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI,
65 MachineFunction &MF) const;
66 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
67 MachineFunction &MF) const;
68 bool selectFrameIndex(MachineInstr &I, MachineRegisterInfo &MRI,
69 MachineFunction &MF) const;
Igor Breger3b97ea32017-04-12 12:54:54 +000070 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
71 MachineFunction &MF) const;
Igor Breger4fdf1e42017-04-19 11:34:59 +000072 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
73 MachineFunction &MF) const;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000074
Daniel Sanderse7b0d662017-04-21 15:59:56 +000075 const X86TargetMachine &TM;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000076 const X86Subtarget &STI;
77 const X86InstrInfo &TII;
78 const X86RegisterInfo &TRI;
79 const X86RegisterBankInfo &RBI;
Daniel Sanderse7b0d662017-04-21 15:59:56 +000080
Daniel Sanderse9fdba32017-04-29 17:30:09 +000081#define GET_GLOBALISEL_PREDICATES_DECL
82#include "X86GenGlobalISel.inc"
83#undef GET_GLOBALISEL_PREDICATES_DECL
Daniel Sanders0b5293f2017-04-06 09:49:34 +000084
85#define GET_GLOBALISEL_TEMPORARIES_DECL
86#include "X86GenGlobalISel.inc"
87#undef GET_GLOBALISEL_TEMPORARIES_DECL
88};
89
90} // end anonymous namespace
91
Daniel Sanders8a4bae92017-03-14 21:32:08 +000092#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000093#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +000094#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000095
Daniel Sanderse7b0d662017-04-21 15:59:56 +000096X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
97 const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +000098 const X86RegisterBankInfo &RBI)
Daniel Sanderse7b0d662017-04-21 15:59:56 +000099 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000100 TRI(*STI.getRegisterInfo()), RBI(RBI),
101#define GET_GLOBALISEL_PREDICATES_INIT
102#include "X86GenGlobalISel.inc"
103#undef GET_GLOBALISEL_PREDICATES_INIT
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000104#define GET_GLOBALISEL_TEMPORARIES_INIT
105#include "X86GenGlobalISel.inc"
106#undef GET_GLOBALISEL_TEMPORARIES_INIT
107{
108}
Igor Bregerf7359d82017-02-22 12:25:09 +0000109
110// FIXME: This should be target-independent, inferred from the types declared
111// for each class in the bank.
112static const TargetRegisterClass *
113getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
114 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger4fdf1e42017-04-19 11:34:59 +0000115 if (Ty.getSizeInBits() <= 8)
116 return &X86::GR8RegClass;
117 if (Ty.getSizeInBits() == 16)
118 return &X86::GR16RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000119 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000120 return &X86::GR32RegClass;
121 if (Ty.getSizeInBits() == 64)
122 return &X86::GR64RegClass;
123 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000124 if (RB.getID() == X86::VECRRegBankID) {
125 if (Ty.getSizeInBits() == 32)
126 return &X86::FR32XRegClass;
127 if (Ty.getSizeInBits() == 64)
128 return &X86::FR64XRegClass;
129 if (Ty.getSizeInBits() == 128)
130 return &X86::VR128XRegClass;
131 if (Ty.getSizeInBits() == 256)
132 return &X86::VR256XRegClass;
133 if (Ty.getSizeInBits() == 512)
134 return &X86::VR512RegClass;
135 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000136
137 llvm_unreachable("Unknown RegBank!");
138}
139
140// Set X86 Opcode and constrain DestReg.
141static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
142 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
143 const RegisterBankInfo &RBI) {
144
145 unsigned DstReg = I.getOperand(0).getReg();
146 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
147 assert(I.isCopy() && "Generic operators do not allow physical registers");
148 return true;
149 }
150
151 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
152 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
153 unsigned SrcReg = I.getOperand(1).getReg();
154 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
Igor Breger360d0f22017-04-27 08:02:03 +0000155
Igor Bregerf7359d82017-02-22 12:25:09 +0000156 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
157 "No phys reg on generic operators");
158 assert((DstSize == SrcSize ||
159 // Copies are a mean to setup initial types, the number of
160 // bits may not exactly match.
161 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
162 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
163 "Copy with different width?!");
164
165 const TargetRegisterClass *RC = nullptr;
166
167 switch (RegBank.getID()) {
168 case X86::GPRRegBankID:
169 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
170 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
Igor Breger360d0f22017-04-27 08:02:03 +0000171
172 // Change the physical register
173 if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
174 if (RC == &X86::GR32RegClass)
175 I.getOperand(1).setSubReg(X86::sub_32bit);
176 else if (RC == &X86::GR16RegClass)
177 I.getOperand(1).setSubReg(X86::sub_16bit);
178 else if (RC == &X86::GR8RegClass)
179 I.getOperand(1).setSubReg(X86::sub_8bit);
180
181 I.getOperand(1).substPhysReg(SrcReg, TRI);
182 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000183 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000184 case X86::VECRRegBankID:
185 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
186 break;
Igor Bregerf7359d82017-02-22 12:25:09 +0000187 default:
188 llvm_unreachable("Unknown RegBank!");
189 }
190
191 // No need to constrain SrcReg. It will get constrained when
192 // we hit another of its use or its defs.
193 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000194 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000195 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
196 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000197 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
198 << " operand\n");
199 return false;
200 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000201 }
202 I.setDesc(TII.get(X86::COPY));
203 return true;
204}
205
206bool X86InstructionSelector::select(MachineInstr &I) const {
207 assert(I.getParent() && "Instruction should be in a basic block!");
208 assert(I.getParent()->getParent() && "Instruction should be in a function!");
209
210 MachineBasicBlock &MBB = *I.getParent();
211 MachineFunction &MF = *MBB.getParent();
212 MachineRegisterInfo &MRI = MF.getRegInfo();
213
214 unsigned Opcode = I.getOpcode();
215 if (!isPreISelGenericOpcode(Opcode)) {
216 // Certain non-generic instructions also need some special handling.
217
218 if (I.isCopy())
219 return selectCopy(I, TII, MRI, TRI, RBI);
220
221 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
222 return true;
223 }
224
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000225 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
226 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000227
Igor Breger2452ef02017-05-01 07:06:08 +0000228 if (selectImpl(I))
229 return true;
230
231 DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
232
233 // TODO: This should be implemented by tblgen.
Igor Bregera8ba5722017-03-23 15:25:57 +0000234 if (selectBinaryOp(I, MRI, MF))
235 return true;
236 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000237 return true;
Igor Breger531a2032017-03-26 08:11:12 +0000238 if (selectFrameIndex(I, MRI, MF))
239 return true;
Igor Breger3b97ea32017-04-12 12:54:54 +0000240 if (selectConstant(I, MRI, MF))
241 return true;
Igor Breger4fdf1e42017-04-19 11:34:59 +0000242 if (selectTrunc(I, MRI, MF))
243 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000244
Igor Breger2452ef02017-05-01 07:06:08 +0000245 return false;
Igor Bregerf7359d82017-02-22 12:25:09 +0000246}
Igor Breger321cf3c2017-03-03 08:06:46 +0000247
248unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
249 const RegisterBank &RB) const {
250
251 if (X86::VECRRegBankID != RB.getID())
252 return TargetOpcode::G_FADD;
253
254 if (Ty == LLT::scalar(32)) {
255 if (STI.hasAVX512()) {
256 return X86::VADDSSZrr;
257 } else if (STI.hasAVX()) {
258 return X86::VADDSSrr;
259 } else if (STI.hasSSE1()) {
260 return X86::ADDSSrr;
261 }
262 } else if (Ty == LLT::scalar(64)) {
263 if (STI.hasAVX512()) {
264 return X86::VADDSDZrr;
265 } else if (STI.hasAVX()) {
266 return X86::VADDSDrr;
267 } else if (STI.hasSSE2()) {
268 return X86::ADDSDrr;
269 }
270 } else if (Ty == LLT::vector(4, 32)) {
271 if ((STI.hasAVX512()) && (STI.hasVLX())) {
272 return X86::VADDPSZ128rr;
273 } else if (STI.hasAVX()) {
274 return X86::VADDPSrr;
275 } else if (STI.hasSSE1()) {
276 return X86::ADDPSrr;
277 }
278 }
279
280 return TargetOpcode::G_FADD;
281}
282
283unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
284 const RegisterBank &RB) const {
285
286 if (X86::VECRRegBankID != RB.getID())
287 return TargetOpcode::G_FSUB;
288
289 if (Ty == LLT::scalar(32)) {
290 if (STI.hasAVX512()) {
291 return X86::VSUBSSZrr;
292 } else if (STI.hasAVX()) {
293 return X86::VSUBSSrr;
294 } else if (STI.hasSSE1()) {
295 return X86::SUBSSrr;
296 }
297 } else if (Ty == LLT::scalar(64)) {
298 if (STI.hasAVX512()) {
299 return X86::VSUBSDZrr;
300 } else if (STI.hasAVX()) {
301 return X86::VSUBSDrr;
302 } else if (STI.hasSSE2()) {
303 return X86::SUBSDrr;
304 }
305 } else if (Ty == LLT::vector(4, 32)) {
306 if ((STI.hasAVX512()) && (STI.hasVLX())) {
307 return X86::VSUBPSZ128rr;
308 } else if (STI.hasAVX()) {
309 return X86::VSUBPSrr;
310 } else if (STI.hasSSE1()) {
311 return X86::SUBPSrr;
312 }
313 }
314
315 return TargetOpcode::G_FSUB;
316}
317
Igor Breger321cf3c2017-03-03 08:06:46 +0000318bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
Igor Bregera8ba5722017-03-23 15:25:57 +0000319 MachineRegisterInfo &MRI,
320 MachineFunction &MF) const {
Igor Breger321cf3c2017-03-03 08:06:46 +0000321
Igor Breger321cf3c2017-03-03 08:06:46 +0000322 const unsigned DefReg = I.getOperand(0).getReg();
Igor Bregera8ba5722017-03-23 15:25:57 +0000323 LLT Ty = MRI.getType(DefReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000324 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
325
326 unsigned NewOpc = I.getOpcode();
327
Igor Bregera8ba5722017-03-23 15:25:57 +0000328 switch (NewOpc) {
Igor Breger321cf3c2017-03-03 08:06:46 +0000329 case TargetOpcode::G_FADD:
330 NewOpc = getFAddOp(Ty, RB);
331 break;
332 case TargetOpcode::G_FSUB:
333 NewOpc = getFSubOp(Ty, RB);
334 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000335 default:
336 break;
337 }
338
339 if (NewOpc == I.getOpcode())
340 return false;
341
342 I.setDesc(TII.get(NewOpc));
343
344 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
345}
Igor Bregera8ba5722017-03-23 15:25:57 +0000346
347unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
348 unsigned Opc,
349 uint64_t Alignment) const {
350 bool Isload = (Opc == TargetOpcode::G_LOAD);
351 bool HasAVX = STI.hasAVX();
352 bool HasAVX512 = STI.hasAVX512();
353 bool HasVLX = STI.hasVLX();
354
355 if (Ty == LLT::scalar(8)) {
356 if (X86::GPRRegBankID == RB.getID())
357 return Isload ? X86::MOV8rm : X86::MOV8mr;
358 } else if (Ty == LLT::scalar(16)) {
359 if (X86::GPRRegBankID == RB.getID())
360 return Isload ? X86::MOV16rm : X86::MOV16mr;
Igor Bregera9edb882017-05-01 06:08:32 +0000361 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000362 if (X86::GPRRegBankID == RB.getID())
363 return Isload ? X86::MOV32rm : X86::MOV32mr;
364 if (X86::VECRRegBankID == RB.getID())
365 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
366 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
367 : (HasAVX512 ? X86::VMOVSSZmr
368 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
Igor Bregera9edb882017-05-01 06:08:32 +0000369 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000370 if (X86::GPRRegBankID == RB.getID())
371 return Isload ? X86::MOV64rm : X86::MOV64mr;
372 if (X86::VECRRegBankID == RB.getID())
373 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
374 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
375 : (HasAVX512 ? X86::VMOVSDZmr
376 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
377 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
378 if (Alignment >= 16)
379 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
380 : HasAVX512
381 ? X86::VMOVAPSZ128rm_NOVLX
382 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
383 : (HasVLX ? X86::VMOVAPSZ128mr
384 : HasAVX512
385 ? X86::VMOVAPSZ128mr_NOVLX
386 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
387 else
388 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
389 : HasAVX512
390 ? X86::VMOVUPSZ128rm_NOVLX
391 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
392 : (HasVLX ? X86::VMOVUPSZ128mr
393 : HasAVX512
394 ? X86::VMOVUPSZ128mr_NOVLX
395 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
396 }
397 return Opc;
398}
399
400bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
401 MachineRegisterInfo &MRI,
402 MachineFunction &MF) const {
403
404 unsigned Opc = I.getOpcode();
405
406 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
407 return false;
408
409 const unsigned DefReg = I.getOperand(0).getReg();
410 LLT Ty = MRI.getType(DefReg);
411 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
412
413 auto &MemOp = **I.memoperands_begin();
414 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
415 if (NewOpc == Opc)
416 return false;
417
418 I.setDesc(TII.get(NewOpc));
419 MachineInstrBuilder MIB(MF, I);
420 if (Opc == TargetOpcode::G_LOAD)
421 addOffset(MIB, 0);
422 else {
423 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
424 I.RemoveOperand(0);
425 addOffset(MIB, 0).addUse(DefReg);
426 }
427 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
428}
429
Igor Breger531a2032017-03-26 08:11:12 +0000430bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
431 MachineRegisterInfo &MRI,
432 MachineFunction &MF) const {
433 if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX)
434 return false;
435
436 const unsigned DefReg = I.getOperand(0).getReg();
437 LLT Ty = MRI.getType(DefReg);
438
439 // Use LEA to calculate frame index.
440 unsigned NewOpc;
441 if (Ty == LLT::pointer(0, 64))
442 NewOpc = X86::LEA64r;
443 else if (Ty == LLT::pointer(0, 32))
444 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
445 else
446 llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type.");
447
448 I.setDesc(TII.get(NewOpc));
449 MachineInstrBuilder MIB(MF, I);
450 addOffset(MIB, 0);
451
452 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
453}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000454
Igor Breger3b97ea32017-04-12 12:54:54 +0000455bool X86InstructionSelector::selectConstant(MachineInstr &I,
456 MachineRegisterInfo &MRI,
457 MachineFunction &MF) const {
458 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
459 return false;
460
461 const unsigned DefReg = I.getOperand(0).getReg();
462 LLT Ty = MRI.getType(DefReg);
463
464 assert(Ty.isScalar() && "invalid element type.");
465
466 uint64_t Val = 0;
467 if (I.getOperand(1).isCImm()) {
468 Val = I.getOperand(1).getCImm()->getZExtValue();
469 I.getOperand(1).ChangeToImmediate(Val);
470 } else if (I.getOperand(1).isImm()) {
471 Val = I.getOperand(1).getImm();
472 } else
473 llvm_unreachable("Unsupported operand type.");
474
475 unsigned NewOpc;
476 switch (Ty.getSizeInBits()) {
477 case 8:
478 NewOpc = X86::MOV8ri;
479 break;
480 case 16:
481 NewOpc = X86::MOV16ri;
482 break;
483 case 32:
484 NewOpc = X86::MOV32ri;
485 break;
486 case 64: {
487 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
488 if (isInt<32>(Val))
489 NewOpc = X86::MOV64ri32;
490 else
491 NewOpc = X86::MOV64ri;
492 break;
493 }
494 default:
495 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
496 }
497
498 I.setDesc(TII.get(NewOpc));
499 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
500}
501
Igor Breger4fdf1e42017-04-19 11:34:59 +0000502bool X86InstructionSelector::selectTrunc(MachineInstr &I,
503 MachineRegisterInfo &MRI,
504 MachineFunction &MF) const {
505 if (I.getOpcode() != TargetOpcode::G_TRUNC)
506 return false;
507
508 const unsigned DstReg = I.getOperand(0).getReg();
509 const unsigned SrcReg = I.getOperand(1).getReg();
510
511 const LLT DstTy = MRI.getType(DstReg);
512 const LLT SrcTy = MRI.getType(SrcReg);
513
514 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
515 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
516
517 if (DstRB.getID() != SrcRB.getID()) {
518 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
519 return false;
520 }
521
522 if (DstRB.getID() != X86::GPRRegBankID)
523 return false;
524
525 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
526 if (!DstRC)
527 return false;
528
529 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
530 if (!SrcRC)
531 return false;
532
533 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
534 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
535 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
536 return false;
537 }
538
539 if (DstRC == SrcRC) {
540 // Nothing to be done
541 } else if (DstRC == &X86::GR32RegClass) {
542 I.getOperand(1).setSubReg(X86::sub_32bit);
543 } else if (DstRC == &X86::GR16RegClass) {
544 I.getOperand(1).setSubReg(X86::sub_16bit);
545 } else if (DstRC == &X86::GR8RegClass) {
546 I.getOperand(1).setSubReg(X86::sub_8bit);
547 } else {
548 return false;
549 }
550
551 I.setDesc(TII.get(X86::COPY));
552 return true;
553}
554
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000555InstructionSelector *
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000556llvm::createX86InstructionSelector(const X86TargetMachine &TM,
557 X86Subtarget &Subtarget,
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000558 X86RegisterBankInfo &RBI) {
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000559 return new X86InstructionSelector(TM, Subtarget, RBI);
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000560}