blob: cfc26cceac5b4161bb6d651f0b8e938fc4d3e27d [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;
Igor Breger28f290f2017-05-17 12:48:08 +000075 bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
76 MachineFunction &MF) const;
Igor Breger1dcd5e82017-06-20 09:15:10 +000077 bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
78
79 const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
80 const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,
81 MachineRegisterInfo &MRI) const;
Igor Breger28f290f2017-05-17 12:48:08 +000082
Daniel Sanderse7b0d662017-04-21 15:59:56 +000083 const X86TargetMachine &TM;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000084 const X86Subtarget &STI;
85 const X86InstrInfo &TII;
86 const X86RegisterInfo &TRI;
87 const X86RegisterBankInfo &RBI;
Daniel Sanderse7b0d662017-04-21 15:59:56 +000088
Daniel Sanderse9fdba32017-04-29 17:30:09 +000089#define GET_GLOBALISEL_PREDICATES_DECL
90#include "X86GenGlobalISel.inc"
91#undef GET_GLOBALISEL_PREDICATES_DECL
Daniel Sanders0b5293f2017-04-06 09:49:34 +000092
93#define GET_GLOBALISEL_TEMPORARIES_DECL
94#include "X86GenGlobalISel.inc"
95#undef GET_GLOBALISEL_TEMPORARIES_DECL
96};
97
98} // end anonymous namespace
99
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000100#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000101#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000102#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000103
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000104X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
105 const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +0000106 const X86RegisterBankInfo &RBI)
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000107 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000108 TRI(*STI.getRegisterInfo()), RBI(RBI),
109#define GET_GLOBALISEL_PREDICATES_INIT
110#include "X86GenGlobalISel.inc"
111#undef GET_GLOBALISEL_PREDICATES_INIT
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000112#define GET_GLOBALISEL_TEMPORARIES_INIT
113#include "X86GenGlobalISel.inc"
114#undef GET_GLOBALISEL_TEMPORARIES_INIT
115{
116}
Igor Bregerf7359d82017-02-22 12:25:09 +0000117
118// FIXME: This should be target-independent, inferred from the types declared
119// for each class in the bank.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000120const TargetRegisterClass *
121X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000122 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger4fdf1e42017-04-19 11:34:59 +0000123 if (Ty.getSizeInBits() <= 8)
124 return &X86::GR8RegClass;
125 if (Ty.getSizeInBits() == 16)
126 return &X86::GR16RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000127 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000128 return &X86::GR32RegClass;
129 if (Ty.getSizeInBits() == 64)
130 return &X86::GR64RegClass;
131 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000132 if (RB.getID() == X86::VECRRegBankID) {
133 if (Ty.getSizeInBits() == 32)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000134 return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000135 if (Ty.getSizeInBits() == 64)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000136 return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000137 if (Ty.getSizeInBits() == 128)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000138 return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000139 if (Ty.getSizeInBits() == 256)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000140 return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000141 if (Ty.getSizeInBits() == 512)
142 return &X86::VR512RegClass;
143 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000144
145 llvm_unreachable("Unknown RegBank!");
146}
147
Igor Breger1dcd5e82017-06-20 09:15:10 +0000148const TargetRegisterClass *
149X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,
150 MachineRegisterInfo &MRI) const {
151 const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
152 return getRegClass(Ty, RegBank);
153}
154
Igor Bregerf7359d82017-02-22 12:25:09 +0000155// Set X86 Opcode and constrain DestReg.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000156bool X86InstructionSelector::selectCopy(MachineInstr &I,
157 MachineRegisterInfo &MRI) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000158
159 unsigned DstReg = I.getOperand(0).getReg();
160 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
161 assert(I.isCopy() && "Generic operators do not allow physical registers");
162 return true;
163 }
164
165 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
166 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
167 unsigned SrcReg = I.getOperand(1).getReg();
168 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
Igor Breger360d0f22017-04-27 08:02:03 +0000169
Igor Bregerf7359d82017-02-22 12:25:09 +0000170 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
171 "No phys reg on generic operators");
172 assert((DstSize == SrcSize ||
173 // Copies are a mean to setup initial types, the number of
174 // bits may not exactly match.
175 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
176 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
177 "Copy with different width?!");
178
179 const TargetRegisterClass *RC = nullptr;
180
181 switch (RegBank.getID()) {
182 case X86::GPRRegBankID:
183 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
Igor Breger1dcd5e82017-06-20 09:15:10 +0000184 RC = getRegClass(MRI.getType(DstReg), RegBank);
Igor Breger360d0f22017-04-27 08:02:03 +0000185
186 // Change the physical register
187 if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
188 if (RC == &X86::GR32RegClass)
189 I.getOperand(1).setSubReg(X86::sub_32bit);
190 else if (RC == &X86::GR16RegClass)
191 I.getOperand(1).setSubReg(X86::sub_16bit);
192 else if (RC == &X86::GR8RegClass)
193 I.getOperand(1).setSubReg(X86::sub_8bit);
194
195 I.getOperand(1).substPhysReg(SrcReg, TRI);
196 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000197 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000198 case X86::VECRRegBankID:
Igor Breger1dcd5e82017-06-20 09:15:10 +0000199 RC = getRegClass(MRI.getType(DstReg), RegBank);
Igor Breger321cf3c2017-03-03 08:06:46 +0000200 break;
Igor Bregerf7359d82017-02-22 12:25:09 +0000201 default:
202 llvm_unreachable("Unknown RegBank!");
203 }
204
205 // No need to constrain SrcReg. It will get constrained when
206 // we hit another of its use or its defs.
207 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000208 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000209 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
210 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000211 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
212 << " operand\n");
213 return false;
214 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000215 }
216 I.setDesc(TII.get(X86::COPY));
217 return true;
218}
219
220bool X86InstructionSelector::select(MachineInstr &I) const {
221 assert(I.getParent() && "Instruction should be in a basic block!");
222 assert(I.getParent()->getParent() && "Instruction should be in a function!");
223
224 MachineBasicBlock &MBB = *I.getParent();
225 MachineFunction &MF = *MBB.getParent();
226 MachineRegisterInfo &MRI = MF.getRegInfo();
227
228 unsigned Opcode = I.getOpcode();
229 if (!isPreISelGenericOpcode(Opcode)) {
230 // Certain non-generic instructions also need some special handling.
231
232 if (I.isCopy())
Igor Breger1dcd5e82017-06-20 09:15:10 +0000233 return selectCopy(I, MRI);
Igor Bregerf7359d82017-02-22 12:25:09 +0000234
235 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
236 return true;
237 }
238
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000239 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
240 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000241
Igor Breger2452ef02017-05-01 07:06:08 +0000242 if (selectImpl(I))
Igor Bregerfda31e62017-05-10 06:52:58 +0000243 return true;
Igor Breger2452ef02017-05-01 07:06:08 +0000244
245 DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
246
247 // TODO: This should be implemented by tblgen.
Igor Bregera8ba5722017-03-23 15:25:57 +0000248 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000249 return true;
Igor Breger810c6252017-05-08 09:40:43 +0000250 if (selectFrameIndexOrGep(I, MRI, MF))
Igor Breger531a2032017-03-26 08:11:12 +0000251 return true;
Igor Breger3b97ea32017-04-12 12:54:54 +0000252 if (selectConstant(I, MRI, MF))
253 return true;
Igor Breger4fdf1e42017-04-19 11:34:59 +0000254 if (selectTrunc(I, MRI, MF))
255 return true;
Igor Bregerfda31e62017-05-10 06:52:58 +0000256 if (selectZext(I, MRI, MF))
257 return true;
Igor Bregerc7b59772017-05-11 07:17:40 +0000258 if (selectCmp(I, MRI, MF))
259 return true;
Igor Breger28f290f2017-05-17 12:48:08 +0000260 if (selectUadde(I, MRI, MF))
261 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000262
Igor Breger2452ef02017-05-01 07:06:08 +0000263 return false;
Igor Bregerf7359d82017-02-22 12:25:09 +0000264}
Igor Breger321cf3c2017-03-03 08:06:46 +0000265
Igor Bregera8ba5722017-03-23 15:25:57 +0000266unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
267 unsigned Opc,
268 uint64_t Alignment) const {
269 bool Isload = (Opc == TargetOpcode::G_LOAD);
270 bool HasAVX = STI.hasAVX();
271 bool HasAVX512 = STI.hasAVX512();
272 bool HasVLX = STI.hasVLX();
273
274 if (Ty == LLT::scalar(8)) {
275 if (X86::GPRRegBankID == RB.getID())
276 return Isload ? X86::MOV8rm : X86::MOV8mr;
277 } else if (Ty == LLT::scalar(16)) {
278 if (X86::GPRRegBankID == RB.getID())
279 return Isload ? X86::MOV16rm : X86::MOV16mr;
Igor Bregera9edb882017-05-01 06:08:32 +0000280 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000281 if (X86::GPRRegBankID == RB.getID())
282 return Isload ? X86::MOV32rm : X86::MOV32mr;
283 if (X86::VECRRegBankID == RB.getID())
284 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
285 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
286 : (HasAVX512 ? X86::VMOVSSZmr
287 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
Igor Bregera9edb882017-05-01 06:08:32 +0000288 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000289 if (X86::GPRRegBankID == RB.getID())
290 return Isload ? X86::MOV64rm : X86::MOV64mr;
291 if (X86::VECRRegBankID == RB.getID())
292 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
293 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
294 : (HasAVX512 ? X86::VMOVSDZmr
295 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
296 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
297 if (Alignment >= 16)
298 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
299 : HasAVX512
300 ? X86::VMOVAPSZ128rm_NOVLX
301 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
302 : (HasVLX ? X86::VMOVAPSZ128mr
303 : HasAVX512
304 ? X86::VMOVAPSZ128mr_NOVLX
305 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
306 else
307 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
308 : HasAVX512
309 ? X86::VMOVUPSZ128rm_NOVLX
310 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
311 : (HasVLX ? X86::VMOVUPSZ128mr
312 : HasAVX512
313 ? X86::VMOVUPSZ128mr_NOVLX
314 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
Igor Breger617be6e2017-05-23 08:23:51 +0000315 } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
316 if (Alignment >= 32)
317 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
318 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
319 : X86::VMOVAPSYrm)
320 : (HasVLX ? X86::VMOVAPSZ256mr
321 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
322 : X86::VMOVAPSYmr);
323 else
324 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
325 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
326 : X86::VMOVUPSYrm)
327 : (HasVLX ? X86::VMOVUPSZ256mr
328 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
329 : X86::VMOVUPSYmr);
330 } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
331 if (Alignment >= 64)
332 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
333 else
334 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
Igor Bregera8ba5722017-03-23 15:25:57 +0000335 }
336 return Opc;
337}
338
Igor Bregerbd2deda2017-06-19 13:12:57 +0000339// Fill in an address from the given instruction.
340void X86SelectAddress(const MachineInstr &I, const MachineRegisterInfo &MRI,
341 X86AddressMode &AM) {
342
343 assert(I.getOperand(0).isReg() && "unsupported opperand.");
344 assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
345 "unsupported type.");
346
347 if (I.getOpcode() == TargetOpcode::G_GEP) {
348 if (auto COff = getConstantVRegVal(I.getOperand(2).getReg(), MRI)) {
349 int64_t Imm = *COff;
350 if (isInt<32>(Imm)) { // Check for displacement overflow.
351 AM.Disp = static_cast<int32_t>(Imm);
352 AM.Base.Reg = I.getOperand(1).getReg();
353 return;
354 }
355 }
356 } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
357 AM.Base.FrameIndex = I.getOperand(1).getIndex();
358 AM.BaseType = X86AddressMode::FrameIndexBase;
359 return;
360 }
361
362 // Default behavior.
363 AM.Base.Reg = I.getOperand(0).getReg();
364 return;
365}
366
Igor Bregera8ba5722017-03-23 15:25:57 +0000367bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
368 MachineRegisterInfo &MRI,
369 MachineFunction &MF) const {
370
371 unsigned Opc = I.getOpcode();
372
373 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
374 return false;
375
376 const unsigned DefReg = I.getOperand(0).getReg();
377 LLT Ty = MRI.getType(DefReg);
378 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
379
380 auto &MemOp = **I.memoperands_begin();
Igor Bregerbd2deda2017-06-19 13:12:57 +0000381 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
382 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
383 return false;
384 }
385
Igor Bregera8ba5722017-03-23 15:25:57 +0000386 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
387 if (NewOpc == Opc)
388 return false;
389
Igor Bregerbd2deda2017-06-19 13:12:57 +0000390 X86AddressMode AM;
391 X86SelectAddress(*MRI.getVRegDef(I.getOperand(1).getReg()), MRI, AM);
392
Igor Bregera8ba5722017-03-23 15:25:57 +0000393 I.setDesc(TII.get(NewOpc));
394 MachineInstrBuilder MIB(MF, I);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000395 if (Opc == TargetOpcode::G_LOAD) {
396 I.RemoveOperand(1);
397 addFullAddress(MIB, AM);
398 } else {
Igor Bregera8ba5722017-03-23 15:25:57 +0000399 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
Igor Bregerbd2deda2017-06-19 13:12:57 +0000400 I.RemoveOperand(1);
Igor Bregera8ba5722017-03-23 15:25:57 +0000401 I.RemoveOperand(0);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000402 addFullAddress(MIB, AM).addUse(DefReg);
Igor Bregera8ba5722017-03-23 15:25:57 +0000403 }
404 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
405}
406
Igor Breger810c6252017-05-08 09:40:43 +0000407bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
408 MachineRegisterInfo &MRI,
409 MachineFunction &MF) const {
410 unsigned Opc = I.getOpcode();
411
412 if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
Igor Breger531a2032017-03-26 08:11:12 +0000413 return false;
414
415 const unsigned DefReg = I.getOperand(0).getReg();
416 LLT Ty = MRI.getType(DefReg);
417
Igor Breger810c6252017-05-08 09:40:43 +0000418 // Use LEA to calculate frame index and GEP
Igor Breger531a2032017-03-26 08:11:12 +0000419 unsigned NewOpc;
420 if (Ty == LLT::pointer(0, 64))
421 NewOpc = X86::LEA64r;
422 else if (Ty == LLT::pointer(0, 32))
423 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
424 else
Igor Breger810c6252017-05-08 09:40:43 +0000425 llvm_unreachable("Can't select G_FRAME_INDEX/G_GEP, unsupported type.");
Igor Breger531a2032017-03-26 08:11:12 +0000426
427 I.setDesc(TII.get(NewOpc));
428 MachineInstrBuilder MIB(MF, I);
Igor Breger810c6252017-05-08 09:40:43 +0000429
430 if (Opc == TargetOpcode::G_FRAME_INDEX) {
431 addOffset(MIB, 0);
432 } else {
433 MachineOperand &InxOp = I.getOperand(2);
434 I.addOperand(InxOp); // set IndexReg
435 InxOp.ChangeToImmediate(1); // set Scale
436 MIB.addImm(0).addReg(0);
437 }
Igor Breger531a2032017-03-26 08:11:12 +0000438
439 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
440}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000441
Igor Breger3b97ea32017-04-12 12:54:54 +0000442bool X86InstructionSelector::selectConstant(MachineInstr &I,
443 MachineRegisterInfo &MRI,
444 MachineFunction &MF) const {
445 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
446 return false;
447
448 const unsigned DefReg = I.getOperand(0).getReg();
449 LLT Ty = MRI.getType(DefReg);
450
451 assert(Ty.isScalar() && "invalid element type.");
452
453 uint64_t Val = 0;
454 if (I.getOperand(1).isCImm()) {
455 Val = I.getOperand(1).getCImm()->getZExtValue();
456 I.getOperand(1).ChangeToImmediate(Val);
457 } else if (I.getOperand(1).isImm()) {
458 Val = I.getOperand(1).getImm();
459 } else
460 llvm_unreachable("Unsupported operand type.");
461
462 unsigned NewOpc;
463 switch (Ty.getSizeInBits()) {
464 case 8:
465 NewOpc = X86::MOV8ri;
466 break;
467 case 16:
468 NewOpc = X86::MOV16ri;
469 break;
470 case 32:
471 NewOpc = X86::MOV32ri;
472 break;
473 case 64: {
474 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
475 if (isInt<32>(Val))
476 NewOpc = X86::MOV64ri32;
477 else
478 NewOpc = X86::MOV64ri;
479 break;
480 }
481 default:
482 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
483 }
484
485 I.setDesc(TII.get(NewOpc));
486 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
487}
488
Igor Breger4fdf1e42017-04-19 11:34:59 +0000489bool X86InstructionSelector::selectTrunc(MachineInstr &I,
490 MachineRegisterInfo &MRI,
491 MachineFunction &MF) const {
492 if (I.getOpcode() != TargetOpcode::G_TRUNC)
493 return false;
494
495 const unsigned DstReg = I.getOperand(0).getReg();
496 const unsigned SrcReg = I.getOperand(1).getReg();
497
498 const LLT DstTy = MRI.getType(DstReg);
499 const LLT SrcTy = MRI.getType(SrcReg);
500
501 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
502 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
503
504 if (DstRB.getID() != SrcRB.getID()) {
505 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
506 return false;
507 }
508
509 if (DstRB.getID() != X86::GPRRegBankID)
510 return false;
511
Igor Breger1dcd5e82017-06-20 09:15:10 +0000512 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000513 if (!DstRC)
514 return false;
515
Igor Breger1dcd5e82017-06-20 09:15:10 +0000516 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000517 if (!SrcRC)
518 return false;
519
Igor Breger014fc562017-05-21 11:13:56 +0000520 unsigned SubIdx;
521 if (DstRC == SrcRC) {
522 // Nothing to be done
523 SubIdx = X86::NoSubRegister;
524 } else if (DstRC == &X86::GR32RegClass) {
525 SubIdx = X86::sub_32bit;
526 } else if (DstRC == &X86::GR16RegClass) {
527 SubIdx = X86::sub_16bit;
528 } else if (DstRC == &X86::GR8RegClass) {
529 SubIdx = X86::sub_8bit;
530 } else {
531 return false;
532 }
533
534 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
535
Igor Breger4fdf1e42017-04-19 11:34:59 +0000536 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
537 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
538 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
539 return false;
540 }
541
Igor Breger014fc562017-05-21 11:13:56 +0000542 I.getOperand(1).setSubReg(SubIdx);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000543
544 I.setDesc(TII.get(X86::COPY));
545 return true;
546}
547
Igor Bregerfda31e62017-05-10 06:52:58 +0000548bool X86InstructionSelector::selectZext(MachineInstr &I,
549 MachineRegisterInfo &MRI,
550 MachineFunction &MF) const {
551 if (I.getOpcode() != TargetOpcode::G_ZEXT)
552 return false;
553
554 const unsigned DstReg = I.getOperand(0).getReg();
555 const unsigned SrcReg = I.getOperand(1).getReg();
556
557 const LLT DstTy = MRI.getType(DstReg);
558 const LLT SrcTy = MRI.getType(SrcReg);
559
560 if (SrcTy == LLT::scalar(1)) {
561
562 unsigned AndOpc;
563 if (DstTy == LLT::scalar(32))
564 AndOpc = X86::AND32ri8;
565 else if (DstTy == LLT::scalar(64))
566 AndOpc = X86::AND64ri8;
567 else
568 return false;
569
570 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
Igor Breger1dcd5e82017-06-20 09:15:10 +0000571 unsigned DefReg = MRI.createVirtualRegister(getRegClass(DstTy, RegBank));
Igor Bregerfda31e62017-05-10 06:52:58 +0000572
573 BuildMI(*I.getParent(), I, I.getDebugLoc(),
574 TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
575 .addImm(0)
576 .addReg(SrcReg)
577 .addImm(X86::sub_8bit);
578
579 MachineInstr &AndInst =
580 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
581 .addReg(DefReg)
582 .addImm(1);
583
584 constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
585
586 I.eraseFromParent();
587 return true;
588 }
589
590 return false;
591}
592
Igor Bregerc7b59772017-05-11 07:17:40 +0000593bool X86InstructionSelector::selectCmp(MachineInstr &I,
594 MachineRegisterInfo &MRI,
595 MachineFunction &MF) const {
596 if (I.getOpcode() != TargetOpcode::G_ICMP)
597 return false;
598
599 X86::CondCode CC;
600 bool SwapArgs;
601 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
602 (CmpInst::Predicate)I.getOperand(1).getPredicate());
603 unsigned OpSet = X86::getSETFromCond(CC);
604
605 unsigned LHS = I.getOperand(2).getReg();
606 unsigned RHS = I.getOperand(3).getReg();
607
608 if (SwapArgs)
609 std::swap(LHS, RHS);
610
611 unsigned OpCmp;
612 LLT Ty = MRI.getType(LHS);
613
614 switch (Ty.getSizeInBits()) {
615 default:
616 return false;
617 case 8:
618 OpCmp = X86::CMP8rr;
619 break;
620 case 16:
621 OpCmp = X86::CMP16rr;
622 break;
623 case 32:
624 OpCmp = X86::CMP32rr;
625 break;
626 case 64:
627 OpCmp = X86::CMP64rr;
628 break;
629 }
630
631 MachineInstr &CmpInst =
632 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
633 .addReg(LHS)
634 .addReg(RHS);
635
636 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
637 TII.get(OpSet), I.getOperand(0).getReg());
638
639 constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
640 constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
641
642 I.eraseFromParent();
643 return true;
644}
645
Igor Breger28f290f2017-05-17 12:48:08 +0000646bool X86InstructionSelector::selectUadde(MachineInstr &I,
647 MachineRegisterInfo &MRI,
648 MachineFunction &MF) const {
649 if (I.getOpcode() != TargetOpcode::G_UADDE)
650 return false;
651
652 const unsigned DstReg = I.getOperand(0).getReg();
653 const unsigned CarryOutReg = I.getOperand(1).getReg();
654 const unsigned Op0Reg = I.getOperand(2).getReg();
655 const unsigned Op1Reg = I.getOperand(3).getReg();
656 unsigned CarryInReg = I.getOperand(4).getReg();
657
658 const LLT DstTy = MRI.getType(DstReg);
659
660 if (DstTy != LLT::scalar(32))
661 return false;
662
663 // find CarryIn def instruction.
664 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
665 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
666 CarryInReg = Def->getOperand(1).getReg();
667 Def = MRI.getVRegDef(CarryInReg);
668 }
669
670 unsigned Opcode;
671 if (Def->getOpcode() == TargetOpcode::G_UADDE) {
672 // carry set by prev ADD.
673
674 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
675 .addReg(CarryInReg);
676
677 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
678 return false;
679
680 Opcode = X86::ADC32rr;
681 } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
682 // carry is constant, support only 0.
683 if (*val != 0)
684 return false;
685
686 Opcode = X86::ADD32rr;
687 } else
688 return false;
689
690 MachineInstr &AddInst =
691 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
692 .addReg(Op0Reg)
693 .addReg(Op1Reg);
694
695 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
696 .addReg(X86::EFLAGS);
697
698 if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
699 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
700 return false;
701
702 I.eraseFromParent();
703 return true;
704}
705
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000706InstructionSelector *
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000707llvm::createX86InstructionSelector(const X86TargetMachine &TM,
708 X86Subtarget &Subtarget,
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000709 X86RegisterBankInfo &RBI) {
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000710 return new X86InstructionSelector(TM, Subtarget, RBI);
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000711}