blob: c29f402b52231e067da14df93213ec9c3ab4fae8 [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 Breger1c29be72017-06-22 09:43:35 +000086
87 // emit insert subreg instruction and insert it before MachineInstr &I
88 bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
89 MachineRegisterInfo &MRI, MachineFunction &MF) const;
Igor Bregerf5035d62017-06-25 11:42:17 +000090 // emit extract subreg instruction and insert it before MachineInstr &I
91 bool emitExtractSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
92 MachineRegisterInfo &MRI, MachineFunction &MF) const;
Igor Breger1dcd5e82017-06-20 09:15:10 +000093
94 const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
95 const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,
96 MachineRegisterInfo &MRI) const;
Igor Breger28f290f2017-05-17 12:48:08 +000097
Daniel Sanderse7b0d662017-04-21 15:59:56 +000098 const X86TargetMachine &TM;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000099 const X86Subtarget &STI;
100 const X86InstrInfo &TII;
101 const X86RegisterInfo &TRI;
102 const X86RegisterBankInfo &RBI;
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000103
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000104#define GET_GLOBALISEL_PREDICATES_DECL
105#include "X86GenGlobalISel.inc"
106#undef GET_GLOBALISEL_PREDICATES_DECL
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000107
108#define GET_GLOBALISEL_TEMPORARIES_DECL
109#include "X86GenGlobalISel.inc"
110#undef GET_GLOBALISEL_TEMPORARIES_DECL
111};
112
113} // end anonymous namespace
114
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000115#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000116#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000117#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000118
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000119X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
120 const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +0000121 const X86RegisterBankInfo &RBI)
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000122 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000123 TRI(*STI.getRegisterInfo()), RBI(RBI),
124#define GET_GLOBALISEL_PREDICATES_INIT
125#include "X86GenGlobalISel.inc"
126#undef GET_GLOBALISEL_PREDICATES_INIT
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000127#define GET_GLOBALISEL_TEMPORARIES_INIT
128#include "X86GenGlobalISel.inc"
129#undef GET_GLOBALISEL_TEMPORARIES_INIT
130{
131}
Igor Bregerf7359d82017-02-22 12:25:09 +0000132
133// FIXME: This should be target-independent, inferred from the types declared
134// for each class in the bank.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000135const TargetRegisterClass *
136X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000137 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger4fdf1e42017-04-19 11:34:59 +0000138 if (Ty.getSizeInBits() <= 8)
139 return &X86::GR8RegClass;
140 if (Ty.getSizeInBits() == 16)
141 return &X86::GR16RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000142 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000143 return &X86::GR32RegClass;
144 if (Ty.getSizeInBits() == 64)
145 return &X86::GR64RegClass;
146 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000147 if (RB.getID() == X86::VECRRegBankID) {
148 if (Ty.getSizeInBits() == 32)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000149 return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000150 if (Ty.getSizeInBits() == 64)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000151 return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000152 if (Ty.getSizeInBits() == 128)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000153 return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000154 if (Ty.getSizeInBits() == 256)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000155 return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000156 if (Ty.getSizeInBits() == 512)
157 return &X86::VR512RegClass;
158 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000159
160 llvm_unreachable("Unknown RegBank!");
161}
162
Igor Breger1dcd5e82017-06-20 09:15:10 +0000163const TargetRegisterClass *
164X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,
165 MachineRegisterInfo &MRI) const {
166 const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
167 return getRegClass(Ty, RegBank);
168}
169
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000170static unsigned getSubRegIndex(const TargetRegisterClass *RC) {
Igor Bregerb3a860a2017-08-20 07:14:40 +0000171 unsigned SubIdx = X86::NoSubRegister;
172 if (RC == &X86::GR32RegClass) {
173 SubIdx = X86::sub_32bit;
174 } else if (RC == &X86::GR16RegClass) {
175 SubIdx = X86::sub_16bit;
176 } else if (RC == &X86::GR8RegClass) {
177 SubIdx = X86::sub_8bit;
178 }
179
180 return SubIdx;
181}
182
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000183static const TargetRegisterClass *getRegClassFromGRPhysReg(unsigned Reg) {
Igor Bregerb3a860a2017-08-20 07:14:40 +0000184 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
185 if (X86::GR64RegClass.contains(Reg))
186 return &X86::GR64RegClass;
187 if (X86::GR32RegClass.contains(Reg))
188 return &X86::GR32RegClass;
189 if (X86::GR16RegClass.contains(Reg))
190 return &X86::GR16RegClass;
191 if (X86::GR8RegClass.contains(Reg))
192 return &X86::GR8RegClass;
193
194 llvm_unreachable("Unknown RegClass for PhysReg!");
195}
196
Igor Bregerf7359d82017-02-22 12:25:09 +0000197// Set X86 Opcode and constrain DestReg.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000198bool X86InstructionSelector::selectCopy(MachineInstr &I,
199 MachineRegisterInfo &MRI) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000200
201 unsigned DstReg = I.getOperand(0).getReg();
Igor Bregerb3a860a2017-08-20 07:14:40 +0000202 const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI);
203 const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
Igor Bregerf7359d82017-02-22 12:25:09 +0000204
Igor Bregerf7359d82017-02-22 12:25:09 +0000205 unsigned SrcReg = I.getOperand(1).getReg();
206 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
Igor Bregerb3a860a2017-08-20 07:14:40 +0000207 const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
208
209 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
210 assert(I.isCopy() && "Generic operators do not allow physical registers");
211
212 if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID &&
213 DstRegBank.getID() == X86::GPRRegBankID) {
214
215 const TargetRegisterClass *SrcRC =
216 getRegClass(MRI.getType(SrcReg), SrcRegBank);
217 const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg);
218
219 if (SrcRC != DstRC) {
220 // This case can be generated by ABI lowering, performe anyext
221 unsigned ExtSrc = MRI.createVirtualRegister(DstRC);
222 BuildMI(*I.getParent(), I, I.getDebugLoc(),
223 TII.get(TargetOpcode::SUBREG_TO_REG))
224 .addDef(ExtSrc)
225 .addImm(0)
226 .addReg(SrcReg)
227 .addImm(getSubRegIndex(SrcRC));
228
229 I.getOperand(1).setReg(ExtSrc);
230 }
231 }
232
233 return true;
234 }
Igor Breger360d0f22017-04-27 08:02:03 +0000235
Igor Bregerf7359d82017-02-22 12:25:09 +0000236 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
237 "No phys reg on generic operators");
238 assert((DstSize == SrcSize ||
239 // Copies are a mean to setup initial types, the number of
240 // bits may not exactly match.
241 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
242 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
243 "Copy with different width?!");
244
Igor Bregerb3a860a2017-08-20 07:14:40 +0000245 const TargetRegisterClass *DstRC =
246 getRegClass(MRI.getType(DstReg), DstRegBank);
Igor Bregerf7359d82017-02-22 12:25:09 +0000247
Igor Bregerb3a860a2017-08-20 07:14:40 +0000248 if (SrcRegBank.getID() == X86::GPRRegBankID &&
249 DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize &&
250 TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
251 // Change the physical register to performe truncate.
Igor Breger360d0f22017-04-27 08:02:03 +0000252
Igor Bregerb3a860a2017-08-20 07:14:40 +0000253 const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg);
Igor Breger360d0f22017-04-27 08:02:03 +0000254
Igor Bregerb3a860a2017-08-20 07:14:40 +0000255 if (DstRC != SrcRC) {
256 I.getOperand(1).setSubReg(getSubRegIndex(DstRC));
Igor Breger360d0f22017-04-27 08:02:03 +0000257 I.getOperand(1).substPhysReg(SrcReg, TRI);
258 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000259 }
260
261 // No need to constrain SrcReg. It will get constrained when
262 // we hit another of its use or its defs.
263 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000264 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Bregerb3a860a2017-08-20 07:14:40 +0000265 if (!OldRC || !DstRC->hasSubClassEq(OldRC)) {
266 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000267 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
268 << " operand\n");
269 return false;
270 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000271 }
272 I.setDesc(TII.get(X86::COPY));
273 return true;
274}
275
276bool X86InstructionSelector::select(MachineInstr &I) const {
277 assert(I.getParent() && "Instruction should be in a basic block!");
278 assert(I.getParent()->getParent() && "Instruction should be in a function!");
279
280 MachineBasicBlock &MBB = *I.getParent();
281 MachineFunction &MF = *MBB.getParent();
282 MachineRegisterInfo &MRI = MF.getRegInfo();
283
284 unsigned Opcode = I.getOpcode();
285 if (!isPreISelGenericOpcode(Opcode)) {
286 // Certain non-generic instructions also need some special handling.
287
Igor Breger03c22082017-08-21 09:17:28 +0000288 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
289 return false;
290 if (Opcode == TargetOpcode::PHI)
291 return false;
292
Igor Bregerf7359d82017-02-22 12:25:09 +0000293 if (I.isCopy())
Igor Breger1dcd5e82017-06-20 09:15:10 +0000294 return selectCopy(I, MRI);
Igor Bregerf7359d82017-02-22 12:25:09 +0000295
296 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
297 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 Breger321cf3c2017-03-03 08:06:46 +0000333
Igor Breger2452ef02017-05-01 07:06:08 +0000334 return false;
Igor Bregerf7359d82017-02-22 12:25:09 +0000335}
Igor Breger321cf3c2017-03-03 08:06:46 +0000336
Igor Bregera8ba5722017-03-23 15:25:57 +0000337unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
338 unsigned Opc,
339 uint64_t Alignment) const {
340 bool Isload = (Opc == TargetOpcode::G_LOAD);
341 bool HasAVX = STI.hasAVX();
342 bool HasAVX512 = STI.hasAVX512();
343 bool HasVLX = STI.hasVLX();
344
345 if (Ty == LLT::scalar(8)) {
346 if (X86::GPRRegBankID == RB.getID())
347 return Isload ? X86::MOV8rm : X86::MOV8mr;
348 } else if (Ty == LLT::scalar(16)) {
349 if (X86::GPRRegBankID == RB.getID())
350 return Isload ? X86::MOV16rm : X86::MOV16mr;
Igor Bregera9edb882017-05-01 06:08:32 +0000351 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000352 if (X86::GPRRegBankID == RB.getID())
353 return Isload ? X86::MOV32rm : X86::MOV32mr;
354 if (X86::VECRRegBankID == RB.getID())
355 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
356 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
357 : (HasAVX512 ? X86::VMOVSSZmr
358 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
Igor Bregera9edb882017-05-01 06:08:32 +0000359 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000360 if (X86::GPRRegBankID == RB.getID())
361 return Isload ? X86::MOV64rm : X86::MOV64mr;
362 if (X86::VECRRegBankID == RB.getID())
363 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
364 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
365 : (HasAVX512 ? X86::VMOVSDZmr
366 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
367 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
368 if (Alignment >= 16)
369 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
370 : HasAVX512
371 ? X86::VMOVAPSZ128rm_NOVLX
372 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
373 : (HasVLX ? X86::VMOVAPSZ128mr
374 : HasAVX512
375 ? X86::VMOVAPSZ128mr_NOVLX
376 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
377 else
378 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
379 : HasAVX512
380 ? X86::VMOVUPSZ128rm_NOVLX
381 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
382 : (HasVLX ? X86::VMOVUPSZ128mr
383 : HasAVX512
384 ? X86::VMOVUPSZ128mr_NOVLX
385 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
Igor Breger617be6e2017-05-23 08:23:51 +0000386 } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
387 if (Alignment >= 32)
388 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
389 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
390 : X86::VMOVAPSYrm)
391 : (HasVLX ? X86::VMOVAPSZ256mr
392 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
393 : X86::VMOVAPSYmr);
394 else
395 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
396 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
397 : X86::VMOVUPSYrm)
398 : (HasVLX ? X86::VMOVUPSZ256mr
399 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
400 : X86::VMOVUPSYmr);
401 } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
402 if (Alignment >= 64)
403 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
404 else
405 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
Igor Bregera8ba5722017-03-23 15:25:57 +0000406 }
407 return Opc;
408}
409
Igor Bregerbd2deda2017-06-19 13:12:57 +0000410// Fill in an address from the given instruction.
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000411static void X86SelectAddress(const MachineInstr &I,
412 const MachineRegisterInfo &MRI,
413 X86AddressMode &AM) {
Igor Bregerbd2deda2017-06-19 13:12:57 +0000414
415 assert(I.getOperand(0).isReg() && "unsupported opperand.");
416 assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
417 "unsupported type.");
418
419 if (I.getOpcode() == TargetOpcode::G_GEP) {
420 if (auto COff = getConstantVRegVal(I.getOperand(2).getReg(), MRI)) {
421 int64_t Imm = *COff;
422 if (isInt<32>(Imm)) { // Check for displacement overflow.
423 AM.Disp = static_cast<int32_t>(Imm);
424 AM.Base.Reg = I.getOperand(1).getReg();
425 return;
426 }
427 }
428 } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
429 AM.Base.FrameIndex = I.getOperand(1).getIndex();
430 AM.BaseType = X86AddressMode::FrameIndexBase;
431 return;
432 }
433
434 // Default behavior.
435 AM.Base.Reg = I.getOperand(0).getReg();
436 return;
437}
438
Igor Bregera8ba5722017-03-23 15:25:57 +0000439bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
440 MachineRegisterInfo &MRI,
441 MachineFunction &MF) const {
442
443 unsigned Opc = I.getOpcode();
444
445 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
446 return false;
447
448 const unsigned DefReg = I.getOperand(0).getReg();
449 LLT Ty = MRI.getType(DefReg);
450 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
451
452 auto &MemOp = **I.memoperands_begin();
Igor Bregerbd2deda2017-06-19 13:12:57 +0000453 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
454 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
455 return false;
456 }
457
Igor Bregera8ba5722017-03-23 15:25:57 +0000458 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
459 if (NewOpc == Opc)
460 return false;
461
Igor Bregerbd2deda2017-06-19 13:12:57 +0000462 X86AddressMode AM;
463 X86SelectAddress(*MRI.getVRegDef(I.getOperand(1).getReg()), MRI, AM);
464
Igor Bregera8ba5722017-03-23 15:25:57 +0000465 I.setDesc(TII.get(NewOpc));
466 MachineInstrBuilder MIB(MF, I);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000467 if (Opc == TargetOpcode::G_LOAD) {
468 I.RemoveOperand(1);
469 addFullAddress(MIB, AM);
470 } else {
Igor Bregera8ba5722017-03-23 15:25:57 +0000471 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
Igor Bregerbd2deda2017-06-19 13:12:57 +0000472 I.RemoveOperand(1);
Igor Bregera8ba5722017-03-23 15:25:57 +0000473 I.RemoveOperand(0);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000474 addFullAddress(MIB, AM).addUse(DefReg);
Igor Bregera8ba5722017-03-23 15:25:57 +0000475 }
476 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
477}
478
Igor Breger717bd362017-07-02 08:58:29 +0000479static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) {
480 if (Ty == LLT::pointer(0, 64))
481 return X86::LEA64r;
482 else if (Ty == LLT::pointer(0, 32))
483 return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
484 else
485 llvm_unreachable("Can't get LEA opcode. Unsupported type.");
486}
487
Igor Breger810c6252017-05-08 09:40:43 +0000488bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
489 MachineRegisterInfo &MRI,
490 MachineFunction &MF) const {
491 unsigned Opc = I.getOpcode();
492
493 if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
Igor Breger531a2032017-03-26 08:11:12 +0000494 return false;
495
496 const unsigned DefReg = I.getOperand(0).getReg();
497 LLT Ty = MRI.getType(DefReg);
498
Igor Breger810c6252017-05-08 09:40:43 +0000499 // Use LEA to calculate frame index and GEP
Igor Breger717bd362017-07-02 08:58:29 +0000500 unsigned NewOpc = getLeaOP(Ty, STI);
Igor Breger531a2032017-03-26 08:11:12 +0000501 I.setDesc(TII.get(NewOpc));
502 MachineInstrBuilder MIB(MF, I);
Igor Breger810c6252017-05-08 09:40:43 +0000503
504 if (Opc == TargetOpcode::G_FRAME_INDEX) {
505 addOffset(MIB, 0);
506 } else {
507 MachineOperand &InxOp = I.getOperand(2);
508 I.addOperand(InxOp); // set IndexReg
509 InxOp.ChangeToImmediate(1); // set Scale
510 MIB.addImm(0).addReg(0);
511 }
Igor Breger531a2032017-03-26 08:11:12 +0000512
513 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
514}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000515
Igor Breger717bd362017-07-02 08:58:29 +0000516bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,
517 MachineRegisterInfo &MRI,
518 MachineFunction &MF) const {
519 unsigned Opc = I.getOpcode();
520
521 if (Opc != TargetOpcode::G_GLOBAL_VALUE)
522 return false;
523
524 auto GV = I.getOperand(1).getGlobal();
525 if (GV->isThreadLocal()) {
526 return false; // TODO: we don't support TLS yet.
527 }
528
529 // Can't handle alternate code models yet.
530 if (TM.getCodeModel() != CodeModel::Small)
531 return 0;
532
533 X86AddressMode AM;
534 AM.GV = GV;
535 AM.GVOpFlags = STI.classifyGlobalReference(GV);
536
537 // TODO: The ABI requires an extra load. not supported yet.
538 if (isGlobalStubReference(AM.GVOpFlags))
539 return false;
540
541 // TODO: This reference is relative to the pic base. not supported yet.
542 if (isGlobalRelativeToPICBase(AM.GVOpFlags))
543 return false;
544
545 if (STI.isPICStyleRIPRel()) {
546 // Use rip-relative addressing.
547 assert(AM.Base.Reg == 0 && AM.IndexReg == 0);
548 AM.Base.Reg = X86::RIP;
549 }
550
551 const unsigned DefReg = I.getOperand(0).getReg();
552 LLT Ty = MRI.getType(DefReg);
553 unsigned NewOpc = getLeaOP(Ty, STI);
554
555 I.setDesc(TII.get(NewOpc));
556 MachineInstrBuilder MIB(MF, I);
557
558 I.RemoveOperand(1);
559 addFullAddress(MIB, AM);
560
561 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
562}
563
Igor Breger3b97ea32017-04-12 12:54:54 +0000564bool X86InstructionSelector::selectConstant(MachineInstr &I,
565 MachineRegisterInfo &MRI,
566 MachineFunction &MF) const {
567 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
568 return false;
569
570 const unsigned DefReg = I.getOperand(0).getReg();
571 LLT Ty = MRI.getType(DefReg);
572
Igor Breger5c787ab2017-07-03 11:06:54 +0000573 if (RBI.getRegBank(DefReg, MRI, TRI)->getID() != X86::GPRRegBankID)
574 return false;
Igor Breger3b97ea32017-04-12 12:54:54 +0000575
576 uint64_t Val = 0;
577 if (I.getOperand(1).isCImm()) {
578 Val = I.getOperand(1).getCImm()->getZExtValue();
579 I.getOperand(1).ChangeToImmediate(Val);
580 } else if (I.getOperand(1).isImm()) {
581 Val = I.getOperand(1).getImm();
582 } else
583 llvm_unreachable("Unsupported operand type.");
584
585 unsigned NewOpc;
586 switch (Ty.getSizeInBits()) {
587 case 8:
588 NewOpc = X86::MOV8ri;
589 break;
590 case 16:
591 NewOpc = X86::MOV16ri;
592 break;
593 case 32:
594 NewOpc = X86::MOV32ri;
595 break;
596 case 64: {
597 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
598 if (isInt<32>(Val))
599 NewOpc = X86::MOV64ri32;
600 else
601 NewOpc = X86::MOV64ri;
602 break;
603 }
604 default:
605 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
606 }
607
608 I.setDesc(TII.get(NewOpc));
609 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
610}
611
Igor Breger4fdf1e42017-04-19 11:34:59 +0000612bool X86InstructionSelector::selectTrunc(MachineInstr &I,
613 MachineRegisterInfo &MRI,
614 MachineFunction &MF) const {
615 if (I.getOpcode() != TargetOpcode::G_TRUNC)
616 return false;
617
618 const unsigned DstReg = I.getOperand(0).getReg();
619 const unsigned SrcReg = I.getOperand(1).getReg();
620
621 const LLT DstTy = MRI.getType(DstReg);
622 const LLT SrcTy = MRI.getType(SrcReg);
623
624 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
625 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
626
627 if (DstRB.getID() != SrcRB.getID()) {
628 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
629 return false;
630 }
631
632 if (DstRB.getID() != X86::GPRRegBankID)
633 return false;
634
Igor Breger1dcd5e82017-06-20 09:15:10 +0000635 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000636 if (!DstRC)
637 return false;
638
Igor Breger1dcd5e82017-06-20 09:15:10 +0000639 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000640 if (!SrcRC)
641 return false;
642
Igor Breger014fc562017-05-21 11:13:56 +0000643 unsigned SubIdx;
644 if (DstRC == SrcRC) {
645 // Nothing to be done
646 SubIdx = X86::NoSubRegister;
647 } else if (DstRC == &X86::GR32RegClass) {
648 SubIdx = X86::sub_32bit;
649 } else if (DstRC == &X86::GR16RegClass) {
650 SubIdx = X86::sub_16bit;
651 } else if (DstRC == &X86::GR8RegClass) {
652 SubIdx = X86::sub_8bit;
653 } else {
654 return false;
655 }
656
657 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
658
Igor Breger4fdf1e42017-04-19 11:34:59 +0000659 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
660 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
661 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
662 return false;
663 }
664
Igor Breger014fc562017-05-21 11:13:56 +0000665 I.getOperand(1).setSubReg(SubIdx);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000666
667 I.setDesc(TII.get(X86::COPY));
668 return true;
669}
670
Igor Bregerfda31e62017-05-10 06:52:58 +0000671bool X86InstructionSelector::selectZext(MachineInstr &I,
672 MachineRegisterInfo &MRI,
673 MachineFunction &MF) const {
674 if (I.getOpcode() != TargetOpcode::G_ZEXT)
675 return false;
676
677 const unsigned DstReg = I.getOperand(0).getReg();
678 const unsigned SrcReg = I.getOperand(1).getReg();
679
680 const LLT DstTy = MRI.getType(DstReg);
681 const LLT SrcTy = MRI.getType(SrcReg);
682
Igor Bregerd48c5e42017-07-10 09:07:34 +0000683 if (SrcTy != LLT::scalar(1))
684 return false;
Igor Bregerfda31e62017-05-10 06:52:58 +0000685
Igor Bregerd48c5e42017-07-10 09:07:34 +0000686 unsigned AndOpc;
687 if (DstTy == LLT::scalar(8))
Igor Breger324d3792017-07-11 08:04:51 +0000688 AndOpc = X86::AND8ri;
Igor Bregerd48c5e42017-07-10 09:07:34 +0000689 else if (DstTy == LLT::scalar(16))
690 AndOpc = X86::AND16ri8;
691 else if (DstTy == LLT::scalar(32))
692 AndOpc = X86::AND32ri8;
693 else if (DstTy == LLT::scalar(64))
694 AndOpc = X86::AND64ri8;
695 else
696 return false;
Igor Bregerfda31e62017-05-10 06:52:58 +0000697
Igor Bregerd48c5e42017-07-10 09:07:34 +0000698 unsigned DefReg = SrcReg;
699 if (DstTy != LLT::scalar(8)) {
700 DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
Igor Bregerfda31e62017-05-10 06:52:58 +0000701 BuildMI(*I.getParent(), I, I.getDebugLoc(),
702 TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
703 .addImm(0)
704 .addReg(SrcReg)
705 .addImm(X86::sub_8bit);
Igor Bregerfda31e62017-05-10 06:52:58 +0000706 }
707
Igor Bregerd48c5e42017-07-10 09:07:34 +0000708 MachineInstr &AndInst =
709 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
710 .addReg(DefReg)
711 .addImm(1);
712
713 constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
714
715 I.eraseFromParent();
716 return true;
Igor Bregerfda31e62017-05-10 06:52:58 +0000717}
718
Igor Bregerc7b59772017-05-11 07:17:40 +0000719bool X86InstructionSelector::selectCmp(MachineInstr &I,
720 MachineRegisterInfo &MRI,
721 MachineFunction &MF) const {
722 if (I.getOpcode() != TargetOpcode::G_ICMP)
723 return false;
724
725 X86::CondCode CC;
726 bool SwapArgs;
727 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
728 (CmpInst::Predicate)I.getOperand(1).getPredicate());
729 unsigned OpSet = X86::getSETFromCond(CC);
730
731 unsigned LHS = I.getOperand(2).getReg();
732 unsigned RHS = I.getOperand(3).getReg();
733
734 if (SwapArgs)
735 std::swap(LHS, RHS);
736
737 unsigned OpCmp;
738 LLT Ty = MRI.getType(LHS);
739
740 switch (Ty.getSizeInBits()) {
741 default:
742 return false;
743 case 8:
744 OpCmp = X86::CMP8rr;
745 break;
746 case 16:
747 OpCmp = X86::CMP16rr;
748 break;
749 case 32:
750 OpCmp = X86::CMP32rr;
751 break;
752 case 64:
753 OpCmp = X86::CMP64rr;
754 break;
755 }
756
757 MachineInstr &CmpInst =
758 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
759 .addReg(LHS)
760 .addReg(RHS);
761
762 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
763 TII.get(OpSet), I.getOperand(0).getReg());
764
765 constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
766 constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
767
768 I.eraseFromParent();
769 return true;
770}
771
Igor Breger28f290f2017-05-17 12:48:08 +0000772bool X86InstructionSelector::selectUadde(MachineInstr &I,
773 MachineRegisterInfo &MRI,
774 MachineFunction &MF) const {
775 if (I.getOpcode() != TargetOpcode::G_UADDE)
776 return false;
777
778 const unsigned DstReg = I.getOperand(0).getReg();
779 const unsigned CarryOutReg = I.getOperand(1).getReg();
780 const unsigned Op0Reg = I.getOperand(2).getReg();
781 const unsigned Op1Reg = I.getOperand(3).getReg();
782 unsigned CarryInReg = I.getOperand(4).getReg();
783
784 const LLT DstTy = MRI.getType(DstReg);
785
786 if (DstTy != LLT::scalar(32))
787 return false;
788
789 // find CarryIn def instruction.
790 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
791 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
792 CarryInReg = Def->getOperand(1).getReg();
793 Def = MRI.getVRegDef(CarryInReg);
794 }
795
796 unsigned Opcode;
797 if (Def->getOpcode() == TargetOpcode::G_UADDE) {
798 // carry set by prev ADD.
799
800 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
801 .addReg(CarryInReg);
802
803 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
804 return false;
805
806 Opcode = X86::ADC32rr;
807 } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
808 // carry is constant, support only 0.
809 if (*val != 0)
810 return false;
811
812 Opcode = X86::ADD32rr;
813 } else
814 return false;
815
816 MachineInstr &AddInst =
817 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
818 .addReg(Op0Reg)
819 .addReg(Op1Reg);
820
821 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
822 .addReg(X86::EFLAGS);
823
824 if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
825 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
826 return false;
827
828 I.eraseFromParent();
829 return true;
830}
831
Igor Bregerf5035d62017-06-25 11:42:17 +0000832bool X86InstructionSelector::selectExtract(MachineInstr &I,
833 MachineRegisterInfo &MRI,
834 MachineFunction &MF) const {
835
836 if (I.getOpcode() != TargetOpcode::G_EXTRACT)
837 return false;
838
839 const unsigned DstReg = I.getOperand(0).getReg();
840 const unsigned SrcReg = I.getOperand(1).getReg();
841 int64_t Index = I.getOperand(2).getImm();
842
843 const LLT DstTy = MRI.getType(DstReg);
844 const LLT SrcTy = MRI.getType(SrcReg);
845
846 // Meanwile handle vector type only.
847 if (!DstTy.isVector())
848 return false;
849
850 if (Index % DstTy.getSizeInBits() != 0)
851 return false; // Not extract subvector.
852
853 if (Index == 0) {
854 // Replace by extract subreg copy.
855 if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))
856 return false;
857
858 I.eraseFromParent();
859 return true;
860 }
861
862 bool HasAVX = STI.hasAVX();
863 bool HasAVX512 = STI.hasAVX512();
864 bool HasVLX = STI.hasVLX();
865
866 if (SrcTy.getSizeInBits() == 256 && DstTy.getSizeInBits() == 128) {
867 if (HasVLX)
868 I.setDesc(TII.get(X86::VEXTRACTF32x4Z256rr));
869 else if (HasAVX)
870 I.setDesc(TII.get(X86::VEXTRACTF128rr));
871 else
872 return false;
873 } else if (SrcTy.getSizeInBits() == 512 && HasAVX512) {
874 if (DstTy.getSizeInBits() == 128)
875 I.setDesc(TII.get(X86::VEXTRACTF32x4Zrr));
876 else if (DstTy.getSizeInBits() == 256)
877 I.setDesc(TII.get(X86::VEXTRACTF64x4Zrr));
878 else
879 return false;
880 } else
881 return false;
882
883 // Convert to X86 VEXTRACT immediate.
884 Index = Index / DstTy.getSizeInBits();
885 I.getOperand(2).setImm(Index);
886
887 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
888}
889
890bool X86InstructionSelector::emitExtractSubreg(unsigned DstReg, unsigned SrcReg,
891 MachineInstr &I,
892 MachineRegisterInfo &MRI,
893 MachineFunction &MF) const {
894
895 const LLT DstTy = MRI.getType(DstReg);
896 const LLT SrcTy = MRI.getType(SrcReg);
897 unsigned SubIdx = X86::NoSubRegister;
898
899 if (!DstTy.isVector() || !SrcTy.isVector())
900 return false;
901
902 assert(SrcTy.getSizeInBits() > DstTy.getSizeInBits() &&
903 "Incorrect Src/Dst register size");
904
905 if (DstTy.getSizeInBits() == 128)
906 SubIdx = X86::sub_xmm;
907 else if (DstTy.getSizeInBits() == 256)
908 SubIdx = X86::sub_ymm;
909 else
910 return false;
911
912 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
913 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
914
915 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
916
917 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
918 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
919 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
920 return false;
921 }
922
923 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), DstReg)
924 .addReg(SrcReg, 0, SubIdx);
925
926 return true;
927}
928
Igor Breger1c29be72017-06-22 09:43:35 +0000929bool X86InstructionSelector::emitInsertSubreg(unsigned DstReg, unsigned SrcReg,
930 MachineInstr &I,
931 MachineRegisterInfo &MRI,
932 MachineFunction &MF) const {
933
934 const LLT DstTy = MRI.getType(DstReg);
935 const LLT SrcTy = MRI.getType(SrcReg);
936 unsigned SubIdx = X86::NoSubRegister;
937
938 // TODO: support scalar types
939 if (!DstTy.isVector() || !SrcTy.isVector())
940 return false;
941
942 assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&
943 "Incorrect Src/Dst register size");
944
945 if (SrcTy.getSizeInBits() == 128)
946 SubIdx = X86::sub_xmm;
947 else if (SrcTy.getSizeInBits() == 256)
948 SubIdx = X86::sub_ymm;
949 else
950 return false;
951
952 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
953 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
954
955 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
956 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
957 DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");
958 return false;
959 }
960
961 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))
962 .addReg(DstReg, RegState::DefineNoRead, SubIdx)
963 .addReg(SrcReg);
964
965 return true;
966}
967
968bool X86InstructionSelector::selectInsert(MachineInstr &I,
969 MachineRegisterInfo &MRI,
970 MachineFunction &MF) const {
971
972 if (I.getOpcode() != TargetOpcode::G_INSERT)
973 return false;
974
975 const unsigned DstReg = I.getOperand(0).getReg();
976 const unsigned SrcReg = I.getOperand(1).getReg();
977 const unsigned InsertReg = I.getOperand(2).getReg();
978 int64_t Index = I.getOperand(3).getImm();
979
980 const LLT DstTy = MRI.getType(DstReg);
981 const LLT InsertRegTy = MRI.getType(InsertReg);
982
983 // Meanwile handle vector type only.
984 if (!DstTy.isVector())
985 return false;
986
987 if (Index % InsertRegTy.getSizeInBits() != 0)
988 return false; // Not insert subvector.
989
990 if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {
991 // Replace by subreg copy.
992 if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
993 return false;
994
995 I.eraseFromParent();
996 return true;
997 }
998
999 bool HasAVX = STI.hasAVX();
1000 bool HasAVX512 = STI.hasAVX512();
1001 bool HasVLX = STI.hasVLX();
1002
1003 if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {
1004 if (HasVLX)
1005 I.setDesc(TII.get(X86::VINSERTF32x4Z256rr));
1006 else if (HasAVX)
1007 I.setDesc(TII.get(X86::VINSERTF128rr));
1008 else
1009 return false;
1010 } else if (DstTy.getSizeInBits() == 512 && HasAVX512) {
1011 if (InsertRegTy.getSizeInBits() == 128)
1012 I.setDesc(TII.get(X86::VINSERTF32x4Zrr));
1013 else if (InsertRegTy.getSizeInBits() == 256)
1014 I.setDesc(TII.get(X86::VINSERTF64x4Zrr));
1015 else
1016 return false;
1017 } else
1018 return false;
1019
1020 // Convert to X86 VINSERT immediate.
1021 Index = Index / InsertRegTy.getSizeInBits();
1022
1023 I.getOperand(3).setImm(Index);
1024
1025 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
1026}
1027
Igor Bregerb186a692017-07-02 08:15:49 +00001028bool X86InstructionSelector::selectUnmergeValues(MachineInstr &I,
1029 MachineRegisterInfo &MRI,
1030 MachineFunction &MF) const {
1031 if (I.getOpcode() != TargetOpcode::G_UNMERGE_VALUES)
1032 return false;
1033
1034 // Split to extracts.
1035 unsigned NumDefs = I.getNumOperands() - 1;
1036 unsigned SrcReg = I.getOperand(NumDefs).getReg();
1037 unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
1038
1039 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1040
1041 MachineInstr &ExtrInst =
1042 *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1043 TII.get(TargetOpcode::G_EXTRACT), I.getOperand(Idx).getReg())
1044 .addReg(SrcReg)
1045 .addImm(Idx * DefSize);
1046
1047 if (!select(ExtrInst))
1048 return false;
1049 }
1050
1051 I.eraseFromParent();
1052 return true;
1053}
1054
Igor Breger0cddd342017-06-29 12:08:28 +00001055bool X86InstructionSelector::selectMergeValues(MachineInstr &I,
1056 MachineRegisterInfo &MRI,
1057 MachineFunction &MF) const {
1058 if (I.getOpcode() != TargetOpcode::G_MERGE_VALUES)
1059 return false;
1060
1061 // Split to inserts.
1062 unsigned DstReg = I.getOperand(0).getReg();
1063 unsigned SrcReg0 = I.getOperand(1).getReg();
1064
1065 const LLT DstTy = MRI.getType(DstReg);
1066 const LLT SrcTy = MRI.getType(SrcReg0);
1067 unsigned SrcSize = SrcTy.getSizeInBits();
1068
1069 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1070
1071 // For the first src use insertSubReg.
1072 unsigned DefReg = MRI.createGenericVirtualRegister(DstTy);
1073 MRI.setRegBank(DefReg, RegBank);
1074 if (!emitInsertSubreg(DefReg, I.getOperand(1).getReg(), I, MRI, MF))
1075 return false;
1076
1077 for (unsigned Idx = 2; Idx < I.getNumOperands(); ++Idx) {
1078
1079 unsigned Tmp = MRI.createGenericVirtualRegister(DstTy);
1080 MRI.setRegBank(Tmp, RegBank);
1081
1082 MachineInstr &InsertInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1083 TII.get(TargetOpcode::G_INSERT), Tmp)
1084 .addReg(DefReg)
1085 .addReg(I.getOperand(Idx).getReg())
1086 .addImm((Idx - 1) * SrcSize);
1087
1088 DefReg = Tmp;
1089
1090 if (!select(InsertInst))
1091 return false;
1092 }
1093
1094 MachineInstr &CopyInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1095 TII.get(TargetOpcode::COPY), DstReg)
1096 .addReg(DefReg);
1097
1098 if (!select(CopyInst))
1099 return false;
1100
1101 I.eraseFromParent();
1102 return true;
1103}
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001104InstructionSelector *
Daniel Sanderse7b0d662017-04-21 15:59:56 +00001105llvm::createX86InstructionSelector(const X86TargetMachine &TM,
1106 X86Subtarget &Subtarget,
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001107 X86RegisterBankInfo &RBI) {
Daniel Sanderse7b0d662017-04-21 15:59:56 +00001108 return new X86InstructionSelector(TM, Subtarget, RBI);
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001109}