blob: 35da6c05caf903fc2557957c5a37bad84c84137c [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 Breger28f290f2017-05-17 12:48:08 +000022#include "llvm/CodeGen/GlobalISel/Utils.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000023#include "llvm/CodeGen/MachineBasicBlock.h"
24#include "llvm/CodeGen/MachineFunction.h"
25#include "llvm/CodeGen/MachineInstr.h"
26#include "llvm/CodeGen/MachineInstrBuilder.h"
Daniel Sanders0b5293f2017-04-06 09:49:34 +000027#include "llvm/CodeGen/MachineOperand.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000028#include "llvm/CodeGen/MachineRegisterInfo.h"
29#include "llvm/IR/Type.h"
30#include "llvm/Support/Debug.h"
31#include "llvm/Support/raw_ostream.h"
32
33#define DEBUG_TYPE "X86-isel"
34
35using namespace llvm;
36
37#ifndef LLVM_BUILD_GLOBAL_ISEL
38#error "You shouldn't build this"
39#endif
40
Daniel Sanders0b5293f2017-04-06 09:49:34 +000041namespace {
42
Daniel Sanderse7b0d662017-04-21 15:59:56 +000043#define GET_GLOBALISEL_PREDICATE_BITSET
44#include "X86GenGlobalISel.inc"
45#undef GET_GLOBALISEL_PREDICATE_BITSET
46
Daniel Sanders0b5293f2017-04-06 09:49:34 +000047class X86InstructionSelector : public InstructionSelector {
48public:
Daniel Sanderse7b0d662017-04-21 15:59:56 +000049 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
Daniel Sanders0b5293f2017-04-06 09:49:34 +000050 const X86RegisterBankInfo &RBI);
51
52 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
Igor Breger2452ef02017-05-01 07:06:08 +000059 // TODO: remove after suported by Tablegen-erated instruction selection.
Daniel Sanders0b5293f2017-04-06 09:49:34 +000060 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
61 uint64_t Alignment) const;
62
Daniel Sanders0b5293f2017-04-06 09:49:34 +000063 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
64 MachineFunction &MF) const;
Igor Breger810c6252017-05-08 09:40:43 +000065 bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
66 MachineFunction &MF) const;
Igor Breger3b97ea32017-04-12 12:54:54 +000067 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
68 MachineFunction &MF) const;
Igor Breger4fdf1e42017-04-19 11:34:59 +000069 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
70 MachineFunction &MF) const;
Igor Bregerfda31e62017-05-10 06:52:58 +000071 bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
72 MachineFunction &MF) const;
Igor Bregerc7b59772017-05-11 07:17:40 +000073 bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
74 MachineFunction &MF) const;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000075
Igor Breger28f290f2017-05-17 12:48:08 +000076 bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
77 MachineFunction &MF) const;
78
Daniel Sanderse7b0d662017-04-21 15:59:56 +000079 const X86TargetMachine &TM;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000080 const X86Subtarget &STI;
81 const X86InstrInfo &TII;
82 const X86RegisterInfo &TRI;
83 const X86RegisterBankInfo &RBI;
Daniel Sanderse7b0d662017-04-21 15:59:56 +000084
Daniel Sanderse9fdba32017-04-29 17:30:09 +000085#define GET_GLOBALISEL_PREDICATES_DECL
86#include "X86GenGlobalISel.inc"
87#undef GET_GLOBALISEL_PREDICATES_DECL
Daniel Sanders0b5293f2017-04-06 09:49:34 +000088
89#define GET_GLOBALISEL_TEMPORARIES_DECL
90#include "X86GenGlobalISel.inc"
91#undef GET_GLOBALISEL_TEMPORARIES_DECL
92};
93
94} // end anonymous namespace
95
Daniel Sanders8a4bae92017-03-14 21:32:08 +000096#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000097#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +000098#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000099
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000100X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
101 const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +0000102 const X86RegisterBankInfo &RBI)
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000103 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000104 TRI(*STI.getRegisterInfo()), RBI(RBI),
105#define GET_GLOBALISEL_PREDICATES_INIT
106#include "X86GenGlobalISel.inc"
107#undef GET_GLOBALISEL_PREDICATES_INIT
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000108#define GET_GLOBALISEL_TEMPORARIES_INIT
109#include "X86GenGlobalISel.inc"
110#undef GET_GLOBALISEL_TEMPORARIES_INIT
111{
112}
Igor Bregerf7359d82017-02-22 12:25:09 +0000113
114// FIXME: This should be target-independent, inferred from the types declared
115// for each class in the bank.
116static const TargetRegisterClass *
117getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
118 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger4fdf1e42017-04-19 11:34:59 +0000119 if (Ty.getSizeInBits() <= 8)
120 return &X86::GR8RegClass;
121 if (Ty.getSizeInBits() == 16)
122 return &X86::GR16RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000123 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000124 return &X86::GR32RegClass;
125 if (Ty.getSizeInBits() == 64)
126 return &X86::GR64RegClass;
127 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000128 if (RB.getID() == X86::VECRRegBankID) {
129 if (Ty.getSizeInBits() == 32)
130 return &X86::FR32XRegClass;
131 if (Ty.getSizeInBits() == 64)
132 return &X86::FR64XRegClass;
133 if (Ty.getSizeInBits() == 128)
134 return &X86::VR128XRegClass;
135 if (Ty.getSizeInBits() == 256)
136 return &X86::VR256XRegClass;
137 if (Ty.getSizeInBits() == 512)
138 return &X86::VR512RegClass;
139 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000140
141 llvm_unreachable("Unknown RegBank!");
142}
143
144// Set X86 Opcode and constrain DestReg.
145static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
146 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
147 const RegisterBankInfo &RBI) {
148
149 unsigned DstReg = I.getOperand(0).getReg();
150 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
151 assert(I.isCopy() && "Generic operators do not allow physical registers");
152 return true;
153 }
154
155 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
156 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
157 unsigned SrcReg = I.getOperand(1).getReg();
158 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
Igor Breger360d0f22017-04-27 08:02:03 +0000159
Igor Bregerf7359d82017-02-22 12:25:09 +0000160 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);
Igor Breger360d0f22017-04-27 08:02:03 +0000175
176 // Change the physical register
177 if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
178 if (RC == &X86::GR32RegClass)
179 I.getOperand(1).setSubReg(X86::sub_32bit);
180 else if (RC == &X86::GR16RegClass)
181 I.getOperand(1).setSubReg(X86::sub_16bit);
182 else if (RC == &X86::GR8RegClass)
183 I.getOperand(1).setSubReg(X86::sub_8bit);
184
185 I.getOperand(1).substPhysReg(SrcReg, TRI);
186 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000187 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000188 case X86::VECRRegBankID:
189 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
190 break;
Igor Bregerf7359d82017-02-22 12:25:09 +0000191 default:
192 llvm_unreachable("Unknown RegBank!");
193 }
194
195 // No need to constrain SrcReg. It will get constrained when
196 // we hit another of its use or its defs.
197 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000198 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000199 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
200 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000201 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
202 << " operand\n");
203 return false;
204 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000205 }
206 I.setDesc(TII.get(X86::COPY));
207 return true;
208}
209
210bool X86InstructionSelector::select(MachineInstr &I) const {
211 assert(I.getParent() && "Instruction should be in a basic block!");
212 assert(I.getParent()->getParent() && "Instruction should be in a function!");
213
214 MachineBasicBlock &MBB = *I.getParent();
215 MachineFunction &MF = *MBB.getParent();
216 MachineRegisterInfo &MRI = MF.getRegInfo();
217
218 unsigned Opcode = I.getOpcode();
219 if (!isPreISelGenericOpcode(Opcode)) {
220 // Certain non-generic instructions also need some special handling.
221
222 if (I.isCopy())
223 return selectCopy(I, TII, MRI, TRI, RBI);
224
225 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
226 return true;
227 }
228
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000229 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
230 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000231
Igor Breger2452ef02017-05-01 07:06:08 +0000232 if (selectImpl(I))
Igor Bregerfda31e62017-05-10 06:52:58 +0000233 return true;
Igor Breger2452ef02017-05-01 07:06:08 +0000234
235 DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
236
237 // TODO: This should be implemented by tblgen.
Igor Bregera8ba5722017-03-23 15:25:57 +0000238 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000239 return true;
Igor Breger810c6252017-05-08 09:40:43 +0000240 if (selectFrameIndexOrGep(I, MRI, MF))
Igor Breger531a2032017-03-26 08:11:12 +0000241 return true;
Igor Breger3b97ea32017-04-12 12:54:54 +0000242 if (selectConstant(I, MRI, MF))
243 return true;
Igor Breger4fdf1e42017-04-19 11:34:59 +0000244 if (selectTrunc(I, MRI, MF))
245 return true;
Igor Bregerfda31e62017-05-10 06:52:58 +0000246 if (selectZext(I, MRI, MF))
247 return true;
Igor Bregerc7b59772017-05-11 07:17:40 +0000248 if (selectCmp(I, MRI, MF))
249 return true;
Igor Breger28f290f2017-05-17 12:48:08 +0000250 if (selectUadde(I, MRI, MF))
251 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000252
Igor Breger2452ef02017-05-01 07:06:08 +0000253 return false;
Igor Bregerf7359d82017-02-22 12:25:09 +0000254}
Igor Breger321cf3c2017-03-03 08:06:46 +0000255
Igor Bregera8ba5722017-03-23 15:25:57 +0000256unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
257 unsigned Opc,
258 uint64_t Alignment) const {
259 bool Isload = (Opc == TargetOpcode::G_LOAD);
260 bool HasAVX = STI.hasAVX();
261 bool HasAVX512 = STI.hasAVX512();
262 bool HasVLX = STI.hasVLX();
263
264 if (Ty == LLT::scalar(8)) {
265 if (X86::GPRRegBankID == RB.getID())
266 return Isload ? X86::MOV8rm : X86::MOV8mr;
267 } else if (Ty == LLT::scalar(16)) {
268 if (X86::GPRRegBankID == RB.getID())
269 return Isload ? X86::MOV16rm : X86::MOV16mr;
Igor Bregera9edb882017-05-01 06:08:32 +0000270 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000271 if (X86::GPRRegBankID == RB.getID())
272 return Isload ? X86::MOV32rm : X86::MOV32mr;
273 if (X86::VECRRegBankID == RB.getID())
274 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
275 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
276 : (HasAVX512 ? X86::VMOVSSZmr
277 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
Igor Bregera9edb882017-05-01 06:08:32 +0000278 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000279 if (X86::GPRRegBankID == RB.getID())
280 return Isload ? X86::MOV64rm : X86::MOV64mr;
281 if (X86::VECRRegBankID == RB.getID())
282 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
283 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
284 : (HasAVX512 ? X86::VMOVSDZmr
285 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
286 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
287 if (Alignment >= 16)
288 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
289 : HasAVX512
290 ? X86::VMOVAPSZ128rm_NOVLX
291 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
292 : (HasVLX ? X86::VMOVAPSZ128mr
293 : HasAVX512
294 ? X86::VMOVAPSZ128mr_NOVLX
295 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
296 else
297 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
298 : HasAVX512
299 ? X86::VMOVUPSZ128rm_NOVLX
300 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
301 : (HasVLX ? X86::VMOVUPSZ128mr
302 : HasAVX512
303 ? X86::VMOVUPSZ128mr_NOVLX
304 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
Igor Breger617be6e2017-05-23 08:23:51 +0000305 } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
306 if (Alignment >= 32)
307 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
308 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
309 : X86::VMOVAPSYrm)
310 : (HasVLX ? X86::VMOVAPSZ256mr
311 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
312 : X86::VMOVAPSYmr);
313 else
314 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
315 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
316 : X86::VMOVUPSYrm)
317 : (HasVLX ? X86::VMOVUPSZ256mr
318 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
319 : X86::VMOVUPSYmr);
320 } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
321 if (Alignment >= 64)
322 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
323 else
324 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
Igor Bregera8ba5722017-03-23 15:25:57 +0000325 }
326 return Opc;
327}
328
Igor Bregerbd2deda2017-06-19 13:12:57 +0000329// Fill in an address from the given instruction.
330void X86SelectAddress(const MachineInstr &I, const MachineRegisterInfo &MRI,
331 X86AddressMode &AM) {
332
333 assert(I.getOperand(0).isReg() && "unsupported opperand.");
334 assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
335 "unsupported type.");
336
337 if (I.getOpcode() == TargetOpcode::G_GEP) {
338 if (auto COff = getConstantVRegVal(I.getOperand(2).getReg(), MRI)) {
339 int64_t Imm = *COff;
340 if (isInt<32>(Imm)) { // Check for displacement overflow.
341 AM.Disp = static_cast<int32_t>(Imm);
342 AM.Base.Reg = I.getOperand(1).getReg();
343 return;
344 }
345 }
346 } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
347 AM.Base.FrameIndex = I.getOperand(1).getIndex();
348 AM.BaseType = X86AddressMode::FrameIndexBase;
349 return;
350 }
351
352 // Default behavior.
353 AM.Base.Reg = I.getOperand(0).getReg();
354 return;
355}
356
Igor Bregera8ba5722017-03-23 15:25:57 +0000357bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
358 MachineRegisterInfo &MRI,
359 MachineFunction &MF) const {
360
361 unsigned Opc = I.getOpcode();
362
363 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
364 return false;
365
366 const unsigned DefReg = I.getOperand(0).getReg();
367 LLT Ty = MRI.getType(DefReg);
368 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
369
370 auto &MemOp = **I.memoperands_begin();
Igor Bregerbd2deda2017-06-19 13:12:57 +0000371 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
372 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
373 return false;
374 }
375
Igor Bregera8ba5722017-03-23 15:25:57 +0000376 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
377 if (NewOpc == Opc)
378 return false;
379
Igor Bregerbd2deda2017-06-19 13:12:57 +0000380 X86AddressMode AM;
381 X86SelectAddress(*MRI.getVRegDef(I.getOperand(1).getReg()), MRI, AM);
382
Igor Bregera8ba5722017-03-23 15:25:57 +0000383 I.setDesc(TII.get(NewOpc));
384 MachineInstrBuilder MIB(MF, I);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000385 if (Opc == TargetOpcode::G_LOAD) {
386 I.RemoveOperand(1);
387 addFullAddress(MIB, AM);
388 } else {
Igor Bregera8ba5722017-03-23 15:25:57 +0000389 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
Igor Bregerbd2deda2017-06-19 13:12:57 +0000390 I.RemoveOperand(1);
Igor Bregera8ba5722017-03-23 15:25:57 +0000391 I.RemoveOperand(0);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000392 addFullAddress(MIB, AM).addUse(DefReg);
Igor Bregera8ba5722017-03-23 15:25:57 +0000393 }
394 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
395}
396
Igor Breger810c6252017-05-08 09:40:43 +0000397bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
398 MachineRegisterInfo &MRI,
399 MachineFunction &MF) const {
400 unsigned Opc = I.getOpcode();
401
402 if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
Igor Breger531a2032017-03-26 08:11:12 +0000403 return false;
404
405 const unsigned DefReg = I.getOperand(0).getReg();
406 LLT Ty = MRI.getType(DefReg);
407
Igor Breger810c6252017-05-08 09:40:43 +0000408 // Use LEA to calculate frame index and GEP
Igor Breger531a2032017-03-26 08:11:12 +0000409 unsigned NewOpc;
410 if (Ty == LLT::pointer(0, 64))
411 NewOpc = X86::LEA64r;
412 else if (Ty == LLT::pointer(0, 32))
413 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
414 else
Igor Breger810c6252017-05-08 09:40:43 +0000415 llvm_unreachable("Can't select G_FRAME_INDEX/G_GEP, unsupported type.");
Igor Breger531a2032017-03-26 08:11:12 +0000416
417 I.setDesc(TII.get(NewOpc));
418 MachineInstrBuilder MIB(MF, I);
Igor Breger810c6252017-05-08 09:40:43 +0000419
420 if (Opc == TargetOpcode::G_FRAME_INDEX) {
421 addOffset(MIB, 0);
422 } else {
423 MachineOperand &InxOp = I.getOperand(2);
424 I.addOperand(InxOp); // set IndexReg
425 InxOp.ChangeToImmediate(1); // set Scale
426 MIB.addImm(0).addReg(0);
427 }
Igor Breger531a2032017-03-26 08:11:12 +0000428
429 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
430}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000431
Igor Breger3b97ea32017-04-12 12:54:54 +0000432bool X86InstructionSelector::selectConstant(MachineInstr &I,
433 MachineRegisterInfo &MRI,
434 MachineFunction &MF) const {
435 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
436 return false;
437
438 const unsigned DefReg = I.getOperand(0).getReg();
439 LLT Ty = MRI.getType(DefReg);
440
441 assert(Ty.isScalar() && "invalid element type.");
442
443 uint64_t Val = 0;
444 if (I.getOperand(1).isCImm()) {
445 Val = I.getOperand(1).getCImm()->getZExtValue();
446 I.getOperand(1).ChangeToImmediate(Val);
447 } else if (I.getOperand(1).isImm()) {
448 Val = I.getOperand(1).getImm();
449 } else
450 llvm_unreachable("Unsupported operand type.");
451
452 unsigned NewOpc;
453 switch (Ty.getSizeInBits()) {
454 case 8:
455 NewOpc = X86::MOV8ri;
456 break;
457 case 16:
458 NewOpc = X86::MOV16ri;
459 break;
460 case 32:
461 NewOpc = X86::MOV32ri;
462 break;
463 case 64: {
464 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
465 if (isInt<32>(Val))
466 NewOpc = X86::MOV64ri32;
467 else
468 NewOpc = X86::MOV64ri;
469 break;
470 }
471 default:
472 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
473 }
474
475 I.setDesc(TII.get(NewOpc));
476 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
477}
478
Igor Breger4fdf1e42017-04-19 11:34:59 +0000479bool X86InstructionSelector::selectTrunc(MachineInstr &I,
480 MachineRegisterInfo &MRI,
481 MachineFunction &MF) const {
482 if (I.getOpcode() != TargetOpcode::G_TRUNC)
483 return false;
484
485 const unsigned DstReg = I.getOperand(0).getReg();
486 const unsigned SrcReg = I.getOperand(1).getReg();
487
488 const LLT DstTy = MRI.getType(DstReg);
489 const LLT SrcTy = MRI.getType(SrcReg);
490
491 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
492 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
493
494 if (DstRB.getID() != SrcRB.getID()) {
495 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
496 return false;
497 }
498
499 if (DstRB.getID() != X86::GPRRegBankID)
500 return false;
501
502 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
503 if (!DstRC)
504 return false;
505
506 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
507 if (!SrcRC)
508 return false;
509
Igor Breger014fc562017-05-21 11:13:56 +0000510 unsigned SubIdx;
511 if (DstRC == SrcRC) {
512 // Nothing to be done
513 SubIdx = X86::NoSubRegister;
514 } else if (DstRC == &X86::GR32RegClass) {
515 SubIdx = X86::sub_32bit;
516 } else if (DstRC == &X86::GR16RegClass) {
517 SubIdx = X86::sub_16bit;
518 } else if (DstRC == &X86::GR8RegClass) {
519 SubIdx = X86::sub_8bit;
520 } else {
521 return false;
522 }
523
524 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
525
Igor Breger4fdf1e42017-04-19 11:34:59 +0000526 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
527 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
528 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
529 return false;
530 }
531
Igor Breger014fc562017-05-21 11:13:56 +0000532 I.getOperand(1).setSubReg(SubIdx);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000533
534 I.setDesc(TII.get(X86::COPY));
535 return true;
536}
537
Igor Bregerfda31e62017-05-10 06:52:58 +0000538bool X86InstructionSelector::selectZext(MachineInstr &I,
539 MachineRegisterInfo &MRI,
540 MachineFunction &MF) const {
541 if (I.getOpcode() != TargetOpcode::G_ZEXT)
542 return false;
543
544 const unsigned DstReg = I.getOperand(0).getReg();
545 const unsigned SrcReg = I.getOperand(1).getReg();
546
547 const LLT DstTy = MRI.getType(DstReg);
548 const LLT SrcTy = MRI.getType(SrcReg);
549
550 if (SrcTy == LLT::scalar(1)) {
551
552 unsigned AndOpc;
553 if (DstTy == LLT::scalar(32))
554 AndOpc = X86::AND32ri8;
555 else if (DstTy == LLT::scalar(64))
556 AndOpc = X86::AND64ri8;
557 else
558 return false;
559
560 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
561 unsigned DefReg =
562 MRI.createVirtualRegister(getRegClassForTypeOnBank(DstTy, RegBank));
563
564 BuildMI(*I.getParent(), I, I.getDebugLoc(),
565 TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
566 .addImm(0)
567 .addReg(SrcReg)
568 .addImm(X86::sub_8bit);
569
570 MachineInstr &AndInst =
571 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
572 .addReg(DefReg)
573 .addImm(1);
574
575 constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
576
577 I.eraseFromParent();
578 return true;
579 }
580
581 return false;
582}
583
Igor Bregerc7b59772017-05-11 07:17:40 +0000584bool X86InstructionSelector::selectCmp(MachineInstr &I,
585 MachineRegisterInfo &MRI,
586 MachineFunction &MF) const {
587 if (I.getOpcode() != TargetOpcode::G_ICMP)
588 return false;
589
590 X86::CondCode CC;
591 bool SwapArgs;
592 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
593 (CmpInst::Predicate)I.getOperand(1).getPredicate());
594 unsigned OpSet = X86::getSETFromCond(CC);
595
596 unsigned LHS = I.getOperand(2).getReg();
597 unsigned RHS = I.getOperand(3).getReg();
598
599 if (SwapArgs)
600 std::swap(LHS, RHS);
601
602 unsigned OpCmp;
603 LLT Ty = MRI.getType(LHS);
604
605 switch (Ty.getSizeInBits()) {
606 default:
607 return false;
608 case 8:
609 OpCmp = X86::CMP8rr;
610 break;
611 case 16:
612 OpCmp = X86::CMP16rr;
613 break;
614 case 32:
615 OpCmp = X86::CMP32rr;
616 break;
617 case 64:
618 OpCmp = X86::CMP64rr;
619 break;
620 }
621
622 MachineInstr &CmpInst =
623 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
624 .addReg(LHS)
625 .addReg(RHS);
626
627 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
628 TII.get(OpSet), I.getOperand(0).getReg());
629
630 constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
631 constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
632
633 I.eraseFromParent();
634 return true;
635}
636
Igor Breger28f290f2017-05-17 12:48:08 +0000637bool X86InstructionSelector::selectUadde(MachineInstr &I,
638 MachineRegisterInfo &MRI,
639 MachineFunction &MF) const {
640 if (I.getOpcode() != TargetOpcode::G_UADDE)
641 return false;
642
643 const unsigned DstReg = I.getOperand(0).getReg();
644 const unsigned CarryOutReg = I.getOperand(1).getReg();
645 const unsigned Op0Reg = I.getOperand(2).getReg();
646 const unsigned Op1Reg = I.getOperand(3).getReg();
647 unsigned CarryInReg = I.getOperand(4).getReg();
648
649 const LLT DstTy = MRI.getType(DstReg);
650
651 if (DstTy != LLT::scalar(32))
652 return false;
653
654 // find CarryIn def instruction.
655 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
656 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
657 CarryInReg = Def->getOperand(1).getReg();
658 Def = MRI.getVRegDef(CarryInReg);
659 }
660
661 unsigned Opcode;
662 if (Def->getOpcode() == TargetOpcode::G_UADDE) {
663 // carry set by prev ADD.
664
665 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
666 .addReg(CarryInReg);
667
668 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
669 return false;
670
671 Opcode = X86::ADC32rr;
672 } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
673 // carry is constant, support only 0.
674 if (*val != 0)
675 return false;
676
677 Opcode = X86::ADD32rr;
678 } else
679 return false;
680
681 MachineInstr &AddInst =
682 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
683 .addReg(Op0Reg)
684 .addReg(Op1Reg);
685
686 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
687 .addReg(X86::EFLAGS);
688
689 if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
690 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
691 return false;
692
693 I.eraseFromParent();
694 return true;
695}
696
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000697InstructionSelector *
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000698llvm::createX86InstructionSelector(const X86TargetMachine &TM,
699 X86Subtarget &Subtarget,
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000700 X86RegisterBankInfo &RBI) {
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000701 return new X86InstructionSelector(TM, Subtarget, RBI);
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000702}