blob: b43f88232bc03205e93398bf3b07f8c806cc0ef4 [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
Daniel Sanders6ab0daa2017-07-04 14:35:06 +000035#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
36
Igor Bregerf7359d82017-02-22 12:25:09 +000037using namespace llvm;
38
Daniel Sanders0b5293f2017-04-06 09:49:34 +000039namespace {
40
Daniel Sanderse7b0d662017-04-21 15:59:56 +000041#define GET_GLOBALISEL_PREDICATE_BITSET
42#include "X86GenGlobalISel.inc"
43#undef GET_GLOBALISEL_PREDICATE_BITSET
44
Daniel Sanders0b5293f2017-04-06 09:49:34 +000045class X86InstructionSelector : public InstructionSelector {
46public:
Daniel Sanderse7b0d662017-04-21 15:59:56 +000047 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
Daniel Sanders0b5293f2017-04-06 09:49:34 +000048 const X86RegisterBankInfo &RBI);
49
50 bool select(MachineInstr &I) const override;
51
52private:
53 /// tblgen-erated 'select' implementation, used as the initial selector for
54 /// the patterns that don't require complex C++.
55 bool selectImpl(MachineInstr &I) const;
56
Hiroshi Inouebb703e82017-07-02 03:24:54 +000057 // TODO: remove after supported by Tablegen-erated instruction selection.
Daniel Sanders0b5293f2017-04-06 09:49:34 +000058 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
59 uint64_t Alignment) const;
60
Daniel Sanders0b5293f2017-04-06 09:49:34 +000061 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
62 MachineFunction &MF) const;
Igor Breger810c6252017-05-08 09:40:43 +000063 bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
64 MachineFunction &MF) const;
Igor Breger717bd362017-07-02 08:58:29 +000065 bool selectGlobalValue(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;
Igor Bregerb186a692017-07-02 08:15:49 +000078 bool selectUnmergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
79 MachineFunction &MF) const;
Igor Breger0cddd342017-06-29 12:08:28 +000080 bool selectMergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
81 MachineFunction &MF) const;
Igor Breger1c29be72017-06-22 09:43:35 +000082 bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,
83 MachineFunction &MF) const;
Igor Bregerf5035d62017-06-25 11:42:17 +000084 bool selectExtract(MachineInstr &I, MachineRegisterInfo &MRI,
85 MachineFunction &MF) const;
Igor Breger685889c2017-08-21 10:51:54 +000086 bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
87 MachineFunction &MF) const;
Igor Breger2661ae42017-09-04 09:06:45 +000088 bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const;
Igor Breger1c29be72017-06-22 09:43:35 +000089
90 // emit insert subreg instruction and insert it before MachineInstr &I
91 bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
92 MachineRegisterInfo &MRI, MachineFunction &MF) const;
Igor Bregerf5035d62017-06-25 11:42:17 +000093 // emit extract subreg instruction and insert it before MachineInstr &I
94 bool emitExtractSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
95 MachineRegisterInfo &MRI, MachineFunction &MF) const;
Igor Breger1dcd5e82017-06-20 09:15:10 +000096
97 const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
98 const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,
99 MachineRegisterInfo &MRI) const;
Igor Breger28f290f2017-05-17 12:48:08 +0000100
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000101 const X86TargetMachine &TM;
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000102 const X86Subtarget &STI;
103 const X86InstrInfo &TII;
104 const X86RegisterInfo &TRI;
105 const X86RegisterBankInfo &RBI;
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000106
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000107#define GET_GLOBALISEL_PREDICATES_DECL
108#include "X86GenGlobalISel.inc"
109#undef GET_GLOBALISEL_PREDICATES_DECL
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000110
111#define GET_GLOBALISEL_TEMPORARIES_DECL
112#include "X86GenGlobalISel.inc"
113#undef GET_GLOBALISEL_TEMPORARIES_DECL
114};
115
116} // end anonymous namespace
117
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000118#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000119#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000120#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000121
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000122X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
123 const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +0000124 const X86RegisterBankInfo &RBI)
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000125 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000126 TRI(*STI.getRegisterInfo()), RBI(RBI),
127#define GET_GLOBALISEL_PREDICATES_INIT
128#include "X86GenGlobalISel.inc"
129#undef GET_GLOBALISEL_PREDICATES_INIT
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000130#define GET_GLOBALISEL_TEMPORARIES_INIT
131#include "X86GenGlobalISel.inc"
132#undef GET_GLOBALISEL_TEMPORARIES_INIT
133{
134}
Igor Bregerf7359d82017-02-22 12:25:09 +0000135
136// FIXME: This should be target-independent, inferred from the types declared
137// for each class in the bank.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000138const TargetRegisterClass *
139X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000140 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger4fdf1e42017-04-19 11:34:59 +0000141 if (Ty.getSizeInBits() <= 8)
142 return &X86::GR8RegClass;
143 if (Ty.getSizeInBits() == 16)
144 return &X86::GR16RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000145 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000146 return &X86::GR32RegClass;
147 if (Ty.getSizeInBits() == 64)
148 return &X86::GR64RegClass;
149 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000150 if (RB.getID() == X86::VECRRegBankID) {
151 if (Ty.getSizeInBits() == 32)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000152 return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000153 if (Ty.getSizeInBits() == 64)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000154 return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000155 if (Ty.getSizeInBits() == 128)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000156 return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000157 if (Ty.getSizeInBits() == 256)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000158 return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000159 if (Ty.getSizeInBits() == 512)
160 return &X86::VR512RegClass;
161 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000162
163 llvm_unreachable("Unknown RegBank!");
164}
165
Igor Breger1dcd5e82017-06-20 09:15:10 +0000166const TargetRegisterClass *
167X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,
168 MachineRegisterInfo &MRI) const {
169 const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
170 return getRegClass(Ty, RegBank);
171}
172
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000173static unsigned getSubRegIndex(const TargetRegisterClass *RC) {
Igor Bregerb3a860a2017-08-20 07:14:40 +0000174 unsigned SubIdx = X86::NoSubRegister;
175 if (RC == &X86::GR32RegClass) {
176 SubIdx = X86::sub_32bit;
177 } else if (RC == &X86::GR16RegClass) {
178 SubIdx = X86::sub_16bit;
179 } else if (RC == &X86::GR8RegClass) {
180 SubIdx = X86::sub_8bit;
181 }
182
183 return SubIdx;
184}
185
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000186static const TargetRegisterClass *getRegClassFromGRPhysReg(unsigned Reg) {
Igor Bregerb3a860a2017-08-20 07:14:40 +0000187 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
188 if (X86::GR64RegClass.contains(Reg))
189 return &X86::GR64RegClass;
190 if (X86::GR32RegClass.contains(Reg))
191 return &X86::GR32RegClass;
192 if (X86::GR16RegClass.contains(Reg))
193 return &X86::GR16RegClass;
194 if (X86::GR8RegClass.contains(Reg))
195 return &X86::GR8RegClass;
196
197 llvm_unreachable("Unknown RegClass for PhysReg!");
198}
199
Igor Bregerf7359d82017-02-22 12:25:09 +0000200// Set X86 Opcode and constrain DestReg.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000201bool X86InstructionSelector::selectCopy(MachineInstr &I,
202 MachineRegisterInfo &MRI) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000203
204 unsigned DstReg = I.getOperand(0).getReg();
Igor Bregerb3a860a2017-08-20 07:14:40 +0000205 const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI);
206 const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
Igor Bregerf7359d82017-02-22 12:25:09 +0000207
Igor Bregerf7359d82017-02-22 12:25:09 +0000208 unsigned SrcReg = I.getOperand(1).getReg();
209 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
Igor Bregerb3a860a2017-08-20 07:14:40 +0000210 const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
211
212 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
213 assert(I.isCopy() && "Generic operators do not allow physical registers");
214
215 if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID &&
216 DstRegBank.getID() == X86::GPRRegBankID) {
217
218 const TargetRegisterClass *SrcRC =
219 getRegClass(MRI.getType(SrcReg), SrcRegBank);
220 const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg);
221
222 if (SrcRC != DstRC) {
223 // This case can be generated by ABI lowering, performe anyext
224 unsigned ExtSrc = MRI.createVirtualRegister(DstRC);
225 BuildMI(*I.getParent(), I, I.getDebugLoc(),
226 TII.get(TargetOpcode::SUBREG_TO_REG))
227 .addDef(ExtSrc)
228 .addImm(0)
229 .addReg(SrcReg)
230 .addImm(getSubRegIndex(SrcRC));
231
232 I.getOperand(1).setReg(ExtSrc);
233 }
234 }
235
236 return true;
237 }
Igor Breger360d0f22017-04-27 08:02:03 +0000238
Igor Bregerf7359d82017-02-22 12:25:09 +0000239 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
240 "No phys reg on generic operators");
241 assert((DstSize == SrcSize ||
242 // Copies are a mean to setup initial types, the number of
243 // bits may not exactly match.
244 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
245 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
246 "Copy with different width?!");
247
Igor Bregerb3a860a2017-08-20 07:14:40 +0000248 const TargetRegisterClass *DstRC =
249 getRegClass(MRI.getType(DstReg), DstRegBank);
Igor Bregerf7359d82017-02-22 12:25:09 +0000250
Igor Bregerb3a860a2017-08-20 07:14:40 +0000251 if (SrcRegBank.getID() == X86::GPRRegBankID &&
252 DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize &&
253 TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
254 // Change the physical register to performe truncate.
Igor Breger360d0f22017-04-27 08:02:03 +0000255
Igor Bregerb3a860a2017-08-20 07:14:40 +0000256 const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg);
Igor Breger360d0f22017-04-27 08:02:03 +0000257
Igor Bregerb3a860a2017-08-20 07:14:40 +0000258 if (DstRC != SrcRC) {
259 I.getOperand(1).setSubReg(getSubRegIndex(DstRC));
Igor Breger360d0f22017-04-27 08:02:03 +0000260 I.getOperand(1).substPhysReg(SrcReg, TRI);
261 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000262 }
263
264 // No need to constrain SrcReg. It will get constrained when
265 // we hit another of its use or its defs.
266 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000267 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Bregerb3a860a2017-08-20 07:14:40 +0000268 if (!OldRC || !DstRC->hasSubClassEq(OldRC)) {
269 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000270 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
271 << " operand\n");
272 return false;
273 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000274 }
275 I.setDesc(TII.get(X86::COPY));
276 return true;
277}
278
279bool X86InstructionSelector::select(MachineInstr &I) const {
280 assert(I.getParent() && "Instruction should be in a basic block!");
281 assert(I.getParent()->getParent() && "Instruction should be in a function!");
282
283 MachineBasicBlock &MBB = *I.getParent();
284 MachineFunction &MF = *MBB.getParent();
285 MachineRegisterInfo &MRI = MF.getRegInfo();
286
287 unsigned Opcode = I.getOpcode();
288 if (!isPreISelGenericOpcode(Opcode)) {
289 // Certain non-generic instructions also need some special handling.
290
Igor Breger03c22082017-08-21 09:17:28 +0000291 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
292 return false;
Igor Breger03c22082017-08-21 09:17:28 +0000293
Igor Bregerf7359d82017-02-22 12:25:09 +0000294 if (I.isCopy())
Igor Breger1dcd5e82017-06-20 09:15:10 +0000295 return selectCopy(I, MRI);
Igor Bregerf7359d82017-02-22 12:25:09 +0000296
Igor Bregerf7359d82017-02-22 12:25:09 +0000297 return true;
298 }
299
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000300 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
301 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000302
Igor Breger2452ef02017-05-01 07:06:08 +0000303 if (selectImpl(I))
Igor Bregerfda31e62017-05-10 06:52:58 +0000304 return true;
Igor Breger2452ef02017-05-01 07:06:08 +0000305
306 DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
307
308 // TODO: This should be implemented by tblgen.
Igor Bregera8ba5722017-03-23 15:25:57 +0000309 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000310 return true;
Igor Breger810c6252017-05-08 09:40:43 +0000311 if (selectFrameIndexOrGep(I, MRI, MF))
Igor Breger531a2032017-03-26 08:11:12 +0000312 return true;
Igor Breger717bd362017-07-02 08:58:29 +0000313 if (selectGlobalValue(I, MRI, MF))
314 return true;
Igor Breger3b97ea32017-04-12 12:54:54 +0000315 if (selectConstant(I, MRI, MF))
316 return true;
Igor Breger4fdf1e42017-04-19 11:34:59 +0000317 if (selectTrunc(I, MRI, MF))
318 return true;
Igor Bregerfda31e62017-05-10 06:52:58 +0000319 if (selectZext(I, MRI, MF))
320 return true;
Igor Bregerc7b59772017-05-11 07:17:40 +0000321 if (selectCmp(I, MRI, MF))
322 return true;
Igor Breger28f290f2017-05-17 12:48:08 +0000323 if (selectUadde(I, MRI, MF))
324 return true;
Igor Bregerb186a692017-07-02 08:15:49 +0000325 if (selectUnmergeValues(I, MRI, MF))
326 return true;
Igor Breger0cddd342017-06-29 12:08:28 +0000327 if (selectMergeValues(I, MRI, MF))
328 return true;
Igor Bregerf5035d62017-06-25 11:42:17 +0000329 if (selectExtract(I, MRI, MF))
330 return true;
Igor Breger1c29be72017-06-22 09:43:35 +0000331 if (selectInsert(I, MRI, MF))
332 return true;
Igor Breger685889c2017-08-21 10:51:54 +0000333 if (selectCondBranch(I, MRI, MF))
334 return true;
Igor Breger2661ae42017-09-04 09:06:45 +0000335 if (selectImplicitDefOrPHI(I, MRI))
Igor Breger47be5fb2017-08-24 07:06:27 +0000336 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000337
Igor Breger2452ef02017-05-01 07:06:08 +0000338 return false;
Igor Bregerf7359d82017-02-22 12:25:09 +0000339}
Igor Breger321cf3c2017-03-03 08:06:46 +0000340
Igor Bregera8ba5722017-03-23 15:25:57 +0000341unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
342 unsigned Opc,
343 uint64_t Alignment) const {
344 bool Isload = (Opc == TargetOpcode::G_LOAD);
345 bool HasAVX = STI.hasAVX();
346 bool HasAVX512 = STI.hasAVX512();
347 bool HasVLX = STI.hasVLX();
348
349 if (Ty == LLT::scalar(8)) {
350 if (X86::GPRRegBankID == RB.getID())
351 return Isload ? X86::MOV8rm : X86::MOV8mr;
352 } else if (Ty == LLT::scalar(16)) {
353 if (X86::GPRRegBankID == RB.getID())
354 return Isload ? X86::MOV16rm : X86::MOV16mr;
Igor Bregera9edb882017-05-01 06:08:32 +0000355 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000356 if (X86::GPRRegBankID == RB.getID())
357 return Isload ? X86::MOV32rm : X86::MOV32mr;
358 if (X86::VECRRegBankID == RB.getID())
359 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
360 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
361 : (HasAVX512 ? X86::VMOVSSZmr
362 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
Igor Bregera9edb882017-05-01 06:08:32 +0000363 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000364 if (X86::GPRRegBankID == RB.getID())
365 return Isload ? X86::MOV64rm : X86::MOV64mr;
366 if (X86::VECRRegBankID == RB.getID())
367 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
368 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
369 : (HasAVX512 ? X86::VMOVSDZmr
370 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
371 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
372 if (Alignment >= 16)
373 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
374 : HasAVX512
375 ? X86::VMOVAPSZ128rm_NOVLX
376 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
377 : (HasVLX ? X86::VMOVAPSZ128mr
378 : HasAVX512
379 ? X86::VMOVAPSZ128mr_NOVLX
380 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
381 else
382 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
383 : HasAVX512
384 ? X86::VMOVUPSZ128rm_NOVLX
385 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
386 : (HasVLX ? X86::VMOVUPSZ128mr
387 : HasAVX512
388 ? X86::VMOVUPSZ128mr_NOVLX
389 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
Igor Breger617be6e2017-05-23 08:23:51 +0000390 } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
391 if (Alignment >= 32)
392 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
393 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
394 : X86::VMOVAPSYrm)
395 : (HasVLX ? X86::VMOVAPSZ256mr
396 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
397 : X86::VMOVAPSYmr);
398 else
399 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
400 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
401 : X86::VMOVUPSYrm)
402 : (HasVLX ? X86::VMOVUPSZ256mr
403 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
404 : X86::VMOVUPSYmr);
405 } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
406 if (Alignment >= 64)
407 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
408 else
409 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
Igor Bregera8ba5722017-03-23 15:25:57 +0000410 }
411 return Opc;
412}
413
Igor Bregerbd2deda2017-06-19 13:12:57 +0000414// Fill in an address from the given instruction.
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000415static void X86SelectAddress(const MachineInstr &I,
416 const MachineRegisterInfo &MRI,
417 X86AddressMode &AM) {
Igor Bregerbd2deda2017-06-19 13:12:57 +0000418
419 assert(I.getOperand(0).isReg() && "unsupported opperand.");
420 assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
421 "unsupported type.");
422
423 if (I.getOpcode() == TargetOpcode::G_GEP) {
424 if (auto COff = getConstantVRegVal(I.getOperand(2).getReg(), MRI)) {
425 int64_t Imm = *COff;
426 if (isInt<32>(Imm)) { // Check for displacement overflow.
427 AM.Disp = static_cast<int32_t>(Imm);
428 AM.Base.Reg = I.getOperand(1).getReg();
429 return;
430 }
431 }
432 } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
433 AM.Base.FrameIndex = I.getOperand(1).getIndex();
434 AM.BaseType = X86AddressMode::FrameIndexBase;
435 return;
436 }
437
438 // Default behavior.
439 AM.Base.Reg = I.getOperand(0).getReg();
440 return;
441}
442
Igor Bregera8ba5722017-03-23 15:25:57 +0000443bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
444 MachineRegisterInfo &MRI,
445 MachineFunction &MF) const {
446
447 unsigned Opc = I.getOpcode();
448
449 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
450 return false;
451
452 const unsigned DefReg = I.getOperand(0).getReg();
453 LLT Ty = MRI.getType(DefReg);
454 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
455
456 auto &MemOp = **I.memoperands_begin();
Igor Bregerbd2deda2017-06-19 13:12:57 +0000457 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
458 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
459 return false;
460 }
461
Igor Bregera8ba5722017-03-23 15:25:57 +0000462 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
463 if (NewOpc == Opc)
464 return false;
465
Igor Bregerbd2deda2017-06-19 13:12:57 +0000466 X86AddressMode AM;
467 X86SelectAddress(*MRI.getVRegDef(I.getOperand(1).getReg()), MRI, AM);
468
Igor Bregera8ba5722017-03-23 15:25:57 +0000469 I.setDesc(TII.get(NewOpc));
470 MachineInstrBuilder MIB(MF, I);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000471 if (Opc == TargetOpcode::G_LOAD) {
472 I.RemoveOperand(1);
473 addFullAddress(MIB, AM);
474 } else {
Igor Bregera8ba5722017-03-23 15:25:57 +0000475 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
Igor Bregerbd2deda2017-06-19 13:12:57 +0000476 I.RemoveOperand(1);
Igor Bregera8ba5722017-03-23 15:25:57 +0000477 I.RemoveOperand(0);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000478 addFullAddress(MIB, AM).addUse(DefReg);
Igor Bregera8ba5722017-03-23 15:25:57 +0000479 }
480 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
481}
482
Igor Breger717bd362017-07-02 08:58:29 +0000483static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) {
484 if (Ty == LLT::pointer(0, 64))
485 return X86::LEA64r;
486 else if (Ty == LLT::pointer(0, 32))
487 return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
488 else
489 llvm_unreachable("Can't get LEA opcode. Unsupported type.");
490}
491
Igor Breger810c6252017-05-08 09:40:43 +0000492bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
493 MachineRegisterInfo &MRI,
494 MachineFunction &MF) const {
495 unsigned Opc = I.getOpcode();
496
497 if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
Igor Breger531a2032017-03-26 08:11:12 +0000498 return false;
499
500 const unsigned DefReg = I.getOperand(0).getReg();
501 LLT Ty = MRI.getType(DefReg);
502
Igor Breger810c6252017-05-08 09:40:43 +0000503 // Use LEA to calculate frame index and GEP
Igor Breger717bd362017-07-02 08:58:29 +0000504 unsigned NewOpc = getLeaOP(Ty, STI);
Igor Breger531a2032017-03-26 08:11:12 +0000505 I.setDesc(TII.get(NewOpc));
506 MachineInstrBuilder MIB(MF, I);
Igor Breger810c6252017-05-08 09:40:43 +0000507
508 if (Opc == TargetOpcode::G_FRAME_INDEX) {
509 addOffset(MIB, 0);
510 } else {
511 MachineOperand &InxOp = I.getOperand(2);
512 I.addOperand(InxOp); // set IndexReg
513 InxOp.ChangeToImmediate(1); // set Scale
514 MIB.addImm(0).addReg(0);
515 }
Igor Breger531a2032017-03-26 08:11:12 +0000516
517 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
518}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000519
Igor Breger717bd362017-07-02 08:58:29 +0000520bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,
521 MachineRegisterInfo &MRI,
522 MachineFunction &MF) const {
523 unsigned Opc = I.getOpcode();
524
525 if (Opc != TargetOpcode::G_GLOBAL_VALUE)
526 return false;
527
528 auto GV = I.getOperand(1).getGlobal();
529 if (GV->isThreadLocal()) {
530 return false; // TODO: we don't support TLS yet.
531 }
532
533 // Can't handle alternate code models yet.
534 if (TM.getCodeModel() != CodeModel::Small)
535 return 0;
536
537 X86AddressMode AM;
538 AM.GV = GV;
539 AM.GVOpFlags = STI.classifyGlobalReference(GV);
540
541 // TODO: The ABI requires an extra load. not supported yet.
542 if (isGlobalStubReference(AM.GVOpFlags))
543 return false;
544
545 // TODO: This reference is relative to the pic base. not supported yet.
546 if (isGlobalRelativeToPICBase(AM.GVOpFlags))
547 return false;
548
549 if (STI.isPICStyleRIPRel()) {
550 // Use rip-relative addressing.
551 assert(AM.Base.Reg == 0 && AM.IndexReg == 0);
552 AM.Base.Reg = X86::RIP;
553 }
554
555 const unsigned DefReg = I.getOperand(0).getReg();
556 LLT Ty = MRI.getType(DefReg);
557 unsigned NewOpc = getLeaOP(Ty, STI);
558
559 I.setDesc(TII.get(NewOpc));
560 MachineInstrBuilder MIB(MF, I);
561
562 I.RemoveOperand(1);
563 addFullAddress(MIB, AM);
564
565 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
566}
567
Igor Breger3b97ea32017-04-12 12:54:54 +0000568bool X86InstructionSelector::selectConstant(MachineInstr &I,
569 MachineRegisterInfo &MRI,
570 MachineFunction &MF) const {
571 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
572 return false;
573
574 const unsigned DefReg = I.getOperand(0).getReg();
575 LLT Ty = MRI.getType(DefReg);
576
Igor Breger5c787ab2017-07-03 11:06:54 +0000577 if (RBI.getRegBank(DefReg, MRI, TRI)->getID() != X86::GPRRegBankID)
578 return false;
Igor Breger3b97ea32017-04-12 12:54:54 +0000579
580 uint64_t Val = 0;
581 if (I.getOperand(1).isCImm()) {
582 Val = I.getOperand(1).getCImm()->getZExtValue();
583 I.getOperand(1).ChangeToImmediate(Val);
584 } else if (I.getOperand(1).isImm()) {
585 Val = I.getOperand(1).getImm();
586 } else
587 llvm_unreachable("Unsupported operand type.");
588
589 unsigned NewOpc;
590 switch (Ty.getSizeInBits()) {
591 case 8:
592 NewOpc = X86::MOV8ri;
593 break;
594 case 16:
595 NewOpc = X86::MOV16ri;
596 break;
597 case 32:
598 NewOpc = X86::MOV32ri;
599 break;
600 case 64: {
601 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
602 if (isInt<32>(Val))
603 NewOpc = X86::MOV64ri32;
604 else
605 NewOpc = X86::MOV64ri;
606 break;
607 }
608 default:
609 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
610 }
611
612 I.setDesc(TII.get(NewOpc));
613 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
614}
615
Igor Breger4fdf1e42017-04-19 11:34:59 +0000616bool X86InstructionSelector::selectTrunc(MachineInstr &I,
617 MachineRegisterInfo &MRI,
618 MachineFunction &MF) const {
619 if (I.getOpcode() != TargetOpcode::G_TRUNC)
620 return false;
621
622 const unsigned DstReg = I.getOperand(0).getReg();
623 const unsigned SrcReg = I.getOperand(1).getReg();
624
625 const LLT DstTy = MRI.getType(DstReg);
626 const LLT SrcTy = MRI.getType(SrcReg);
627
628 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
629 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
630
631 if (DstRB.getID() != SrcRB.getID()) {
632 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
633 return false;
634 }
635
636 if (DstRB.getID() != X86::GPRRegBankID)
637 return false;
638
Igor Breger1dcd5e82017-06-20 09:15:10 +0000639 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000640 if (!DstRC)
641 return false;
642
Igor Breger1dcd5e82017-06-20 09:15:10 +0000643 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000644 if (!SrcRC)
645 return false;
646
Igor Breger014fc562017-05-21 11:13:56 +0000647 unsigned SubIdx;
648 if (DstRC == SrcRC) {
649 // Nothing to be done
650 SubIdx = X86::NoSubRegister;
651 } else if (DstRC == &X86::GR32RegClass) {
652 SubIdx = X86::sub_32bit;
653 } else if (DstRC == &X86::GR16RegClass) {
654 SubIdx = X86::sub_16bit;
655 } else if (DstRC == &X86::GR8RegClass) {
656 SubIdx = X86::sub_8bit;
657 } else {
658 return false;
659 }
660
661 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
662
Igor Breger4fdf1e42017-04-19 11:34:59 +0000663 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
664 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
665 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
666 return false;
667 }
668
Igor Breger014fc562017-05-21 11:13:56 +0000669 I.getOperand(1).setSubReg(SubIdx);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000670
671 I.setDesc(TII.get(X86::COPY));
672 return true;
673}
674
Igor Bregerfda31e62017-05-10 06:52:58 +0000675bool X86InstructionSelector::selectZext(MachineInstr &I,
676 MachineRegisterInfo &MRI,
677 MachineFunction &MF) const {
678 if (I.getOpcode() != TargetOpcode::G_ZEXT)
679 return false;
680
681 const unsigned DstReg = I.getOperand(0).getReg();
682 const unsigned SrcReg = I.getOperand(1).getReg();
683
684 const LLT DstTy = MRI.getType(DstReg);
685 const LLT SrcTy = MRI.getType(SrcReg);
686
Igor Bregerd48c5e42017-07-10 09:07:34 +0000687 if (SrcTy != LLT::scalar(1))
688 return false;
Igor Bregerfda31e62017-05-10 06:52:58 +0000689
Igor Bregerd48c5e42017-07-10 09:07:34 +0000690 unsigned AndOpc;
691 if (DstTy == LLT::scalar(8))
Igor Breger324d3792017-07-11 08:04:51 +0000692 AndOpc = X86::AND8ri;
Igor Bregerd48c5e42017-07-10 09:07:34 +0000693 else if (DstTy == LLT::scalar(16))
694 AndOpc = X86::AND16ri8;
695 else if (DstTy == LLT::scalar(32))
696 AndOpc = X86::AND32ri8;
697 else if (DstTy == LLT::scalar(64))
698 AndOpc = X86::AND64ri8;
699 else
700 return false;
Igor Bregerfda31e62017-05-10 06:52:58 +0000701
Igor Bregerd48c5e42017-07-10 09:07:34 +0000702 unsigned DefReg = SrcReg;
703 if (DstTy != LLT::scalar(8)) {
704 DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
Igor Bregerfda31e62017-05-10 06:52:58 +0000705 BuildMI(*I.getParent(), I, I.getDebugLoc(),
706 TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
707 .addImm(0)
708 .addReg(SrcReg)
709 .addImm(X86::sub_8bit);
Igor Bregerfda31e62017-05-10 06:52:58 +0000710 }
711
Igor Bregerd48c5e42017-07-10 09:07:34 +0000712 MachineInstr &AndInst =
713 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
714 .addReg(DefReg)
715 .addImm(1);
716
717 constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
718
719 I.eraseFromParent();
720 return true;
Igor Bregerfda31e62017-05-10 06:52:58 +0000721}
722
Igor Bregerc7b59772017-05-11 07:17:40 +0000723bool X86InstructionSelector::selectCmp(MachineInstr &I,
724 MachineRegisterInfo &MRI,
725 MachineFunction &MF) const {
726 if (I.getOpcode() != TargetOpcode::G_ICMP)
727 return false;
728
729 X86::CondCode CC;
730 bool SwapArgs;
731 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
732 (CmpInst::Predicate)I.getOperand(1).getPredicate());
733 unsigned OpSet = X86::getSETFromCond(CC);
734
735 unsigned LHS = I.getOperand(2).getReg();
736 unsigned RHS = I.getOperand(3).getReg();
737
738 if (SwapArgs)
739 std::swap(LHS, RHS);
740
741 unsigned OpCmp;
742 LLT Ty = MRI.getType(LHS);
743
744 switch (Ty.getSizeInBits()) {
745 default:
746 return false;
747 case 8:
748 OpCmp = X86::CMP8rr;
749 break;
750 case 16:
751 OpCmp = X86::CMP16rr;
752 break;
753 case 32:
754 OpCmp = X86::CMP32rr;
755 break;
756 case 64:
757 OpCmp = X86::CMP64rr;
758 break;
759 }
760
761 MachineInstr &CmpInst =
762 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
763 .addReg(LHS)
764 .addReg(RHS);
765
766 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
767 TII.get(OpSet), I.getOperand(0).getReg());
768
769 constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
770 constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
771
772 I.eraseFromParent();
773 return true;
774}
775
Igor Breger28f290f2017-05-17 12:48:08 +0000776bool X86InstructionSelector::selectUadde(MachineInstr &I,
777 MachineRegisterInfo &MRI,
778 MachineFunction &MF) const {
779 if (I.getOpcode() != TargetOpcode::G_UADDE)
780 return false;
781
782 const unsigned DstReg = I.getOperand(0).getReg();
783 const unsigned CarryOutReg = I.getOperand(1).getReg();
784 const unsigned Op0Reg = I.getOperand(2).getReg();
785 const unsigned Op1Reg = I.getOperand(3).getReg();
786 unsigned CarryInReg = I.getOperand(4).getReg();
787
788 const LLT DstTy = MRI.getType(DstReg);
789
790 if (DstTy != LLT::scalar(32))
791 return false;
792
793 // find CarryIn def instruction.
794 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
795 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
796 CarryInReg = Def->getOperand(1).getReg();
797 Def = MRI.getVRegDef(CarryInReg);
798 }
799
800 unsigned Opcode;
801 if (Def->getOpcode() == TargetOpcode::G_UADDE) {
802 // carry set by prev ADD.
803
804 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
805 .addReg(CarryInReg);
806
807 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
808 return false;
809
810 Opcode = X86::ADC32rr;
811 } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
812 // carry is constant, support only 0.
813 if (*val != 0)
814 return false;
815
816 Opcode = X86::ADD32rr;
817 } else
818 return false;
819
820 MachineInstr &AddInst =
821 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
822 .addReg(Op0Reg)
823 .addReg(Op1Reg);
824
825 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
826 .addReg(X86::EFLAGS);
827
828 if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
829 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
830 return false;
831
832 I.eraseFromParent();
833 return true;
834}
835
Igor Bregerf5035d62017-06-25 11:42:17 +0000836bool X86InstructionSelector::selectExtract(MachineInstr &I,
837 MachineRegisterInfo &MRI,
838 MachineFunction &MF) const {
839
840 if (I.getOpcode() != TargetOpcode::G_EXTRACT)
841 return false;
842
843 const unsigned DstReg = I.getOperand(0).getReg();
844 const unsigned SrcReg = I.getOperand(1).getReg();
845 int64_t Index = I.getOperand(2).getImm();
846
847 const LLT DstTy = MRI.getType(DstReg);
848 const LLT SrcTy = MRI.getType(SrcReg);
849
850 // Meanwile handle vector type only.
851 if (!DstTy.isVector())
852 return false;
853
854 if (Index % DstTy.getSizeInBits() != 0)
855 return false; // Not extract subvector.
856
857 if (Index == 0) {
858 // Replace by extract subreg copy.
859 if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))
860 return false;
861
862 I.eraseFromParent();
863 return true;
864 }
865
866 bool HasAVX = STI.hasAVX();
867 bool HasAVX512 = STI.hasAVX512();
868 bool HasVLX = STI.hasVLX();
869
870 if (SrcTy.getSizeInBits() == 256 && DstTy.getSizeInBits() == 128) {
871 if (HasVLX)
872 I.setDesc(TII.get(X86::VEXTRACTF32x4Z256rr));
873 else if (HasAVX)
874 I.setDesc(TII.get(X86::VEXTRACTF128rr));
875 else
876 return false;
877 } else if (SrcTy.getSizeInBits() == 512 && HasAVX512) {
878 if (DstTy.getSizeInBits() == 128)
879 I.setDesc(TII.get(X86::VEXTRACTF32x4Zrr));
880 else if (DstTy.getSizeInBits() == 256)
881 I.setDesc(TII.get(X86::VEXTRACTF64x4Zrr));
882 else
883 return false;
884 } else
885 return false;
886
887 // Convert to X86 VEXTRACT immediate.
888 Index = Index / DstTy.getSizeInBits();
889 I.getOperand(2).setImm(Index);
890
891 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
892}
893
894bool X86InstructionSelector::emitExtractSubreg(unsigned DstReg, unsigned SrcReg,
895 MachineInstr &I,
896 MachineRegisterInfo &MRI,
897 MachineFunction &MF) const {
898
899 const LLT DstTy = MRI.getType(DstReg);
900 const LLT SrcTy = MRI.getType(SrcReg);
901 unsigned SubIdx = X86::NoSubRegister;
902
903 if (!DstTy.isVector() || !SrcTy.isVector())
904 return false;
905
906 assert(SrcTy.getSizeInBits() > DstTy.getSizeInBits() &&
907 "Incorrect Src/Dst register size");
908
909 if (DstTy.getSizeInBits() == 128)
910 SubIdx = X86::sub_xmm;
911 else if (DstTy.getSizeInBits() == 256)
912 SubIdx = X86::sub_ymm;
913 else
914 return false;
915
916 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
917 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
918
919 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
920
921 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
922 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
923 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
924 return false;
925 }
926
927 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), DstReg)
928 .addReg(SrcReg, 0, SubIdx);
929
930 return true;
931}
932
Igor Breger1c29be72017-06-22 09:43:35 +0000933bool X86InstructionSelector::emitInsertSubreg(unsigned DstReg, unsigned SrcReg,
934 MachineInstr &I,
935 MachineRegisterInfo &MRI,
936 MachineFunction &MF) const {
937
938 const LLT DstTy = MRI.getType(DstReg);
939 const LLT SrcTy = MRI.getType(SrcReg);
940 unsigned SubIdx = X86::NoSubRegister;
941
942 // TODO: support scalar types
943 if (!DstTy.isVector() || !SrcTy.isVector())
944 return false;
945
946 assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&
947 "Incorrect Src/Dst register size");
948
949 if (SrcTy.getSizeInBits() == 128)
950 SubIdx = X86::sub_xmm;
951 else if (SrcTy.getSizeInBits() == 256)
952 SubIdx = X86::sub_ymm;
953 else
954 return false;
955
956 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
957 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
958
959 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
960 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
961 DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");
962 return false;
963 }
964
965 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))
966 .addReg(DstReg, RegState::DefineNoRead, SubIdx)
967 .addReg(SrcReg);
968
969 return true;
970}
971
972bool X86InstructionSelector::selectInsert(MachineInstr &I,
973 MachineRegisterInfo &MRI,
974 MachineFunction &MF) const {
975
976 if (I.getOpcode() != TargetOpcode::G_INSERT)
977 return false;
978
979 const unsigned DstReg = I.getOperand(0).getReg();
980 const unsigned SrcReg = I.getOperand(1).getReg();
981 const unsigned InsertReg = I.getOperand(2).getReg();
982 int64_t Index = I.getOperand(3).getImm();
983
984 const LLT DstTy = MRI.getType(DstReg);
985 const LLT InsertRegTy = MRI.getType(InsertReg);
986
987 // Meanwile handle vector type only.
988 if (!DstTy.isVector())
989 return false;
990
991 if (Index % InsertRegTy.getSizeInBits() != 0)
992 return false; // Not insert subvector.
993
994 if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {
995 // Replace by subreg copy.
996 if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
997 return false;
998
999 I.eraseFromParent();
1000 return true;
1001 }
1002
1003 bool HasAVX = STI.hasAVX();
1004 bool HasAVX512 = STI.hasAVX512();
1005 bool HasVLX = STI.hasVLX();
1006
1007 if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {
1008 if (HasVLX)
1009 I.setDesc(TII.get(X86::VINSERTF32x4Z256rr));
1010 else if (HasAVX)
1011 I.setDesc(TII.get(X86::VINSERTF128rr));
1012 else
1013 return false;
1014 } else if (DstTy.getSizeInBits() == 512 && HasAVX512) {
1015 if (InsertRegTy.getSizeInBits() == 128)
1016 I.setDesc(TII.get(X86::VINSERTF32x4Zrr));
1017 else if (InsertRegTy.getSizeInBits() == 256)
1018 I.setDesc(TII.get(X86::VINSERTF64x4Zrr));
1019 else
1020 return false;
1021 } else
1022 return false;
1023
1024 // Convert to X86 VINSERT immediate.
1025 Index = Index / InsertRegTy.getSizeInBits();
1026
1027 I.getOperand(3).setImm(Index);
1028
1029 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
1030}
1031
Igor Bregerb186a692017-07-02 08:15:49 +00001032bool X86InstructionSelector::selectUnmergeValues(MachineInstr &I,
1033 MachineRegisterInfo &MRI,
1034 MachineFunction &MF) const {
1035 if (I.getOpcode() != TargetOpcode::G_UNMERGE_VALUES)
1036 return false;
1037
1038 // Split to extracts.
1039 unsigned NumDefs = I.getNumOperands() - 1;
1040 unsigned SrcReg = I.getOperand(NumDefs).getReg();
1041 unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
1042
1043 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1044
1045 MachineInstr &ExtrInst =
1046 *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1047 TII.get(TargetOpcode::G_EXTRACT), I.getOperand(Idx).getReg())
1048 .addReg(SrcReg)
1049 .addImm(Idx * DefSize);
1050
1051 if (!select(ExtrInst))
1052 return false;
1053 }
1054
1055 I.eraseFromParent();
1056 return true;
1057}
1058
Igor Breger0cddd342017-06-29 12:08:28 +00001059bool X86InstructionSelector::selectMergeValues(MachineInstr &I,
1060 MachineRegisterInfo &MRI,
1061 MachineFunction &MF) const {
1062 if (I.getOpcode() != TargetOpcode::G_MERGE_VALUES)
1063 return false;
1064
1065 // Split to inserts.
1066 unsigned DstReg = I.getOperand(0).getReg();
1067 unsigned SrcReg0 = I.getOperand(1).getReg();
1068
1069 const LLT DstTy = MRI.getType(DstReg);
1070 const LLT SrcTy = MRI.getType(SrcReg0);
1071 unsigned SrcSize = SrcTy.getSizeInBits();
1072
1073 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1074
1075 // For the first src use insertSubReg.
1076 unsigned DefReg = MRI.createGenericVirtualRegister(DstTy);
1077 MRI.setRegBank(DefReg, RegBank);
1078 if (!emitInsertSubreg(DefReg, I.getOperand(1).getReg(), I, MRI, MF))
1079 return false;
1080
1081 for (unsigned Idx = 2; Idx < I.getNumOperands(); ++Idx) {
1082
1083 unsigned Tmp = MRI.createGenericVirtualRegister(DstTy);
1084 MRI.setRegBank(Tmp, RegBank);
1085
1086 MachineInstr &InsertInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1087 TII.get(TargetOpcode::G_INSERT), Tmp)
1088 .addReg(DefReg)
1089 .addReg(I.getOperand(Idx).getReg())
1090 .addImm((Idx - 1) * SrcSize);
1091
1092 DefReg = Tmp;
1093
1094 if (!select(InsertInst))
1095 return false;
1096 }
1097
1098 MachineInstr &CopyInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1099 TII.get(TargetOpcode::COPY), DstReg)
1100 .addReg(DefReg);
1101
1102 if (!select(CopyInst))
1103 return false;
1104
1105 I.eraseFromParent();
1106 return true;
1107}
Igor Breger685889c2017-08-21 10:51:54 +00001108
1109bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
1110 MachineRegisterInfo &MRI,
1111 MachineFunction &MF) const {
1112 if (I.getOpcode() != TargetOpcode::G_BRCOND)
1113 return false;
1114
1115 const unsigned CondReg = I.getOperand(0).getReg();
1116 MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
1117
1118 MachineInstr &TestInst =
1119 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TEST8ri))
1120 .addReg(CondReg)
1121 .addImm(1);
1122 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::JNE_1))
1123 .addMBB(DestMBB);
1124
1125 constrainSelectedInstRegOperands(TestInst, TII, TRI, RBI);
1126
1127 I.eraseFromParent();
1128 return true;
1129}
1130
Igor Breger2661ae42017-09-04 09:06:45 +00001131bool X86InstructionSelector::selectImplicitDefOrPHI(
1132 MachineInstr &I, MachineRegisterInfo &MRI) const {
Igor Breger47be5fb2017-08-24 07:06:27 +00001133
Igor Breger2661ae42017-09-04 09:06:45 +00001134 if (I.getOpcode() != TargetOpcode::G_IMPLICIT_DEF &&
1135 I.getOpcode() != TargetOpcode::G_PHI)
Igor Breger47be5fb2017-08-24 07:06:27 +00001136 return false;
1137
1138 unsigned DstReg = I.getOperand(0).getReg();
1139
1140 if (!MRI.getRegClassOrNull(DstReg)) {
1141 const LLT DstTy = MRI.getType(DstReg);
1142 const TargetRegisterClass *RC = getRegClass(DstTy, DstReg, MRI);
1143
1144 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1145 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
1146 << " operand\n");
1147 return false;
1148 }
1149 }
1150
Igor Breger2661ae42017-09-04 09:06:45 +00001151 if (I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1152 I.setDesc(TII.get(X86::IMPLICIT_DEF));
1153 else
1154 I.setDesc(TII.get(X86::PHI));
1155
Igor Breger47be5fb2017-08-24 07:06:27 +00001156 return true;
1157}
1158
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001159InstructionSelector *
Daniel Sanderse7b0d662017-04-21 15:59:56 +00001160llvm::createX86InstructionSelector(const X86TargetMachine &TM,
1161 X86Subtarget &Subtarget,
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001162 X86RegisterBankInfo &RBI) {
Daniel Sanderse7b0d662017-04-21 15:59:56 +00001163 return new X86InstructionSelector(TM, Subtarget, RBI);
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001164}