blob: 6bce2558c021a936b3406717f13596f4177f51bb [file] [log] [blame]
Eugene Zelenko60433b62017-10-05 00:33:50 +00001//===- X86InstructionSelector.cpp -----------------------------------------===//
Igor Bregerf7359d82017-02-22 12:25:09 +00002//
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
Eugene Zelenko60433b62017-10-05 00:33:50 +000015#define DEBUG_TYPE "X86-isel"
16
17#include "MCTargetDesc/X86BaseInfo.h"
Igor Bregera8ba5722017-03-23 15:25:57 +000018#include "X86InstrBuilder.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000019#include "X86InstrInfo.h"
20#include "X86RegisterBankInfo.h"
21#include "X86RegisterInfo.h"
22#include "X86Subtarget.h"
23#include "X86TargetMachine.h"
Igor Breger3b97ea32017-04-12 12:54:54 +000024#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
Eugene Zelenko60433b62017-10-05 00:33:50 +000025#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
26#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
Igor Breger28f290f2017-05-17 12:48:08 +000027#include "llvm/CodeGen/GlobalISel/Utils.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000028#include "llvm/CodeGen/MachineBasicBlock.h"
Igor Breger21200ed2017-09-17 08:08:13 +000029#include "llvm/CodeGen/MachineConstantPool.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000030#include "llvm/CodeGen/MachineFunction.h"
31#include "llvm/CodeGen/MachineInstr.h"
32#include "llvm/CodeGen/MachineInstrBuilder.h"
Eugene Zelenko60433b62017-10-05 00:33:50 +000033#include "llvm/CodeGen/MachineMemOperand.h"
Daniel Sanders0b5293f2017-04-06 09:49:34 +000034#include "llvm/CodeGen/MachineOperand.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000035#include "llvm/CodeGen/MachineRegisterInfo.h"
Eugene Zelenko60433b62017-10-05 00:33:50 +000036#include "llvm/IR/DataLayout.h"
37#include "llvm/IR/InstrTypes.h"
38#include "llvm/Support/AtomicOrdering.h"
39#include "llvm/Support/CodeGen.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000040#include "llvm/Support/Debug.h"
Eugene Zelenko60433b62017-10-05 00:33:50 +000041#include "llvm/Support/ErrorHandling.h"
42#include "llvm/Support/LowLevelTypeImpl.h"
43#include "llvm/Support/MathExtras.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000044#include "llvm/Support/raw_ostream.h"
Eugene Zelenko60433b62017-10-05 00:33:50 +000045#include "llvm/Target/TargetOpcodes.h"
46#include "llvm/Target/TargetRegisterInfo.h"
47#include <cassert>
48#include <cstdint>
49#include <tuple>
Daniel Sanders6ab0daa2017-07-04 14:35:06 +000050
Igor Bregerf7359d82017-02-22 12:25:09 +000051using namespace llvm;
52
Daniel Sanders0b5293f2017-04-06 09:49:34 +000053namespace {
54
Daniel Sanderse7b0d662017-04-21 15:59:56 +000055#define GET_GLOBALISEL_PREDICATE_BITSET
56#include "X86GenGlobalISel.inc"
57#undef GET_GLOBALISEL_PREDICATE_BITSET
58
Daniel Sanders0b5293f2017-04-06 09:49:34 +000059class X86InstructionSelector : public InstructionSelector {
60public:
Daniel Sanderse7b0d662017-04-21 15:59:56 +000061 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
Daniel Sanders0b5293f2017-04-06 09:49:34 +000062 const X86RegisterBankInfo &RBI);
63
64 bool select(MachineInstr &I) const override;
65
66private:
67 /// tblgen-erated 'select' implementation, used as the initial selector for
68 /// the patterns that don't require complex C++.
69 bool selectImpl(MachineInstr &I) const;
70
Hiroshi Inouebb703e82017-07-02 03:24:54 +000071 // TODO: remove after supported by Tablegen-erated instruction selection.
Igor Breger21200ed2017-09-17 08:08:13 +000072 unsigned getLoadStoreOp(const LLT &Ty, const RegisterBank &RB, unsigned Opc,
Daniel Sanders0b5293f2017-04-06 09:49:34 +000073 uint64_t Alignment) const;
74
Daniel Sanders0b5293f2017-04-06 09:49:34 +000075 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
76 MachineFunction &MF) const;
Igor Breger810c6252017-05-08 09:40:43 +000077 bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
78 MachineFunction &MF) const;
Igor Breger717bd362017-07-02 08:58:29 +000079 bool selectGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI,
80 MachineFunction &MF) const;
Igor Breger3b97ea32017-04-12 12:54:54 +000081 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
82 MachineFunction &MF) const;
Igor Breger4fdf1e42017-04-19 11:34:59 +000083 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
84 MachineFunction &MF) const;
Igor Bregerfda31e62017-05-10 06:52:58 +000085 bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
86 MachineFunction &MF) const;
Igor Breger1f143642017-09-11 09:41:13 +000087 bool selectAnyext(MachineInstr &I, MachineRegisterInfo &MRI,
88 MachineFunction &MF) const;
Igor Bregerc7b59772017-05-11 07:17:40 +000089 bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
90 MachineFunction &MF) const;
Igor Breger28f290f2017-05-17 12:48:08 +000091 bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
92 MachineFunction &MF) const;
Igor Breger1dcd5e82017-06-20 09:15:10 +000093 bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
Igor Bregerb186a692017-07-02 08:15:49 +000094 bool selectUnmergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
95 MachineFunction &MF) const;
Igor Breger0cddd342017-06-29 12:08:28 +000096 bool selectMergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
97 MachineFunction &MF) const;
Igor Breger1c29be72017-06-22 09:43:35 +000098 bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,
99 MachineFunction &MF) const;
Igor Bregerf5035d62017-06-25 11:42:17 +0000100 bool selectExtract(MachineInstr &I, MachineRegisterInfo &MRI,
101 MachineFunction &MF) const;
Igor Breger685889c2017-08-21 10:51:54 +0000102 bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
103 MachineFunction &MF) const;
Igor Breger21200ed2017-09-17 08:08:13 +0000104 bool materializeFP(MachineInstr &I, MachineRegisterInfo &MRI,
105 MachineFunction &MF) const;
Igor Breger2661ae42017-09-04 09:06:45 +0000106 bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const;
Igor Breger1c29be72017-06-22 09:43:35 +0000107
108 // emit insert subreg instruction and insert it before MachineInstr &I
109 bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
110 MachineRegisterInfo &MRI, MachineFunction &MF) const;
Igor Bregerf5035d62017-06-25 11:42:17 +0000111 // emit extract subreg instruction and insert it before MachineInstr &I
112 bool emitExtractSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
113 MachineRegisterInfo &MRI, MachineFunction &MF) const;
Igor Breger1dcd5e82017-06-20 09:15:10 +0000114
115 const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
116 const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,
117 MachineRegisterInfo &MRI) const;
Igor Breger28f290f2017-05-17 12:48:08 +0000118
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000119 const X86TargetMachine &TM;
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000120 const X86Subtarget &STI;
121 const X86InstrInfo &TII;
122 const X86RegisterInfo &TRI;
123 const X86RegisterBankInfo &RBI;
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000124
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000125#define GET_GLOBALISEL_PREDICATES_DECL
126#include "X86GenGlobalISel.inc"
127#undef GET_GLOBALISEL_PREDICATES_DECL
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000128
129#define GET_GLOBALISEL_TEMPORARIES_DECL
130#include "X86GenGlobalISel.inc"
131#undef GET_GLOBALISEL_TEMPORARIES_DECL
132};
133
134} // end anonymous namespace
135
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000136#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000137#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000138#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000139
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000140X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
141 const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +0000142 const X86RegisterBankInfo &RBI)
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000143 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000144 TRI(*STI.getRegisterInfo()), RBI(RBI),
145#define GET_GLOBALISEL_PREDICATES_INIT
146#include "X86GenGlobalISel.inc"
147#undef GET_GLOBALISEL_PREDICATES_INIT
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000148#define GET_GLOBALISEL_TEMPORARIES_INIT
149#include "X86GenGlobalISel.inc"
150#undef GET_GLOBALISEL_TEMPORARIES_INIT
151{
152}
Igor Bregerf7359d82017-02-22 12:25:09 +0000153
154// FIXME: This should be target-independent, inferred from the types declared
155// for each class in the bank.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000156const TargetRegisterClass *
157X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000158 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger4fdf1e42017-04-19 11:34:59 +0000159 if (Ty.getSizeInBits() <= 8)
160 return &X86::GR8RegClass;
161 if (Ty.getSizeInBits() == 16)
162 return &X86::GR16RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000163 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000164 return &X86::GR32RegClass;
165 if (Ty.getSizeInBits() == 64)
166 return &X86::GR64RegClass;
167 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000168 if (RB.getID() == X86::VECRRegBankID) {
169 if (Ty.getSizeInBits() == 32)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000170 return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000171 if (Ty.getSizeInBits() == 64)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000172 return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000173 if (Ty.getSizeInBits() == 128)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000174 return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000175 if (Ty.getSizeInBits() == 256)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000176 return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000177 if (Ty.getSizeInBits() == 512)
178 return &X86::VR512RegClass;
179 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000180
181 llvm_unreachable("Unknown RegBank!");
182}
183
Igor Breger1dcd5e82017-06-20 09:15:10 +0000184const TargetRegisterClass *
185X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,
186 MachineRegisterInfo &MRI) const {
187 const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
188 return getRegClass(Ty, RegBank);
189}
190
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000191static unsigned getSubRegIndex(const TargetRegisterClass *RC) {
Igor Bregerb3a860a2017-08-20 07:14:40 +0000192 unsigned SubIdx = X86::NoSubRegister;
193 if (RC == &X86::GR32RegClass) {
194 SubIdx = X86::sub_32bit;
195 } else if (RC == &X86::GR16RegClass) {
196 SubIdx = X86::sub_16bit;
197 } else if (RC == &X86::GR8RegClass) {
198 SubIdx = X86::sub_8bit;
199 }
200
201 return SubIdx;
202}
203
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000204static const TargetRegisterClass *getRegClassFromGRPhysReg(unsigned Reg) {
Igor Bregerb3a860a2017-08-20 07:14:40 +0000205 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
206 if (X86::GR64RegClass.contains(Reg))
207 return &X86::GR64RegClass;
208 if (X86::GR32RegClass.contains(Reg))
209 return &X86::GR32RegClass;
210 if (X86::GR16RegClass.contains(Reg))
211 return &X86::GR16RegClass;
212 if (X86::GR8RegClass.contains(Reg))
213 return &X86::GR8RegClass;
214
215 llvm_unreachable("Unknown RegClass for PhysReg!");
216}
217
Igor Bregerf7359d82017-02-22 12:25:09 +0000218// Set X86 Opcode and constrain DestReg.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000219bool X86InstructionSelector::selectCopy(MachineInstr &I,
220 MachineRegisterInfo &MRI) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000221 unsigned DstReg = I.getOperand(0).getReg();
Igor Bregerb3a860a2017-08-20 07:14:40 +0000222 const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI);
223 const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
Igor Bregerf7359d82017-02-22 12:25:09 +0000224
Igor Bregerf7359d82017-02-22 12:25:09 +0000225 unsigned SrcReg = I.getOperand(1).getReg();
226 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
Igor Bregerb3a860a2017-08-20 07:14:40 +0000227 const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
228
229 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
230 assert(I.isCopy() && "Generic operators do not allow physical registers");
231
232 if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID &&
233 DstRegBank.getID() == X86::GPRRegBankID) {
234
235 const TargetRegisterClass *SrcRC =
236 getRegClass(MRI.getType(SrcReg), SrcRegBank);
237 const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg);
238
239 if (SrcRC != DstRC) {
240 // This case can be generated by ABI lowering, performe anyext
241 unsigned ExtSrc = MRI.createVirtualRegister(DstRC);
242 BuildMI(*I.getParent(), I, I.getDebugLoc(),
243 TII.get(TargetOpcode::SUBREG_TO_REG))
244 .addDef(ExtSrc)
245 .addImm(0)
246 .addReg(SrcReg)
247 .addImm(getSubRegIndex(SrcRC));
248
249 I.getOperand(1).setReg(ExtSrc);
250 }
251 }
252
253 return true;
254 }
Igor Breger360d0f22017-04-27 08:02:03 +0000255
Igor Bregerf7359d82017-02-22 12:25:09 +0000256 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
257 "No phys reg on generic operators");
258 assert((DstSize == SrcSize ||
259 // Copies are a mean to setup initial types, the number of
260 // bits may not exactly match.
261 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
262 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
263 "Copy with different width?!");
264
Igor Bregerb3a860a2017-08-20 07:14:40 +0000265 const TargetRegisterClass *DstRC =
266 getRegClass(MRI.getType(DstReg), DstRegBank);
Igor Bregerf7359d82017-02-22 12:25:09 +0000267
Igor Bregerb3a860a2017-08-20 07:14:40 +0000268 if (SrcRegBank.getID() == X86::GPRRegBankID &&
269 DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize &&
270 TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
271 // Change the physical register to performe truncate.
Igor Breger360d0f22017-04-27 08:02:03 +0000272
Igor Bregerb3a860a2017-08-20 07:14:40 +0000273 const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg);
Igor Breger360d0f22017-04-27 08:02:03 +0000274
Igor Bregerb3a860a2017-08-20 07:14:40 +0000275 if (DstRC != SrcRC) {
276 I.getOperand(1).setSubReg(getSubRegIndex(DstRC));
Igor Breger360d0f22017-04-27 08:02:03 +0000277 I.getOperand(1).substPhysReg(SrcReg, TRI);
278 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000279 }
280
281 // No need to constrain SrcReg. It will get constrained when
282 // we hit another of its use or its defs.
283 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000284 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Bregerb3a860a2017-08-20 07:14:40 +0000285 if (!OldRC || !DstRC->hasSubClassEq(OldRC)) {
286 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000287 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
288 << " operand\n");
289 return false;
290 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000291 }
292 I.setDesc(TII.get(X86::COPY));
293 return true;
294}
295
296bool X86InstructionSelector::select(MachineInstr &I) const {
297 assert(I.getParent() && "Instruction should be in a basic block!");
298 assert(I.getParent()->getParent() && "Instruction should be in a function!");
299
300 MachineBasicBlock &MBB = *I.getParent();
301 MachineFunction &MF = *MBB.getParent();
302 MachineRegisterInfo &MRI = MF.getRegInfo();
303
304 unsigned Opcode = I.getOpcode();
305 if (!isPreISelGenericOpcode(Opcode)) {
306 // Certain non-generic instructions also need some special handling.
307
Igor Breger03c22082017-08-21 09:17:28 +0000308 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
309 return false;
Igor Breger03c22082017-08-21 09:17:28 +0000310
Igor Bregerf7359d82017-02-22 12:25:09 +0000311 if (I.isCopy())
Igor Breger1dcd5e82017-06-20 09:15:10 +0000312 return selectCopy(I, MRI);
Igor Bregerf7359d82017-02-22 12:25:09 +0000313
Igor Bregerf7359d82017-02-22 12:25:09 +0000314 return true;
315 }
316
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000317 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
318 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000319
Igor Breger2452ef02017-05-01 07:06:08 +0000320 if (selectImpl(I))
Igor Bregerfda31e62017-05-10 06:52:58 +0000321 return true;
Igor Breger2452ef02017-05-01 07:06:08 +0000322
323 DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
324
325 // TODO: This should be implemented by tblgen.
Igor Breger06335bb2017-09-17 14:02:19 +0000326 switch (I.getOpcode()) {
327 default:
328 return false;
329 case TargetOpcode::G_STORE:
330 case TargetOpcode::G_LOAD:
331 return selectLoadStoreOp(I, MRI, MF);
332 case TargetOpcode::G_GEP:
333 case TargetOpcode::G_FRAME_INDEX:
334 return selectFrameIndexOrGep(I, MRI, MF);
335 case TargetOpcode::G_GLOBAL_VALUE:
336 return selectGlobalValue(I, MRI, MF);
337 case TargetOpcode::G_CONSTANT:
338 return selectConstant(I, MRI, MF);
339 case TargetOpcode::G_FCONSTANT:
340 return materializeFP(I, MRI, MF);
341 case TargetOpcode::G_TRUNC:
342 return selectTrunc(I, MRI, MF);
343 case TargetOpcode::G_ZEXT:
344 return selectZext(I, MRI, MF);
345 case TargetOpcode::G_ANYEXT:
346 return selectAnyext(I, MRI, MF);
347 case TargetOpcode::G_ICMP:
348 return selectCmp(I, MRI, MF);
349 case TargetOpcode::G_UADDE:
350 return selectUadde(I, MRI, MF);
351 case TargetOpcode::G_UNMERGE_VALUES:
352 return selectUnmergeValues(I, MRI, MF);
353 case TargetOpcode::G_MERGE_VALUES:
354 return selectMergeValues(I, MRI, MF);
355 case TargetOpcode::G_EXTRACT:
356 return selectExtract(I, MRI, MF);
357 case TargetOpcode::G_INSERT:
358 return selectInsert(I, MRI, MF);
359 case TargetOpcode::G_BRCOND:
360 return selectCondBranch(I, MRI, MF);
361 case TargetOpcode::G_IMPLICIT_DEF:
362 case TargetOpcode::G_PHI:
363 return selectImplicitDefOrPHI(I, MRI);
364 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000365
Igor Breger2452ef02017-05-01 07:06:08 +0000366 return false;
Igor Bregerf7359d82017-02-22 12:25:09 +0000367}
Igor Breger321cf3c2017-03-03 08:06:46 +0000368
Igor Breger21200ed2017-09-17 08:08:13 +0000369unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty,
370 const RegisterBank &RB,
Igor Bregera8ba5722017-03-23 15:25:57 +0000371 unsigned Opc,
372 uint64_t Alignment) const {
373 bool Isload = (Opc == TargetOpcode::G_LOAD);
374 bool HasAVX = STI.hasAVX();
375 bool HasAVX512 = STI.hasAVX512();
376 bool HasVLX = STI.hasVLX();
377
378 if (Ty == LLT::scalar(8)) {
379 if (X86::GPRRegBankID == RB.getID())
380 return Isload ? X86::MOV8rm : X86::MOV8mr;
381 } else if (Ty == LLT::scalar(16)) {
382 if (X86::GPRRegBankID == RB.getID())
383 return Isload ? X86::MOV16rm : X86::MOV16mr;
Igor Bregera9edb882017-05-01 06:08:32 +0000384 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000385 if (X86::GPRRegBankID == RB.getID())
386 return Isload ? X86::MOV32rm : X86::MOV32mr;
387 if (X86::VECRRegBankID == RB.getID())
388 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
389 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
390 : (HasAVX512 ? X86::VMOVSSZmr
391 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
Igor Bregera9edb882017-05-01 06:08:32 +0000392 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000393 if (X86::GPRRegBankID == RB.getID())
394 return Isload ? X86::MOV64rm : X86::MOV64mr;
395 if (X86::VECRRegBankID == RB.getID())
396 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
397 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
398 : (HasAVX512 ? X86::VMOVSDZmr
399 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
400 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
401 if (Alignment >= 16)
402 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
403 : HasAVX512
404 ? X86::VMOVAPSZ128rm_NOVLX
405 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
406 : (HasVLX ? X86::VMOVAPSZ128mr
407 : HasAVX512
408 ? X86::VMOVAPSZ128mr_NOVLX
409 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
410 else
411 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
412 : HasAVX512
413 ? X86::VMOVUPSZ128rm_NOVLX
414 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
415 : (HasVLX ? X86::VMOVUPSZ128mr
416 : HasAVX512
417 ? X86::VMOVUPSZ128mr_NOVLX
418 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
Igor Breger617be6e2017-05-23 08:23:51 +0000419 } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
420 if (Alignment >= 32)
421 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
422 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
423 : X86::VMOVAPSYrm)
424 : (HasVLX ? X86::VMOVAPSZ256mr
425 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
426 : X86::VMOVAPSYmr);
427 else
428 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
429 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
430 : X86::VMOVUPSYrm)
431 : (HasVLX ? X86::VMOVUPSZ256mr
432 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
433 : X86::VMOVUPSYmr);
434 } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
435 if (Alignment >= 64)
436 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
437 else
438 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
Igor Bregera8ba5722017-03-23 15:25:57 +0000439 }
440 return Opc;
441}
442
Igor Bregerbd2deda2017-06-19 13:12:57 +0000443// Fill in an address from the given instruction.
Benjamin Kramer49a49fe2017-08-20 13:03:48 +0000444static void X86SelectAddress(const MachineInstr &I,
445 const MachineRegisterInfo &MRI,
446 X86AddressMode &AM) {
Igor Bregerbd2deda2017-06-19 13:12:57 +0000447 assert(I.getOperand(0).isReg() && "unsupported opperand.");
448 assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
449 "unsupported type.");
450
451 if (I.getOpcode() == TargetOpcode::G_GEP) {
452 if (auto COff = getConstantVRegVal(I.getOperand(2).getReg(), MRI)) {
453 int64_t Imm = *COff;
454 if (isInt<32>(Imm)) { // Check for displacement overflow.
455 AM.Disp = static_cast<int32_t>(Imm);
456 AM.Base.Reg = I.getOperand(1).getReg();
457 return;
458 }
459 }
460 } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
461 AM.Base.FrameIndex = I.getOperand(1).getIndex();
462 AM.BaseType = X86AddressMode::FrameIndexBase;
463 return;
464 }
465
466 // Default behavior.
467 AM.Base.Reg = I.getOperand(0).getReg();
Igor Bregerbd2deda2017-06-19 13:12:57 +0000468}
469
Igor Bregera8ba5722017-03-23 15:25:57 +0000470bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
471 MachineRegisterInfo &MRI,
472 MachineFunction &MF) const {
Igor Bregera8ba5722017-03-23 15:25:57 +0000473 unsigned Opc = I.getOpcode();
474
Igor Breger06335bb2017-09-17 14:02:19 +0000475 assert((Opc == TargetOpcode::G_STORE || Opc == TargetOpcode::G_LOAD) &&
476 "unexpected instruction");
Igor Bregera8ba5722017-03-23 15:25:57 +0000477
478 const unsigned DefReg = I.getOperand(0).getReg();
479 LLT Ty = MRI.getType(DefReg);
480 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
481
482 auto &MemOp = **I.memoperands_begin();
Igor Bregerbd2deda2017-06-19 13:12:57 +0000483 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
484 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
485 return false;
486 }
487
Igor Bregera8ba5722017-03-23 15:25:57 +0000488 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
489 if (NewOpc == Opc)
490 return false;
491
Igor Bregerbd2deda2017-06-19 13:12:57 +0000492 X86AddressMode AM;
493 X86SelectAddress(*MRI.getVRegDef(I.getOperand(1).getReg()), MRI, AM);
494
Igor Bregera8ba5722017-03-23 15:25:57 +0000495 I.setDesc(TII.get(NewOpc));
496 MachineInstrBuilder MIB(MF, I);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000497 if (Opc == TargetOpcode::G_LOAD) {
498 I.RemoveOperand(1);
499 addFullAddress(MIB, AM);
500 } else {
Igor Bregera8ba5722017-03-23 15:25:57 +0000501 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
Igor Bregerbd2deda2017-06-19 13:12:57 +0000502 I.RemoveOperand(1);
Igor Bregera8ba5722017-03-23 15:25:57 +0000503 I.RemoveOperand(0);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000504 addFullAddress(MIB, AM).addUse(DefReg);
Igor Bregera8ba5722017-03-23 15:25:57 +0000505 }
506 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
507}
508
Igor Breger717bd362017-07-02 08:58:29 +0000509static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) {
510 if (Ty == LLT::pointer(0, 64))
511 return X86::LEA64r;
512 else if (Ty == LLT::pointer(0, 32))
513 return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
514 else
515 llvm_unreachable("Can't get LEA opcode. Unsupported type.");
516}
517
Igor Breger810c6252017-05-08 09:40:43 +0000518bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
519 MachineRegisterInfo &MRI,
520 MachineFunction &MF) const {
521 unsigned Opc = I.getOpcode();
522
Igor Breger06335bb2017-09-17 14:02:19 +0000523 assert((Opc == TargetOpcode::G_FRAME_INDEX || Opc == TargetOpcode::G_GEP) &&
524 "unexpected instruction");
Igor Breger531a2032017-03-26 08:11:12 +0000525
526 const unsigned DefReg = I.getOperand(0).getReg();
527 LLT Ty = MRI.getType(DefReg);
528
Igor Breger810c6252017-05-08 09:40:43 +0000529 // Use LEA to calculate frame index and GEP
Igor Breger717bd362017-07-02 08:58:29 +0000530 unsigned NewOpc = getLeaOP(Ty, STI);
Igor Breger531a2032017-03-26 08:11:12 +0000531 I.setDesc(TII.get(NewOpc));
532 MachineInstrBuilder MIB(MF, I);
Igor Breger810c6252017-05-08 09:40:43 +0000533
534 if (Opc == TargetOpcode::G_FRAME_INDEX) {
535 addOffset(MIB, 0);
536 } else {
537 MachineOperand &InxOp = I.getOperand(2);
538 I.addOperand(InxOp); // set IndexReg
539 InxOp.ChangeToImmediate(1); // set Scale
540 MIB.addImm(0).addReg(0);
541 }
Igor Breger531a2032017-03-26 08:11:12 +0000542
543 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
544}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000545
Igor Breger717bd362017-07-02 08:58:29 +0000546bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,
547 MachineRegisterInfo &MRI,
548 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +0000549 assert((I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE) &&
550 "unexpected instruction");
Igor Breger717bd362017-07-02 08:58:29 +0000551
552 auto GV = I.getOperand(1).getGlobal();
553 if (GV->isThreadLocal()) {
554 return false; // TODO: we don't support TLS yet.
555 }
556
557 // Can't handle alternate code models yet.
558 if (TM.getCodeModel() != CodeModel::Small)
Eugene Zelenko60433b62017-10-05 00:33:50 +0000559 return false;
Igor Breger717bd362017-07-02 08:58:29 +0000560
561 X86AddressMode AM;
562 AM.GV = GV;
563 AM.GVOpFlags = STI.classifyGlobalReference(GV);
564
565 // TODO: The ABI requires an extra load. not supported yet.
566 if (isGlobalStubReference(AM.GVOpFlags))
567 return false;
568
569 // TODO: This reference is relative to the pic base. not supported yet.
570 if (isGlobalRelativeToPICBase(AM.GVOpFlags))
571 return false;
572
573 if (STI.isPICStyleRIPRel()) {
574 // Use rip-relative addressing.
575 assert(AM.Base.Reg == 0 && AM.IndexReg == 0);
576 AM.Base.Reg = X86::RIP;
577 }
578
579 const unsigned DefReg = I.getOperand(0).getReg();
580 LLT Ty = MRI.getType(DefReg);
581 unsigned NewOpc = getLeaOP(Ty, STI);
582
583 I.setDesc(TII.get(NewOpc));
584 MachineInstrBuilder MIB(MF, I);
585
586 I.RemoveOperand(1);
587 addFullAddress(MIB, AM);
588
589 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
590}
591
Igor Breger3b97ea32017-04-12 12:54:54 +0000592bool X86InstructionSelector::selectConstant(MachineInstr &I,
593 MachineRegisterInfo &MRI,
594 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +0000595 assert((I.getOpcode() == TargetOpcode::G_CONSTANT) &&
596 "unexpected instruction");
Igor Breger3b97ea32017-04-12 12:54:54 +0000597
598 const unsigned DefReg = I.getOperand(0).getReg();
599 LLT Ty = MRI.getType(DefReg);
600
Igor Breger5c787ab2017-07-03 11:06:54 +0000601 if (RBI.getRegBank(DefReg, MRI, TRI)->getID() != X86::GPRRegBankID)
602 return false;
Igor Breger3b97ea32017-04-12 12:54:54 +0000603
604 uint64_t Val = 0;
605 if (I.getOperand(1).isCImm()) {
606 Val = I.getOperand(1).getCImm()->getZExtValue();
607 I.getOperand(1).ChangeToImmediate(Val);
608 } else if (I.getOperand(1).isImm()) {
609 Val = I.getOperand(1).getImm();
610 } else
611 llvm_unreachable("Unsupported operand type.");
612
613 unsigned NewOpc;
614 switch (Ty.getSizeInBits()) {
615 case 8:
616 NewOpc = X86::MOV8ri;
617 break;
618 case 16:
619 NewOpc = X86::MOV16ri;
620 break;
621 case 32:
622 NewOpc = X86::MOV32ri;
623 break;
Eugene Zelenko60433b62017-10-05 00:33:50 +0000624 case 64:
Igor Breger3b97ea32017-04-12 12:54:54 +0000625 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
626 if (isInt<32>(Val))
627 NewOpc = X86::MOV64ri32;
628 else
629 NewOpc = X86::MOV64ri;
630 break;
Igor Breger3b97ea32017-04-12 12:54:54 +0000631 default:
632 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
633 }
634
635 I.setDesc(TII.get(NewOpc));
636 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
637}
638
Igor Breger4fdf1e42017-04-19 11:34:59 +0000639bool X86InstructionSelector::selectTrunc(MachineInstr &I,
640 MachineRegisterInfo &MRI,
641 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +0000642 assert((I.getOpcode() == TargetOpcode::G_TRUNC) && "unexpected instruction");
Igor Breger4fdf1e42017-04-19 11:34:59 +0000643
644 const unsigned DstReg = I.getOperand(0).getReg();
645 const unsigned SrcReg = I.getOperand(1).getReg();
646
647 const LLT DstTy = MRI.getType(DstReg);
648 const LLT SrcTy = MRI.getType(SrcReg);
649
650 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
651 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
652
653 if (DstRB.getID() != SrcRB.getID()) {
654 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
655 return false;
656 }
657
658 if (DstRB.getID() != X86::GPRRegBankID)
659 return false;
660
Igor Breger1dcd5e82017-06-20 09:15:10 +0000661 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000662 if (!DstRC)
663 return false;
664
Igor Breger1dcd5e82017-06-20 09:15:10 +0000665 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000666 if (!SrcRC)
667 return false;
668
Igor Breger014fc562017-05-21 11:13:56 +0000669 unsigned SubIdx;
670 if (DstRC == SrcRC) {
671 // Nothing to be done
672 SubIdx = X86::NoSubRegister;
673 } else if (DstRC == &X86::GR32RegClass) {
674 SubIdx = X86::sub_32bit;
675 } else if (DstRC == &X86::GR16RegClass) {
676 SubIdx = X86::sub_16bit;
677 } else if (DstRC == &X86::GR8RegClass) {
678 SubIdx = X86::sub_8bit;
679 } else {
680 return false;
681 }
682
683 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
684
Igor Breger4fdf1e42017-04-19 11:34:59 +0000685 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
686 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
687 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
688 return false;
689 }
690
Igor Breger014fc562017-05-21 11:13:56 +0000691 I.getOperand(1).setSubReg(SubIdx);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000692
693 I.setDesc(TII.get(X86::COPY));
694 return true;
695}
696
Igor Bregerfda31e62017-05-10 06:52:58 +0000697bool X86InstructionSelector::selectZext(MachineInstr &I,
698 MachineRegisterInfo &MRI,
699 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +0000700 assert((I.getOpcode() == TargetOpcode::G_ZEXT) && "unexpected instruction");
Igor Bregerfda31e62017-05-10 06:52:58 +0000701
702 const unsigned DstReg = I.getOperand(0).getReg();
703 const unsigned SrcReg = I.getOperand(1).getReg();
704
705 const LLT DstTy = MRI.getType(DstReg);
706 const LLT SrcTy = MRI.getType(SrcReg);
707
Igor Bregerd48c5e42017-07-10 09:07:34 +0000708 if (SrcTy != LLT::scalar(1))
709 return false;
Igor Bregerfda31e62017-05-10 06:52:58 +0000710
Igor Bregerd48c5e42017-07-10 09:07:34 +0000711 unsigned AndOpc;
712 if (DstTy == LLT::scalar(8))
Igor Breger324d3792017-07-11 08:04:51 +0000713 AndOpc = X86::AND8ri;
Igor Bregerd48c5e42017-07-10 09:07:34 +0000714 else if (DstTy == LLT::scalar(16))
715 AndOpc = X86::AND16ri8;
716 else if (DstTy == LLT::scalar(32))
717 AndOpc = X86::AND32ri8;
718 else if (DstTy == LLT::scalar(64))
719 AndOpc = X86::AND64ri8;
720 else
721 return false;
Igor Bregerfda31e62017-05-10 06:52:58 +0000722
Igor Bregerd48c5e42017-07-10 09:07:34 +0000723 unsigned DefReg = SrcReg;
724 if (DstTy != LLT::scalar(8)) {
725 DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
Igor Bregerfda31e62017-05-10 06:52:58 +0000726 BuildMI(*I.getParent(), I, I.getDebugLoc(),
727 TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
728 .addImm(0)
729 .addReg(SrcReg)
730 .addImm(X86::sub_8bit);
Igor Bregerfda31e62017-05-10 06:52:58 +0000731 }
732
Igor Bregerd48c5e42017-07-10 09:07:34 +0000733 MachineInstr &AndInst =
734 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
735 .addReg(DefReg)
736 .addImm(1);
737
738 constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
739
740 I.eraseFromParent();
741 return true;
Igor Bregerfda31e62017-05-10 06:52:58 +0000742}
743
Igor Breger1f143642017-09-11 09:41:13 +0000744bool X86InstructionSelector::selectAnyext(MachineInstr &I,
745 MachineRegisterInfo &MRI,
746 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +0000747 assert((I.getOpcode() == TargetOpcode::G_ANYEXT) && "unexpected instruction");
Igor Breger1f143642017-09-11 09:41:13 +0000748
749 const unsigned DstReg = I.getOperand(0).getReg();
750 const unsigned SrcReg = I.getOperand(1).getReg();
751
752 const LLT DstTy = MRI.getType(DstReg);
753 const LLT SrcTy = MRI.getType(SrcReg);
754
755 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
756 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
757
Igor Breger21200ed2017-09-17 08:08:13 +0000758 assert(DstRB.getID() == SrcRB.getID() &&
759 "G_ANYEXT input/output on different banks\n");
Igor Breger1f143642017-09-11 09:41:13 +0000760
Igor Breger21200ed2017-09-17 08:08:13 +0000761 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
762 "G_ANYEXT incorrect operand size");
Igor Breger1f143642017-09-11 09:41:13 +0000763
764 if (DstRB.getID() != X86::GPRRegBankID)
765 return false;
766
767 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
768 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
769
770 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
771 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
772 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
773 << " operand\n");
774 return false;
775 }
776
777 if (SrcRC == DstRC) {
778 I.setDesc(TII.get(X86::COPY));
779 return true;
780 }
781
782 BuildMI(*I.getParent(), I, I.getDebugLoc(),
783 TII.get(TargetOpcode::SUBREG_TO_REG))
784 .addDef(DstReg)
785 .addImm(0)
786 .addReg(SrcReg)
787 .addImm(getSubRegIndex(SrcRC));
788
789 I.eraseFromParent();
790 return true;
791}
792
Igor Bregerc7b59772017-05-11 07:17:40 +0000793bool X86InstructionSelector::selectCmp(MachineInstr &I,
794 MachineRegisterInfo &MRI,
795 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +0000796 assert((I.getOpcode() == TargetOpcode::G_ICMP) && "unexpected instruction");
Igor Bregerc7b59772017-05-11 07:17:40 +0000797
798 X86::CondCode CC;
799 bool SwapArgs;
800 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
801 (CmpInst::Predicate)I.getOperand(1).getPredicate());
802 unsigned OpSet = X86::getSETFromCond(CC);
803
804 unsigned LHS = I.getOperand(2).getReg();
805 unsigned RHS = I.getOperand(3).getReg();
806
807 if (SwapArgs)
808 std::swap(LHS, RHS);
809
810 unsigned OpCmp;
811 LLT Ty = MRI.getType(LHS);
812
813 switch (Ty.getSizeInBits()) {
814 default:
815 return false;
816 case 8:
817 OpCmp = X86::CMP8rr;
818 break;
819 case 16:
820 OpCmp = X86::CMP16rr;
821 break;
822 case 32:
823 OpCmp = X86::CMP32rr;
824 break;
825 case 64:
826 OpCmp = X86::CMP64rr;
827 break;
828 }
829
830 MachineInstr &CmpInst =
831 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
832 .addReg(LHS)
833 .addReg(RHS);
834
835 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
836 TII.get(OpSet), I.getOperand(0).getReg());
837
838 constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
839 constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
840
841 I.eraseFromParent();
842 return true;
843}
844
Igor Breger28f290f2017-05-17 12:48:08 +0000845bool X86InstructionSelector::selectUadde(MachineInstr &I,
846 MachineRegisterInfo &MRI,
847 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +0000848 assert((I.getOpcode() == TargetOpcode::G_UADDE) && "unexpected instruction");
Igor Breger28f290f2017-05-17 12:48:08 +0000849
850 const unsigned DstReg = I.getOperand(0).getReg();
851 const unsigned CarryOutReg = I.getOperand(1).getReg();
852 const unsigned Op0Reg = I.getOperand(2).getReg();
853 const unsigned Op1Reg = I.getOperand(3).getReg();
854 unsigned CarryInReg = I.getOperand(4).getReg();
855
856 const LLT DstTy = MRI.getType(DstReg);
857
858 if (DstTy != LLT::scalar(32))
859 return false;
860
861 // find CarryIn def instruction.
862 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
863 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
864 CarryInReg = Def->getOperand(1).getReg();
865 Def = MRI.getVRegDef(CarryInReg);
866 }
867
868 unsigned Opcode;
869 if (Def->getOpcode() == TargetOpcode::G_UADDE) {
870 // carry set by prev ADD.
871
872 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
873 .addReg(CarryInReg);
874
875 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
876 return false;
877
878 Opcode = X86::ADC32rr;
879 } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
880 // carry is constant, support only 0.
881 if (*val != 0)
882 return false;
883
884 Opcode = X86::ADD32rr;
885 } else
886 return false;
887
888 MachineInstr &AddInst =
889 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
890 .addReg(Op0Reg)
891 .addReg(Op1Reg);
892
893 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
894 .addReg(X86::EFLAGS);
895
896 if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
897 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
898 return false;
899
900 I.eraseFromParent();
901 return true;
902}
903
Igor Bregerf5035d62017-06-25 11:42:17 +0000904bool X86InstructionSelector::selectExtract(MachineInstr &I,
905 MachineRegisterInfo &MRI,
906 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +0000907 assert((I.getOpcode() == TargetOpcode::G_EXTRACT) &&
908 "unexpected instruction");
Igor Bregerf5035d62017-06-25 11:42:17 +0000909
910 const unsigned DstReg = I.getOperand(0).getReg();
911 const unsigned SrcReg = I.getOperand(1).getReg();
912 int64_t Index = I.getOperand(2).getImm();
913
914 const LLT DstTy = MRI.getType(DstReg);
915 const LLT SrcTy = MRI.getType(SrcReg);
916
917 // Meanwile handle vector type only.
918 if (!DstTy.isVector())
919 return false;
920
921 if (Index % DstTy.getSizeInBits() != 0)
922 return false; // Not extract subvector.
923
924 if (Index == 0) {
925 // Replace by extract subreg copy.
926 if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))
927 return false;
928
929 I.eraseFromParent();
930 return true;
931 }
932
933 bool HasAVX = STI.hasAVX();
934 bool HasAVX512 = STI.hasAVX512();
935 bool HasVLX = STI.hasVLX();
936
937 if (SrcTy.getSizeInBits() == 256 && DstTy.getSizeInBits() == 128) {
938 if (HasVLX)
939 I.setDesc(TII.get(X86::VEXTRACTF32x4Z256rr));
940 else if (HasAVX)
941 I.setDesc(TII.get(X86::VEXTRACTF128rr));
942 else
943 return false;
944 } else if (SrcTy.getSizeInBits() == 512 && HasAVX512) {
945 if (DstTy.getSizeInBits() == 128)
946 I.setDesc(TII.get(X86::VEXTRACTF32x4Zrr));
947 else if (DstTy.getSizeInBits() == 256)
948 I.setDesc(TII.get(X86::VEXTRACTF64x4Zrr));
949 else
950 return false;
951 } else
952 return false;
953
954 // Convert to X86 VEXTRACT immediate.
955 Index = Index / DstTy.getSizeInBits();
956 I.getOperand(2).setImm(Index);
957
958 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
959}
960
961bool X86InstructionSelector::emitExtractSubreg(unsigned DstReg, unsigned SrcReg,
962 MachineInstr &I,
963 MachineRegisterInfo &MRI,
964 MachineFunction &MF) const {
Igor Bregerf5035d62017-06-25 11:42:17 +0000965 const LLT DstTy = MRI.getType(DstReg);
966 const LLT SrcTy = MRI.getType(SrcReg);
967 unsigned SubIdx = X86::NoSubRegister;
968
969 if (!DstTy.isVector() || !SrcTy.isVector())
970 return false;
971
972 assert(SrcTy.getSizeInBits() > DstTy.getSizeInBits() &&
973 "Incorrect Src/Dst register size");
974
975 if (DstTy.getSizeInBits() == 128)
976 SubIdx = X86::sub_xmm;
977 else if (DstTy.getSizeInBits() == 256)
978 SubIdx = X86::sub_ymm;
979 else
980 return false;
981
982 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
983 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
984
985 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
986
987 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
988 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
989 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
990 return false;
991 }
992
993 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), DstReg)
994 .addReg(SrcReg, 0, SubIdx);
995
996 return true;
997}
998
Igor Breger1c29be72017-06-22 09:43:35 +0000999bool X86InstructionSelector::emitInsertSubreg(unsigned DstReg, unsigned SrcReg,
1000 MachineInstr &I,
1001 MachineRegisterInfo &MRI,
1002 MachineFunction &MF) const {
Igor Breger1c29be72017-06-22 09:43:35 +00001003 const LLT DstTy = MRI.getType(DstReg);
1004 const LLT SrcTy = MRI.getType(SrcReg);
1005 unsigned SubIdx = X86::NoSubRegister;
1006
1007 // TODO: support scalar types
1008 if (!DstTy.isVector() || !SrcTy.isVector())
1009 return false;
1010
1011 assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&
1012 "Incorrect Src/Dst register size");
1013
1014 if (SrcTy.getSizeInBits() == 128)
1015 SubIdx = X86::sub_xmm;
1016 else if (SrcTy.getSizeInBits() == 256)
1017 SubIdx = X86::sub_ymm;
1018 else
1019 return false;
1020
1021 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
1022 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
1023
1024 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
1025 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1026 DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");
1027 return false;
1028 }
1029
1030 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))
1031 .addReg(DstReg, RegState::DefineNoRead, SubIdx)
1032 .addReg(SrcReg);
1033
1034 return true;
1035}
1036
1037bool X86InstructionSelector::selectInsert(MachineInstr &I,
1038 MachineRegisterInfo &MRI,
1039 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +00001040 assert((I.getOpcode() == TargetOpcode::G_INSERT) && "unexpected instruction");
Igor Breger1c29be72017-06-22 09:43:35 +00001041
1042 const unsigned DstReg = I.getOperand(0).getReg();
1043 const unsigned SrcReg = I.getOperand(1).getReg();
1044 const unsigned InsertReg = I.getOperand(2).getReg();
1045 int64_t Index = I.getOperand(3).getImm();
1046
1047 const LLT DstTy = MRI.getType(DstReg);
1048 const LLT InsertRegTy = MRI.getType(InsertReg);
1049
1050 // Meanwile handle vector type only.
1051 if (!DstTy.isVector())
1052 return false;
1053
1054 if (Index % InsertRegTy.getSizeInBits() != 0)
1055 return false; // Not insert subvector.
1056
1057 if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {
1058 // Replace by subreg copy.
1059 if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
1060 return false;
1061
1062 I.eraseFromParent();
1063 return true;
1064 }
1065
1066 bool HasAVX = STI.hasAVX();
1067 bool HasAVX512 = STI.hasAVX512();
1068 bool HasVLX = STI.hasVLX();
1069
1070 if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {
1071 if (HasVLX)
1072 I.setDesc(TII.get(X86::VINSERTF32x4Z256rr));
1073 else if (HasAVX)
1074 I.setDesc(TII.get(X86::VINSERTF128rr));
1075 else
1076 return false;
1077 } else if (DstTy.getSizeInBits() == 512 && HasAVX512) {
1078 if (InsertRegTy.getSizeInBits() == 128)
1079 I.setDesc(TII.get(X86::VINSERTF32x4Zrr));
1080 else if (InsertRegTy.getSizeInBits() == 256)
1081 I.setDesc(TII.get(X86::VINSERTF64x4Zrr));
1082 else
1083 return false;
1084 } else
1085 return false;
1086
1087 // Convert to X86 VINSERT immediate.
1088 Index = Index / InsertRegTy.getSizeInBits();
1089
1090 I.getOperand(3).setImm(Index);
1091
1092 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
1093}
1094
Igor Bregerb186a692017-07-02 08:15:49 +00001095bool X86InstructionSelector::selectUnmergeValues(MachineInstr &I,
1096 MachineRegisterInfo &MRI,
1097 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +00001098 assert((I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES) &&
1099 "unexpected instruction");
Igor Bregerb186a692017-07-02 08:15:49 +00001100
1101 // Split to extracts.
1102 unsigned NumDefs = I.getNumOperands() - 1;
1103 unsigned SrcReg = I.getOperand(NumDefs).getReg();
1104 unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
1105
1106 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
Igor Bregerb186a692017-07-02 08:15:49 +00001107 MachineInstr &ExtrInst =
1108 *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1109 TII.get(TargetOpcode::G_EXTRACT), I.getOperand(Idx).getReg())
1110 .addReg(SrcReg)
1111 .addImm(Idx * DefSize);
1112
1113 if (!select(ExtrInst))
1114 return false;
1115 }
1116
1117 I.eraseFromParent();
1118 return true;
1119}
1120
Igor Breger0cddd342017-06-29 12:08:28 +00001121bool X86InstructionSelector::selectMergeValues(MachineInstr &I,
1122 MachineRegisterInfo &MRI,
1123 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +00001124 assert((I.getOpcode() == TargetOpcode::G_MERGE_VALUES) &&
1125 "unexpected instruction");
Igor Breger0cddd342017-06-29 12:08:28 +00001126
1127 // Split to inserts.
1128 unsigned DstReg = I.getOperand(0).getReg();
1129 unsigned SrcReg0 = I.getOperand(1).getReg();
1130
1131 const LLT DstTy = MRI.getType(DstReg);
1132 const LLT SrcTy = MRI.getType(SrcReg0);
1133 unsigned SrcSize = SrcTy.getSizeInBits();
1134
1135 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1136
1137 // For the first src use insertSubReg.
1138 unsigned DefReg = MRI.createGenericVirtualRegister(DstTy);
1139 MRI.setRegBank(DefReg, RegBank);
1140 if (!emitInsertSubreg(DefReg, I.getOperand(1).getReg(), I, MRI, MF))
1141 return false;
1142
1143 for (unsigned Idx = 2; Idx < I.getNumOperands(); ++Idx) {
Igor Breger0cddd342017-06-29 12:08:28 +00001144 unsigned Tmp = MRI.createGenericVirtualRegister(DstTy);
1145 MRI.setRegBank(Tmp, RegBank);
1146
1147 MachineInstr &InsertInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1148 TII.get(TargetOpcode::G_INSERT), Tmp)
1149 .addReg(DefReg)
1150 .addReg(I.getOperand(Idx).getReg())
1151 .addImm((Idx - 1) * SrcSize);
1152
1153 DefReg = Tmp;
1154
1155 if (!select(InsertInst))
1156 return false;
1157 }
1158
1159 MachineInstr &CopyInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1160 TII.get(TargetOpcode::COPY), DstReg)
1161 .addReg(DefReg);
1162
1163 if (!select(CopyInst))
1164 return false;
1165
1166 I.eraseFromParent();
1167 return true;
1168}
Igor Breger685889c2017-08-21 10:51:54 +00001169
1170bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
1171 MachineRegisterInfo &MRI,
1172 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +00001173 assert((I.getOpcode() == TargetOpcode::G_BRCOND) && "unexpected instruction");
Igor Breger685889c2017-08-21 10:51:54 +00001174
1175 const unsigned CondReg = I.getOperand(0).getReg();
1176 MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
1177
1178 MachineInstr &TestInst =
1179 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TEST8ri))
1180 .addReg(CondReg)
1181 .addImm(1);
1182 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::JNE_1))
1183 .addMBB(DestMBB);
1184
1185 constrainSelectedInstRegOperands(TestInst, TII, TRI, RBI);
1186
1187 I.eraseFromParent();
1188 return true;
1189}
1190
Igor Breger21200ed2017-09-17 08:08:13 +00001191bool X86InstructionSelector::materializeFP(MachineInstr &I,
1192 MachineRegisterInfo &MRI,
1193 MachineFunction &MF) const {
Igor Breger06335bb2017-09-17 14:02:19 +00001194 assert((I.getOpcode() == TargetOpcode::G_FCONSTANT) &&
1195 "unexpected instruction");
Igor Breger21200ed2017-09-17 08:08:13 +00001196
1197 // Can't handle alternate code models yet.
1198 CodeModel::Model CM = TM.getCodeModel();
1199 if (CM != CodeModel::Small && CM != CodeModel::Large)
1200 return false;
1201
1202 const unsigned DstReg = I.getOperand(0).getReg();
1203 const LLT DstTy = MRI.getType(DstReg);
1204 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1205 unsigned Align = DstTy.getSizeInBits();
1206 const DebugLoc &DbgLoc = I.getDebugLoc();
1207
1208 unsigned Opc = getLoadStoreOp(DstTy, RegBank, TargetOpcode::G_LOAD, Align);
1209
1210 // Create the load from the constant pool.
1211 const ConstantFP *CFP = I.getOperand(1).getFPImm();
1212 unsigned CPI = MF.getConstantPool()->getConstantPoolIndex(CFP, Align);
1213 MachineInstr *LoadInst = nullptr;
1214 unsigned char OpFlag = STI.classifyLocalReference(nullptr);
1215
1216 if (CM == CodeModel::Large && STI.is64Bit()) {
1217 // Under X86-64 non-small code model, GV (and friends) are 64-bits, so
1218 // they cannot be folded into immediate fields.
1219
1220 unsigned AddrReg = MRI.createVirtualRegister(&X86::GR64RegClass);
1221 BuildMI(*I.getParent(), I, DbgLoc, TII.get(X86::MOV64ri), AddrReg)
1222 .addConstantPoolIndex(CPI, 0, OpFlag);
1223
1224 MachineMemOperand *MMO = MF.getMachineMemOperand(
1225 MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
1226 MF.getDataLayout().getPointerSize(), Align);
1227
1228 LoadInst =
1229 addDirectMem(BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg),
1230 AddrReg)
1231 .addMemOperand(MMO);
1232
Igor Breger06335bb2017-09-17 14:02:19 +00001233 } else if (CM == CodeModel::Small || !STI.is64Bit()) {
Igor Breger21200ed2017-09-17 08:08:13 +00001234 // Handle the case when globals fit in our immediate field.
1235 // This is true for X86-32 always and X86-64 when in -mcmodel=small mode.
1236
1237 // x86-32 PIC requires a PIC base register for constant pools.
1238 unsigned PICBase = 0;
1239 if (OpFlag == X86II::MO_PIC_BASE_OFFSET || OpFlag == X86II::MO_GOTOFF) {
1240 // PICBase can be allocated by TII.getGlobalBaseReg(&MF).
1241 // In DAGISEL the code that initialize it generated by the CGBR pass.
1242 return false; // TODO support the mode.
Igor Breger06335bb2017-09-17 14:02:19 +00001243 } else if (STI.is64Bit() && TM.getCodeModel() == CodeModel::Small)
Igor Breger21200ed2017-09-17 08:08:13 +00001244 PICBase = X86::RIP;
1245
1246 LoadInst = addConstantPoolReference(
1247 BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg), CPI, PICBase,
1248 OpFlag);
1249 } else
1250 return false;
1251
1252 constrainSelectedInstRegOperands(*LoadInst, TII, TRI, RBI);
1253 I.eraseFromParent();
1254 return true;
1255}
1256
Igor Breger2661ae42017-09-04 09:06:45 +00001257bool X86InstructionSelector::selectImplicitDefOrPHI(
1258 MachineInstr &I, MachineRegisterInfo &MRI) const {
Igor Breger06335bb2017-09-17 14:02:19 +00001259 assert((I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
1260 I.getOpcode() == TargetOpcode::G_PHI) &&
1261 "unexpected instruction");
Igor Breger47be5fb2017-08-24 07:06:27 +00001262
1263 unsigned DstReg = I.getOperand(0).getReg();
1264
1265 if (!MRI.getRegClassOrNull(DstReg)) {
1266 const LLT DstTy = MRI.getType(DstReg);
1267 const TargetRegisterClass *RC = getRegClass(DstTy, DstReg, MRI);
1268
1269 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1270 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
1271 << " operand\n");
1272 return false;
1273 }
1274 }
1275
Igor Breger2661ae42017-09-04 09:06:45 +00001276 if (I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1277 I.setDesc(TII.get(X86::IMPLICIT_DEF));
1278 else
1279 I.setDesc(TII.get(X86::PHI));
1280
Igor Breger47be5fb2017-08-24 07:06:27 +00001281 return true;
1282}
1283
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001284InstructionSelector *
Daniel Sanderse7b0d662017-04-21 15:59:56 +00001285llvm::createX86InstructionSelector(const X86TargetMachine &TM,
1286 X86Subtarget &Subtarget,
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001287 X86RegisterBankInfo &RBI) {
Daniel Sanderse7b0d662017-04-21 15:59:56 +00001288 return new X86InstructionSelector(TM, Subtarget, RBI);
Daniel Sanders0b5293f2017-04-06 09:49:34 +00001289}