blob: 87228322652744adf4df75bc375ec23c4827ec15 [file] [log] [blame]
Igor Bregerf7359d82017-02-22 12:25:09 +00001//===- X86InstructionSelector.cpp ----------------------------*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10/// This file implements the targeting of the InstructionSelector class for
11/// X86.
12/// \todo This should be generated by TableGen.
13//===----------------------------------------------------------------------===//
14
Igor Bregera8ba5722017-03-23 15:25:57 +000015#include "X86InstrBuilder.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000016#include "X86InstrInfo.h"
17#include "X86RegisterBankInfo.h"
18#include "X86RegisterInfo.h"
19#include "X86Subtarget.h"
20#include "X86TargetMachine.h"
Igor Breger3b97ea32017-04-12 12:54:54 +000021#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
Igor Breger28f290f2017-05-17 12:48:08 +000022#include "llvm/CodeGen/GlobalISel/Utils.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000023#include "llvm/CodeGen/MachineBasicBlock.h"
24#include "llvm/CodeGen/MachineFunction.h"
25#include "llvm/CodeGen/MachineInstr.h"
26#include "llvm/CodeGen/MachineInstrBuilder.h"
Daniel Sanders0b5293f2017-04-06 09:49:34 +000027#include "llvm/CodeGen/MachineOperand.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000028#include "llvm/CodeGen/MachineRegisterInfo.h"
29#include "llvm/IR/Type.h"
30#include "llvm/Support/Debug.h"
31#include "llvm/Support/raw_ostream.h"
32
33#define DEBUG_TYPE "X86-isel"
34
35using namespace llvm;
36
37#ifndef LLVM_BUILD_GLOBAL_ISEL
38#error "You shouldn't build this"
39#endif
40
Daniel Sanders0b5293f2017-04-06 09:49:34 +000041namespace {
42
Daniel Sanderse7b0d662017-04-21 15:59:56 +000043#define GET_GLOBALISEL_PREDICATE_BITSET
44#include "X86GenGlobalISel.inc"
45#undef GET_GLOBALISEL_PREDICATE_BITSET
46
Daniel Sanders0b5293f2017-04-06 09:49:34 +000047class X86InstructionSelector : public InstructionSelector {
48public:
Daniel Sanderse7b0d662017-04-21 15:59:56 +000049 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
Daniel Sanders0b5293f2017-04-06 09:49:34 +000050 const X86RegisterBankInfo &RBI);
51
52 bool select(MachineInstr &I) const override;
53
54private:
55 /// tblgen-erated 'select' implementation, used as the initial selector for
56 /// the patterns that don't require complex C++.
57 bool selectImpl(MachineInstr &I) const;
58
Igor Breger2452ef02017-05-01 07:06:08 +000059 // TODO: remove after suported by Tablegen-erated instruction selection.
Daniel Sanders0b5293f2017-04-06 09:49:34 +000060 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
61 uint64_t Alignment) const;
62
Daniel Sanders0b5293f2017-04-06 09:49:34 +000063 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
64 MachineFunction &MF) const;
Igor Breger810c6252017-05-08 09:40:43 +000065 bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
66 MachineFunction &MF) const;
Igor Breger3b97ea32017-04-12 12:54:54 +000067 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
68 MachineFunction &MF) const;
Igor Breger4fdf1e42017-04-19 11:34:59 +000069 bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
70 MachineFunction &MF) const;
Igor Bregerfda31e62017-05-10 06:52:58 +000071 bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
72 MachineFunction &MF) const;
Igor Bregerc7b59772017-05-11 07:17:40 +000073 bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
74 MachineFunction &MF) const;
Igor Breger28f290f2017-05-17 12:48:08 +000075 bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
76 MachineFunction &MF) const;
Igor Breger1dcd5e82017-06-20 09:15:10 +000077 bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
Igor Breger1c29be72017-06-22 09:43:35 +000078 bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,
79 MachineFunction &MF) const;
80
81 // emit insert subreg instruction and insert it before MachineInstr &I
82 bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
83 MachineRegisterInfo &MRI, MachineFunction &MF) const;
Igor Breger1dcd5e82017-06-20 09:15:10 +000084
85 const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
86 const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,
87 MachineRegisterInfo &MRI) const;
Igor Breger28f290f2017-05-17 12:48:08 +000088
Daniel Sanderse7b0d662017-04-21 15:59:56 +000089 const X86TargetMachine &TM;
Daniel Sanders0b5293f2017-04-06 09:49:34 +000090 const X86Subtarget &STI;
91 const X86InstrInfo &TII;
92 const X86RegisterInfo &TRI;
93 const X86RegisterBankInfo &RBI;
Daniel Sanderse7b0d662017-04-21 15:59:56 +000094
Daniel Sanderse9fdba32017-04-29 17:30:09 +000095#define GET_GLOBALISEL_PREDICATES_DECL
96#include "X86GenGlobalISel.inc"
97#undef GET_GLOBALISEL_PREDICATES_DECL
Daniel Sanders0b5293f2017-04-06 09:49:34 +000098
99#define GET_GLOBALISEL_TEMPORARIES_DECL
100#include "X86GenGlobalISel.inc"
101#undef GET_GLOBALISEL_TEMPORARIES_DECL
102};
103
104} // end anonymous namespace
105
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000106#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000107#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000108#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +0000109
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000110X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
111 const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +0000112 const X86RegisterBankInfo &RBI)
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000113 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanderse9fdba32017-04-29 17:30:09 +0000114 TRI(*STI.getRegisterInfo()), RBI(RBI),
115#define GET_GLOBALISEL_PREDICATES_INIT
116#include "X86GenGlobalISel.inc"
117#undef GET_GLOBALISEL_PREDICATES_INIT
Daniel Sanders8a4bae92017-03-14 21:32:08 +0000118#define GET_GLOBALISEL_TEMPORARIES_INIT
119#include "X86GenGlobalISel.inc"
120#undef GET_GLOBALISEL_TEMPORARIES_INIT
121{
122}
Igor Bregerf7359d82017-02-22 12:25:09 +0000123
124// FIXME: This should be target-independent, inferred from the types declared
125// for each class in the bank.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000126const TargetRegisterClass *
127X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000128 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger4fdf1e42017-04-19 11:34:59 +0000129 if (Ty.getSizeInBits() <= 8)
130 return &X86::GR8RegClass;
131 if (Ty.getSizeInBits() == 16)
132 return &X86::GR16RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000133 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000134 return &X86::GR32RegClass;
135 if (Ty.getSizeInBits() == 64)
136 return &X86::GR64RegClass;
137 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000138 if (RB.getID() == X86::VECRRegBankID) {
139 if (Ty.getSizeInBits() == 32)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000140 return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000141 if (Ty.getSizeInBits() == 64)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000142 return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000143 if (Ty.getSizeInBits() == 128)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000144 return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000145 if (Ty.getSizeInBits() == 256)
Igor Breger1dcd5e82017-06-20 09:15:10 +0000146 return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
Igor Breger321cf3c2017-03-03 08:06:46 +0000147 if (Ty.getSizeInBits() == 512)
148 return &X86::VR512RegClass;
149 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000150
151 llvm_unreachable("Unknown RegBank!");
152}
153
Igor Breger1dcd5e82017-06-20 09:15:10 +0000154const TargetRegisterClass *
155X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,
156 MachineRegisterInfo &MRI) const {
157 const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
158 return getRegClass(Ty, RegBank);
159}
160
Igor Bregerf7359d82017-02-22 12:25:09 +0000161// Set X86 Opcode and constrain DestReg.
Igor Breger1dcd5e82017-06-20 09:15:10 +0000162bool X86InstructionSelector::selectCopy(MachineInstr &I,
163 MachineRegisterInfo &MRI) const {
Igor Bregerf7359d82017-02-22 12:25:09 +0000164
165 unsigned DstReg = I.getOperand(0).getReg();
166 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
167 assert(I.isCopy() && "Generic operators do not allow physical registers");
168 return true;
169 }
170
171 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
172 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
173 unsigned SrcReg = I.getOperand(1).getReg();
174 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
Igor Breger360d0f22017-04-27 08:02:03 +0000175
Igor Bregerf7359d82017-02-22 12:25:09 +0000176 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
177 "No phys reg on generic operators");
178 assert((DstSize == SrcSize ||
179 // Copies are a mean to setup initial types, the number of
180 // bits may not exactly match.
181 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
182 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
183 "Copy with different width?!");
184
185 const TargetRegisterClass *RC = nullptr;
186
187 switch (RegBank.getID()) {
188 case X86::GPRRegBankID:
189 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
Igor Breger1dcd5e82017-06-20 09:15:10 +0000190 RC = getRegClass(MRI.getType(DstReg), RegBank);
Igor Breger360d0f22017-04-27 08:02:03 +0000191
192 // Change the physical register
193 if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
194 if (RC == &X86::GR32RegClass)
195 I.getOperand(1).setSubReg(X86::sub_32bit);
196 else if (RC == &X86::GR16RegClass)
197 I.getOperand(1).setSubReg(X86::sub_16bit);
198 else if (RC == &X86::GR8RegClass)
199 I.getOperand(1).setSubReg(X86::sub_8bit);
200
201 I.getOperand(1).substPhysReg(SrcReg, TRI);
202 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000203 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000204 case X86::VECRRegBankID:
Igor Breger1dcd5e82017-06-20 09:15:10 +0000205 RC = getRegClass(MRI.getType(DstReg), RegBank);
Igor Breger321cf3c2017-03-03 08:06:46 +0000206 break;
Igor Bregerf7359d82017-02-22 12:25:09 +0000207 default:
208 llvm_unreachable("Unknown RegBank!");
209 }
210
211 // No need to constrain SrcReg. It will get constrained when
212 // we hit another of its use or its defs.
213 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000214 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000215 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
216 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000217 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
218 << " operand\n");
219 return false;
220 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000221 }
222 I.setDesc(TII.get(X86::COPY));
223 return true;
224}
225
226bool X86InstructionSelector::select(MachineInstr &I) const {
227 assert(I.getParent() && "Instruction should be in a basic block!");
228 assert(I.getParent()->getParent() && "Instruction should be in a function!");
229
230 MachineBasicBlock &MBB = *I.getParent();
231 MachineFunction &MF = *MBB.getParent();
232 MachineRegisterInfo &MRI = MF.getRegInfo();
233
234 unsigned Opcode = I.getOpcode();
235 if (!isPreISelGenericOpcode(Opcode)) {
236 // Certain non-generic instructions also need some special handling.
237
238 if (I.isCopy())
Igor Breger1dcd5e82017-06-20 09:15:10 +0000239 return selectCopy(I, MRI);
Igor Bregerf7359d82017-02-22 12:25:09 +0000240
241 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
242 return true;
243 }
244
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000245 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
246 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000247
Igor Breger2452ef02017-05-01 07:06:08 +0000248 if (selectImpl(I))
Igor Bregerfda31e62017-05-10 06:52:58 +0000249 return true;
Igor Breger2452ef02017-05-01 07:06:08 +0000250
251 DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
252
253 // TODO: This should be implemented by tblgen.
Igor Bregera8ba5722017-03-23 15:25:57 +0000254 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000255 return true;
Igor Breger810c6252017-05-08 09:40:43 +0000256 if (selectFrameIndexOrGep(I, MRI, MF))
Igor Breger531a2032017-03-26 08:11:12 +0000257 return true;
Igor Breger3b97ea32017-04-12 12:54:54 +0000258 if (selectConstant(I, MRI, MF))
259 return true;
Igor Breger4fdf1e42017-04-19 11:34:59 +0000260 if (selectTrunc(I, MRI, MF))
261 return true;
Igor Bregerfda31e62017-05-10 06:52:58 +0000262 if (selectZext(I, MRI, MF))
263 return true;
Igor Bregerc7b59772017-05-11 07:17:40 +0000264 if (selectCmp(I, MRI, MF))
265 return true;
Igor Breger28f290f2017-05-17 12:48:08 +0000266 if (selectUadde(I, MRI, MF))
267 return true;
Igor Breger1c29be72017-06-22 09:43:35 +0000268 if (selectInsert(I, MRI, MF))
269 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000270
Igor Breger2452ef02017-05-01 07:06:08 +0000271 return false;
Igor Bregerf7359d82017-02-22 12:25:09 +0000272}
Igor Breger321cf3c2017-03-03 08:06:46 +0000273
Igor Bregera8ba5722017-03-23 15:25:57 +0000274unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
275 unsigned Opc,
276 uint64_t Alignment) const {
277 bool Isload = (Opc == TargetOpcode::G_LOAD);
278 bool HasAVX = STI.hasAVX();
279 bool HasAVX512 = STI.hasAVX512();
280 bool HasVLX = STI.hasVLX();
281
282 if (Ty == LLT::scalar(8)) {
283 if (X86::GPRRegBankID == RB.getID())
284 return Isload ? X86::MOV8rm : X86::MOV8mr;
285 } else if (Ty == LLT::scalar(16)) {
286 if (X86::GPRRegBankID == RB.getID())
287 return Isload ? X86::MOV16rm : X86::MOV16mr;
Igor Bregera9edb882017-05-01 06:08:32 +0000288 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000289 if (X86::GPRRegBankID == RB.getID())
290 return Isload ? X86::MOV32rm : X86::MOV32mr;
291 if (X86::VECRRegBankID == RB.getID())
292 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
293 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
294 : (HasAVX512 ? X86::VMOVSSZmr
295 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
Igor Bregera9edb882017-05-01 06:08:32 +0000296 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
Igor Bregera8ba5722017-03-23 15:25:57 +0000297 if (X86::GPRRegBankID == RB.getID())
298 return Isload ? X86::MOV64rm : X86::MOV64mr;
299 if (X86::VECRRegBankID == RB.getID())
300 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
301 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
302 : (HasAVX512 ? X86::VMOVSDZmr
303 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
304 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
305 if (Alignment >= 16)
306 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
307 : HasAVX512
308 ? X86::VMOVAPSZ128rm_NOVLX
309 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
310 : (HasVLX ? X86::VMOVAPSZ128mr
311 : HasAVX512
312 ? X86::VMOVAPSZ128mr_NOVLX
313 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
314 else
315 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
316 : HasAVX512
317 ? X86::VMOVUPSZ128rm_NOVLX
318 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
319 : (HasVLX ? X86::VMOVUPSZ128mr
320 : HasAVX512
321 ? X86::VMOVUPSZ128mr_NOVLX
322 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
Igor Breger617be6e2017-05-23 08:23:51 +0000323 } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
324 if (Alignment >= 32)
325 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
326 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
327 : X86::VMOVAPSYrm)
328 : (HasVLX ? X86::VMOVAPSZ256mr
329 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
330 : X86::VMOVAPSYmr);
331 else
332 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
333 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
334 : X86::VMOVUPSYrm)
335 : (HasVLX ? X86::VMOVUPSZ256mr
336 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
337 : X86::VMOVUPSYmr);
338 } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
339 if (Alignment >= 64)
340 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
341 else
342 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
Igor Bregera8ba5722017-03-23 15:25:57 +0000343 }
344 return Opc;
345}
346
Igor Bregerbd2deda2017-06-19 13:12:57 +0000347// Fill in an address from the given instruction.
348void X86SelectAddress(const MachineInstr &I, const MachineRegisterInfo &MRI,
349 X86AddressMode &AM) {
350
351 assert(I.getOperand(0).isReg() && "unsupported opperand.");
352 assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
353 "unsupported type.");
354
355 if (I.getOpcode() == TargetOpcode::G_GEP) {
356 if (auto COff = getConstantVRegVal(I.getOperand(2).getReg(), MRI)) {
357 int64_t Imm = *COff;
358 if (isInt<32>(Imm)) { // Check for displacement overflow.
359 AM.Disp = static_cast<int32_t>(Imm);
360 AM.Base.Reg = I.getOperand(1).getReg();
361 return;
362 }
363 }
364 } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
365 AM.Base.FrameIndex = I.getOperand(1).getIndex();
366 AM.BaseType = X86AddressMode::FrameIndexBase;
367 return;
368 }
369
370 // Default behavior.
371 AM.Base.Reg = I.getOperand(0).getReg();
372 return;
373}
374
Igor Bregera8ba5722017-03-23 15:25:57 +0000375bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
376 MachineRegisterInfo &MRI,
377 MachineFunction &MF) const {
378
379 unsigned Opc = I.getOpcode();
380
381 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
382 return false;
383
384 const unsigned DefReg = I.getOperand(0).getReg();
385 LLT Ty = MRI.getType(DefReg);
386 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
387
388 auto &MemOp = **I.memoperands_begin();
Igor Bregerbd2deda2017-06-19 13:12:57 +0000389 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
390 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
391 return false;
392 }
393
Igor Bregera8ba5722017-03-23 15:25:57 +0000394 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
395 if (NewOpc == Opc)
396 return false;
397
Igor Bregerbd2deda2017-06-19 13:12:57 +0000398 X86AddressMode AM;
399 X86SelectAddress(*MRI.getVRegDef(I.getOperand(1).getReg()), MRI, AM);
400
Igor Bregera8ba5722017-03-23 15:25:57 +0000401 I.setDesc(TII.get(NewOpc));
402 MachineInstrBuilder MIB(MF, I);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000403 if (Opc == TargetOpcode::G_LOAD) {
404 I.RemoveOperand(1);
405 addFullAddress(MIB, AM);
406 } else {
Igor Bregera8ba5722017-03-23 15:25:57 +0000407 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
Igor Bregerbd2deda2017-06-19 13:12:57 +0000408 I.RemoveOperand(1);
Igor Bregera8ba5722017-03-23 15:25:57 +0000409 I.RemoveOperand(0);
Igor Bregerbd2deda2017-06-19 13:12:57 +0000410 addFullAddress(MIB, AM).addUse(DefReg);
Igor Bregera8ba5722017-03-23 15:25:57 +0000411 }
412 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
413}
414
Igor Breger810c6252017-05-08 09:40:43 +0000415bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
416 MachineRegisterInfo &MRI,
417 MachineFunction &MF) const {
418 unsigned Opc = I.getOpcode();
419
420 if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
Igor Breger531a2032017-03-26 08:11:12 +0000421 return false;
422
423 const unsigned DefReg = I.getOperand(0).getReg();
424 LLT Ty = MRI.getType(DefReg);
425
Igor Breger810c6252017-05-08 09:40:43 +0000426 // Use LEA to calculate frame index and GEP
Igor Breger531a2032017-03-26 08:11:12 +0000427 unsigned NewOpc;
428 if (Ty == LLT::pointer(0, 64))
429 NewOpc = X86::LEA64r;
430 else if (Ty == LLT::pointer(0, 32))
431 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
432 else
Igor Breger810c6252017-05-08 09:40:43 +0000433 llvm_unreachable("Can't select G_FRAME_INDEX/G_GEP, unsupported type.");
Igor Breger531a2032017-03-26 08:11:12 +0000434
435 I.setDesc(TII.get(NewOpc));
436 MachineInstrBuilder MIB(MF, I);
Igor Breger810c6252017-05-08 09:40:43 +0000437
438 if (Opc == TargetOpcode::G_FRAME_INDEX) {
439 addOffset(MIB, 0);
440 } else {
441 MachineOperand &InxOp = I.getOperand(2);
442 I.addOperand(InxOp); // set IndexReg
443 InxOp.ChangeToImmediate(1); // set Scale
444 MIB.addImm(0).addReg(0);
445 }
Igor Breger531a2032017-03-26 08:11:12 +0000446
447 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
448}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000449
Igor Breger3b97ea32017-04-12 12:54:54 +0000450bool X86InstructionSelector::selectConstant(MachineInstr &I,
451 MachineRegisterInfo &MRI,
452 MachineFunction &MF) const {
453 if (I.getOpcode() != TargetOpcode::G_CONSTANT)
454 return false;
455
456 const unsigned DefReg = I.getOperand(0).getReg();
457 LLT Ty = MRI.getType(DefReg);
458
459 assert(Ty.isScalar() && "invalid element type.");
460
461 uint64_t Val = 0;
462 if (I.getOperand(1).isCImm()) {
463 Val = I.getOperand(1).getCImm()->getZExtValue();
464 I.getOperand(1).ChangeToImmediate(Val);
465 } else if (I.getOperand(1).isImm()) {
466 Val = I.getOperand(1).getImm();
467 } else
468 llvm_unreachable("Unsupported operand type.");
469
470 unsigned NewOpc;
471 switch (Ty.getSizeInBits()) {
472 case 8:
473 NewOpc = X86::MOV8ri;
474 break;
475 case 16:
476 NewOpc = X86::MOV16ri;
477 break;
478 case 32:
479 NewOpc = X86::MOV32ri;
480 break;
481 case 64: {
482 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
483 if (isInt<32>(Val))
484 NewOpc = X86::MOV64ri32;
485 else
486 NewOpc = X86::MOV64ri;
487 break;
488 }
489 default:
490 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
491 }
492
493 I.setDesc(TII.get(NewOpc));
494 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
495}
496
Igor Breger4fdf1e42017-04-19 11:34:59 +0000497bool X86InstructionSelector::selectTrunc(MachineInstr &I,
498 MachineRegisterInfo &MRI,
499 MachineFunction &MF) const {
500 if (I.getOpcode() != TargetOpcode::G_TRUNC)
501 return false;
502
503 const unsigned DstReg = I.getOperand(0).getReg();
504 const unsigned SrcReg = I.getOperand(1).getReg();
505
506 const LLT DstTy = MRI.getType(DstReg);
507 const LLT SrcTy = MRI.getType(SrcReg);
508
509 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
510 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
511
512 if (DstRB.getID() != SrcRB.getID()) {
513 DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
514 return false;
515 }
516
517 if (DstRB.getID() != X86::GPRRegBankID)
518 return false;
519
Igor Breger1dcd5e82017-06-20 09:15:10 +0000520 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000521 if (!DstRC)
522 return false;
523
Igor Breger1dcd5e82017-06-20 09:15:10 +0000524 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000525 if (!SrcRC)
526 return false;
527
Igor Breger014fc562017-05-21 11:13:56 +0000528 unsigned SubIdx;
529 if (DstRC == SrcRC) {
530 // Nothing to be done
531 SubIdx = X86::NoSubRegister;
532 } else if (DstRC == &X86::GR32RegClass) {
533 SubIdx = X86::sub_32bit;
534 } else if (DstRC == &X86::GR16RegClass) {
535 SubIdx = X86::sub_16bit;
536 } else if (DstRC == &X86::GR8RegClass) {
537 SubIdx = X86::sub_8bit;
538 } else {
539 return false;
540 }
541
542 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
543
Igor Breger4fdf1e42017-04-19 11:34:59 +0000544 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
545 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
546 DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
547 return false;
548 }
549
Igor Breger014fc562017-05-21 11:13:56 +0000550 I.getOperand(1).setSubReg(SubIdx);
Igor Breger4fdf1e42017-04-19 11:34:59 +0000551
552 I.setDesc(TII.get(X86::COPY));
553 return true;
554}
555
Igor Bregerfda31e62017-05-10 06:52:58 +0000556bool X86InstructionSelector::selectZext(MachineInstr &I,
557 MachineRegisterInfo &MRI,
558 MachineFunction &MF) const {
559 if (I.getOpcode() != TargetOpcode::G_ZEXT)
560 return false;
561
562 const unsigned DstReg = I.getOperand(0).getReg();
563 const unsigned SrcReg = I.getOperand(1).getReg();
564
565 const LLT DstTy = MRI.getType(DstReg);
566 const LLT SrcTy = MRI.getType(SrcReg);
567
568 if (SrcTy == LLT::scalar(1)) {
569
570 unsigned AndOpc;
571 if (DstTy == LLT::scalar(32))
572 AndOpc = X86::AND32ri8;
573 else if (DstTy == LLT::scalar(64))
574 AndOpc = X86::AND64ri8;
575 else
576 return false;
577
Igor Breger0dee0f42017-06-20 09:40:57 +0000578 unsigned DefReg =
579 MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
Igor Bregerfda31e62017-05-10 06:52:58 +0000580
581 BuildMI(*I.getParent(), I, I.getDebugLoc(),
582 TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
583 .addImm(0)
584 .addReg(SrcReg)
585 .addImm(X86::sub_8bit);
586
587 MachineInstr &AndInst =
588 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
589 .addReg(DefReg)
590 .addImm(1);
591
592 constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
593
594 I.eraseFromParent();
595 return true;
596 }
597
598 return false;
599}
600
Igor Bregerc7b59772017-05-11 07:17:40 +0000601bool X86InstructionSelector::selectCmp(MachineInstr &I,
602 MachineRegisterInfo &MRI,
603 MachineFunction &MF) const {
604 if (I.getOpcode() != TargetOpcode::G_ICMP)
605 return false;
606
607 X86::CondCode CC;
608 bool SwapArgs;
609 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
610 (CmpInst::Predicate)I.getOperand(1).getPredicate());
611 unsigned OpSet = X86::getSETFromCond(CC);
612
613 unsigned LHS = I.getOperand(2).getReg();
614 unsigned RHS = I.getOperand(3).getReg();
615
616 if (SwapArgs)
617 std::swap(LHS, RHS);
618
619 unsigned OpCmp;
620 LLT Ty = MRI.getType(LHS);
621
622 switch (Ty.getSizeInBits()) {
623 default:
624 return false;
625 case 8:
626 OpCmp = X86::CMP8rr;
627 break;
628 case 16:
629 OpCmp = X86::CMP16rr;
630 break;
631 case 32:
632 OpCmp = X86::CMP32rr;
633 break;
634 case 64:
635 OpCmp = X86::CMP64rr;
636 break;
637 }
638
639 MachineInstr &CmpInst =
640 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
641 .addReg(LHS)
642 .addReg(RHS);
643
644 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
645 TII.get(OpSet), I.getOperand(0).getReg());
646
647 constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
648 constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
649
650 I.eraseFromParent();
651 return true;
652}
653
Igor Breger28f290f2017-05-17 12:48:08 +0000654bool X86InstructionSelector::selectUadde(MachineInstr &I,
655 MachineRegisterInfo &MRI,
656 MachineFunction &MF) const {
657 if (I.getOpcode() != TargetOpcode::G_UADDE)
658 return false;
659
660 const unsigned DstReg = I.getOperand(0).getReg();
661 const unsigned CarryOutReg = I.getOperand(1).getReg();
662 const unsigned Op0Reg = I.getOperand(2).getReg();
663 const unsigned Op1Reg = I.getOperand(3).getReg();
664 unsigned CarryInReg = I.getOperand(4).getReg();
665
666 const LLT DstTy = MRI.getType(DstReg);
667
668 if (DstTy != LLT::scalar(32))
669 return false;
670
671 // find CarryIn def instruction.
672 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
673 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
674 CarryInReg = Def->getOperand(1).getReg();
675 Def = MRI.getVRegDef(CarryInReg);
676 }
677
678 unsigned Opcode;
679 if (Def->getOpcode() == TargetOpcode::G_UADDE) {
680 // carry set by prev ADD.
681
682 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
683 .addReg(CarryInReg);
684
685 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
686 return false;
687
688 Opcode = X86::ADC32rr;
689 } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
690 // carry is constant, support only 0.
691 if (*val != 0)
692 return false;
693
694 Opcode = X86::ADD32rr;
695 } else
696 return false;
697
698 MachineInstr &AddInst =
699 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
700 .addReg(Op0Reg)
701 .addReg(Op1Reg);
702
703 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
704 .addReg(X86::EFLAGS);
705
706 if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
707 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
708 return false;
709
710 I.eraseFromParent();
711 return true;
712}
713
Igor Breger1c29be72017-06-22 09:43:35 +0000714bool X86InstructionSelector::emitInsertSubreg(unsigned DstReg, unsigned SrcReg,
715 MachineInstr &I,
716 MachineRegisterInfo &MRI,
717 MachineFunction &MF) const {
718
719 const LLT DstTy = MRI.getType(DstReg);
720 const LLT SrcTy = MRI.getType(SrcReg);
721 unsigned SubIdx = X86::NoSubRegister;
722
723 // TODO: support scalar types
724 if (!DstTy.isVector() || !SrcTy.isVector())
725 return false;
726
727 assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&
728 "Incorrect Src/Dst register size");
729
730 if (SrcTy.getSizeInBits() == 128)
731 SubIdx = X86::sub_xmm;
732 else if (SrcTy.getSizeInBits() == 256)
733 SubIdx = X86::sub_ymm;
734 else
735 return false;
736
737 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
738 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
739
740 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
741 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
742 DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");
743 return false;
744 }
745
746 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))
747 .addReg(DstReg, RegState::DefineNoRead, SubIdx)
748 .addReg(SrcReg);
749
750 return true;
751}
752
753bool X86InstructionSelector::selectInsert(MachineInstr &I,
754 MachineRegisterInfo &MRI,
755 MachineFunction &MF) const {
756
757 if (I.getOpcode() != TargetOpcode::G_INSERT)
758 return false;
759
760 const unsigned DstReg = I.getOperand(0).getReg();
761 const unsigned SrcReg = I.getOperand(1).getReg();
762 const unsigned InsertReg = I.getOperand(2).getReg();
763 int64_t Index = I.getOperand(3).getImm();
764
765 const LLT DstTy = MRI.getType(DstReg);
766 const LLT InsertRegTy = MRI.getType(InsertReg);
767
768 // Meanwile handle vector type only.
769 if (!DstTy.isVector())
770 return false;
771
772 if (Index % InsertRegTy.getSizeInBits() != 0)
773 return false; // Not insert subvector.
774
775 if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {
776 // Replace by subreg copy.
777 if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
778 return false;
779
780 I.eraseFromParent();
781 return true;
782 }
783
784 bool HasAVX = STI.hasAVX();
785 bool HasAVX512 = STI.hasAVX512();
786 bool HasVLX = STI.hasVLX();
787
788 if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {
789 if (HasVLX)
790 I.setDesc(TII.get(X86::VINSERTF32x4Z256rr));
791 else if (HasAVX)
792 I.setDesc(TII.get(X86::VINSERTF128rr));
793 else
794 return false;
795 } else if (DstTy.getSizeInBits() == 512 && HasAVX512) {
796 if (InsertRegTy.getSizeInBits() == 128)
797 I.setDesc(TII.get(X86::VINSERTF32x4Zrr));
798 else if (InsertRegTy.getSizeInBits() == 256)
799 I.setDesc(TII.get(X86::VINSERTF64x4Zrr));
800 else
801 return false;
802 } else
803 return false;
804
805 // Convert to X86 VINSERT immediate.
806 Index = Index / InsertRegTy.getSizeInBits();
807
808 I.getOperand(3).setImm(Index);
809
810 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
811}
812
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000813InstructionSelector *
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000814llvm::createX86InstructionSelector(const X86TargetMachine &TM,
815 X86Subtarget &Subtarget,
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000816 X86RegisterBankInfo &RBI) {
Daniel Sanderse7b0d662017-04-21 15:59:56 +0000817 return new X86InstructionSelector(TM, Subtarget, RBI);
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000818}