blob: d5a1a133f70a7f7f3c08506eb74724151d6aa31c [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"
21#include "llvm/CodeGen/MachineBasicBlock.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineInstr.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
Daniel Sanders0b5293f2017-04-06 09:49:34 +000025#include "llvm/CodeGen/MachineOperand.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000026#include "llvm/CodeGen/MachineRegisterInfo.h"
Daniel Sanders0b5293f2017-04-06 09:49:34 +000027#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
Igor Bregerf7359d82017-02-22 12:25:09 +000028#include "llvm/IR/Type.h"
29#include "llvm/Support/Debug.h"
30#include "llvm/Support/raw_ostream.h"
31
32#define DEBUG_TYPE "X86-isel"
33
34using namespace llvm;
35
36#ifndef LLVM_BUILD_GLOBAL_ISEL
37#error "You shouldn't build this"
38#endif
39
Daniel Sanders0b5293f2017-04-06 09:49:34 +000040namespace {
41
42class X86InstructionSelector : public InstructionSelector {
43public:
44 X86InstructionSelector(const X86Subtarget &STI,
45 const X86RegisterBankInfo &RBI);
46
47 bool select(MachineInstr &I) const override;
48
49private:
50 /// tblgen-erated 'select' implementation, used as the initial selector for
51 /// the patterns that don't require complex C++.
52 bool selectImpl(MachineInstr &I) const;
53
54 // TODO: remove after selectImpl support pattern with a predicate.
55 unsigned getFAddOp(LLT &Ty, const RegisterBank &RB) const;
56 unsigned getFSubOp(LLT &Ty, const RegisterBank &RB) const;
57 unsigned getAddOp(LLT &Ty, const RegisterBank &RB) const;
58 unsigned getSubOp(LLT &Ty, const RegisterBank &RB) const;
59 unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
60 uint64_t Alignment) const;
61
62 bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI,
63 MachineFunction &MF) const;
64 bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
65 MachineFunction &MF) const;
66 bool selectFrameIndex(MachineInstr &I, MachineRegisterInfo &MRI,
67 MachineFunction &MF) const;
68
69 const X86Subtarget &STI;
70 const X86InstrInfo &TII;
71 const X86RegisterInfo &TRI;
72 const X86RegisterBankInfo &RBI;
73
74#define GET_GLOBALISEL_TEMPORARIES_DECL
75#include "X86GenGlobalISel.inc"
76#undef GET_GLOBALISEL_TEMPORARIES_DECL
77};
78
79} // end anonymous namespace
80
Daniel Sanders8a4bae92017-03-14 21:32:08 +000081#define GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000082#include "X86GenGlobalISel.inc"
Daniel Sanders8a4bae92017-03-14 21:32:08 +000083#undef GET_GLOBALISEL_IMPL
Igor Bregerf7359d82017-02-22 12:25:09 +000084
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +000085X86InstructionSelector::X86InstructionSelector(const X86Subtarget &STI,
Igor Bregerf7359d82017-02-22 12:25:09 +000086 const X86RegisterBankInfo &RBI)
Igor Breger321cf3c2017-03-03 08:06:46 +000087 : InstructionSelector(), STI(STI), TII(*STI.getInstrInfo()),
Daniel Sanders8a4bae92017-03-14 21:32:08 +000088 TRI(*STI.getRegisterInfo()), RBI(RBI)
89#define GET_GLOBALISEL_TEMPORARIES_INIT
90#include "X86GenGlobalISel.inc"
91#undef GET_GLOBALISEL_TEMPORARIES_INIT
92{
93}
Igor Bregerf7359d82017-02-22 12:25:09 +000094
95// FIXME: This should be target-independent, inferred from the types declared
96// for each class in the bank.
97static const TargetRegisterClass *
98getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
99 if (RB.getID() == X86::GPRRegBankID) {
Igor Breger321cf3c2017-03-03 08:06:46 +0000100 if (Ty.getSizeInBits() == 32)
Igor Bregerf7359d82017-02-22 12:25:09 +0000101 return &X86::GR32RegClass;
102 if (Ty.getSizeInBits() == 64)
103 return &X86::GR64RegClass;
104 }
Igor Breger321cf3c2017-03-03 08:06:46 +0000105 if (RB.getID() == X86::VECRRegBankID) {
106 if (Ty.getSizeInBits() == 32)
107 return &X86::FR32XRegClass;
108 if (Ty.getSizeInBits() == 64)
109 return &X86::FR64XRegClass;
110 if (Ty.getSizeInBits() == 128)
111 return &X86::VR128XRegClass;
112 if (Ty.getSizeInBits() == 256)
113 return &X86::VR256XRegClass;
114 if (Ty.getSizeInBits() == 512)
115 return &X86::VR512RegClass;
116 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000117
118 llvm_unreachable("Unknown RegBank!");
119}
120
121// Set X86 Opcode and constrain DestReg.
122static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
123 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
124 const RegisterBankInfo &RBI) {
125
126 unsigned DstReg = I.getOperand(0).getReg();
127 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
128 assert(I.isCopy() && "Generic operators do not allow physical registers");
129 return true;
130 }
131
132 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
133 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000134 (void)DstSize;
Igor Bregerf7359d82017-02-22 12:25:09 +0000135 unsigned SrcReg = I.getOperand(1).getReg();
136 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
137 (void)SrcSize;
138 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
139 "No phys reg on generic operators");
140 assert((DstSize == SrcSize ||
141 // Copies are a mean to setup initial types, the number of
142 // bits may not exactly match.
143 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
144 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
145 "Copy with different width?!");
146
147 const TargetRegisterClass *RC = nullptr;
148
149 switch (RegBank.getID()) {
150 case X86::GPRRegBankID:
151 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
152 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
153 break;
Igor Breger321cf3c2017-03-03 08:06:46 +0000154 case X86::VECRRegBankID:
155 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
156 break;
Igor Bregerf7359d82017-02-22 12:25:09 +0000157 default:
158 llvm_unreachable("Unknown RegBank!");
159 }
160
161 // No need to constrain SrcReg. It will get constrained when
162 // we hit another of its use or its defs.
163 // Copies do not have constraints.
Igor Breger8a924be2017-03-23 12:13:29 +0000164 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000165 if (!OldRC || !RC->hasSubClassEq(OldRC)) {
166 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Igor Breger8a924be2017-03-23 12:13:29 +0000167 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
168 << " operand\n");
169 return false;
170 }
Igor Bregerf7359d82017-02-22 12:25:09 +0000171 }
172 I.setDesc(TII.get(X86::COPY));
173 return true;
174}
175
176bool X86InstructionSelector::select(MachineInstr &I) const {
177 assert(I.getParent() && "Instruction should be in a basic block!");
178 assert(I.getParent()->getParent() && "Instruction should be in a function!");
179
180 MachineBasicBlock &MBB = *I.getParent();
181 MachineFunction &MF = *MBB.getParent();
182 MachineRegisterInfo &MRI = MF.getRegInfo();
183
184 unsigned Opcode = I.getOpcode();
185 if (!isPreISelGenericOpcode(Opcode)) {
186 // Certain non-generic instructions also need some special handling.
187
188 if (I.isCopy())
189 return selectCopy(I, TII, MRI, TRI, RBI);
190
191 // TODO: handle more cases - LOAD_STACK_GUARD, PHI
192 return true;
193 }
194
Benjamin Kramer5a7e0f82017-02-22 12:59:47 +0000195 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
196 "Generic instruction has unexpected implicit operands\n");
Igor Bregerf7359d82017-02-22 12:25:09 +0000197
Igor Breger8a924be2017-03-23 12:13:29 +0000198 // TODO: This should be implemented by tblgen, pattern with predicate not
199 // supported yet.
Igor Bregera8ba5722017-03-23 15:25:57 +0000200 if (selectBinaryOp(I, MRI, MF))
201 return true;
202 if (selectLoadStoreOp(I, MRI, MF))
Igor Breger321cf3c2017-03-03 08:06:46 +0000203 return true;
Igor Breger531a2032017-03-26 08:11:12 +0000204 if (selectFrameIndex(I, MRI, MF))
205 return true;
Igor Breger321cf3c2017-03-03 08:06:46 +0000206
Igor Bregerf7359d82017-02-22 12:25:09 +0000207 return selectImpl(I);
208}
Igor Breger321cf3c2017-03-03 08:06:46 +0000209
210unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
211 const RegisterBank &RB) const {
212
213 if (X86::VECRRegBankID != RB.getID())
214 return TargetOpcode::G_FADD;
215
216 if (Ty == LLT::scalar(32)) {
217 if (STI.hasAVX512()) {
218 return X86::VADDSSZrr;
219 } else if (STI.hasAVX()) {
220 return X86::VADDSSrr;
221 } else if (STI.hasSSE1()) {
222 return X86::ADDSSrr;
223 }
224 } else if (Ty == LLT::scalar(64)) {
225 if (STI.hasAVX512()) {
226 return X86::VADDSDZrr;
227 } else if (STI.hasAVX()) {
228 return X86::VADDSDrr;
229 } else if (STI.hasSSE2()) {
230 return X86::ADDSDrr;
231 }
232 } else if (Ty == LLT::vector(4, 32)) {
233 if ((STI.hasAVX512()) && (STI.hasVLX())) {
234 return X86::VADDPSZ128rr;
235 } else if (STI.hasAVX()) {
236 return X86::VADDPSrr;
237 } else if (STI.hasSSE1()) {
238 return X86::ADDPSrr;
239 }
240 }
241
242 return TargetOpcode::G_FADD;
243}
244
245unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
246 const RegisterBank &RB) const {
247
248 if (X86::VECRRegBankID != RB.getID())
249 return TargetOpcode::G_FSUB;
250
251 if (Ty == LLT::scalar(32)) {
252 if (STI.hasAVX512()) {
253 return X86::VSUBSSZrr;
254 } else if (STI.hasAVX()) {
255 return X86::VSUBSSrr;
256 } else if (STI.hasSSE1()) {
257 return X86::SUBSSrr;
258 }
259 } else if (Ty == LLT::scalar(64)) {
260 if (STI.hasAVX512()) {
261 return X86::VSUBSDZrr;
262 } else if (STI.hasAVX()) {
263 return X86::VSUBSDrr;
264 } else if (STI.hasSSE2()) {
265 return X86::SUBSDrr;
266 }
267 } else if (Ty == LLT::vector(4, 32)) {
268 if ((STI.hasAVX512()) && (STI.hasVLX())) {
269 return X86::VSUBPSZ128rr;
270 } else if (STI.hasAVX()) {
271 return X86::VSUBPSrr;
272 } else if (STI.hasSSE1()) {
273 return X86::SUBPSrr;
274 }
275 }
276
277 return TargetOpcode::G_FSUB;
278}
279
280unsigned X86InstructionSelector::getAddOp(LLT &Ty,
281 const RegisterBank &RB) const {
282
283 if (X86::VECRRegBankID != RB.getID())
284 return TargetOpcode::G_ADD;
285
286 if (Ty == LLT::vector(4, 32)) {
287 if (STI.hasAVX512() && STI.hasVLX()) {
288 return X86::VPADDDZ128rr;
289 } else if (STI.hasAVX()) {
290 return X86::VPADDDrr;
291 } else if (STI.hasSSE2()) {
292 return X86::PADDDrr;
293 }
294 }
295
296 return TargetOpcode::G_ADD;
297}
298
299unsigned X86InstructionSelector::getSubOp(LLT &Ty,
300 const RegisterBank &RB) const {
301
302 if (X86::VECRRegBankID != RB.getID())
303 return TargetOpcode::G_SUB;
304
305 if (Ty == LLT::vector(4, 32)) {
306 if (STI.hasAVX512() && STI.hasVLX()) {
307 return X86::VPSUBDZ128rr;
308 } else if (STI.hasAVX()) {
309 return X86::VPSUBDrr;
310 } else if (STI.hasSSE2()) {
311 return X86::PSUBDrr;
312 }
313 }
314
315 return TargetOpcode::G_SUB;
316}
317
318bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
Igor Bregera8ba5722017-03-23 15:25:57 +0000319 MachineRegisterInfo &MRI,
320 MachineFunction &MF) const {
Igor Breger321cf3c2017-03-03 08:06:46 +0000321
Igor Breger321cf3c2017-03-03 08:06:46 +0000322 const unsigned DefReg = I.getOperand(0).getReg();
Igor Bregera8ba5722017-03-23 15:25:57 +0000323 LLT Ty = MRI.getType(DefReg);
Igor Breger321cf3c2017-03-03 08:06:46 +0000324 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
325
326 unsigned NewOpc = I.getOpcode();
327
Igor Bregera8ba5722017-03-23 15:25:57 +0000328 switch (NewOpc) {
Igor Breger321cf3c2017-03-03 08:06:46 +0000329 case TargetOpcode::G_FADD:
330 NewOpc = getFAddOp(Ty, RB);
331 break;
332 case TargetOpcode::G_FSUB:
333 NewOpc = getFSubOp(Ty, RB);
334 break;
335 case TargetOpcode::G_ADD:
336 NewOpc = getAddOp(Ty, RB);
337 break;
338 case TargetOpcode::G_SUB:
339 NewOpc = getSubOp(Ty, RB);
340 break;
341 default:
342 break;
343 }
344
345 if (NewOpc == I.getOpcode())
346 return false;
347
348 I.setDesc(TII.get(NewOpc));
349
350 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
351}
Igor Bregera8ba5722017-03-23 15:25:57 +0000352
353unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
354 unsigned Opc,
355 uint64_t Alignment) const {
356 bool Isload = (Opc == TargetOpcode::G_LOAD);
357 bool HasAVX = STI.hasAVX();
358 bool HasAVX512 = STI.hasAVX512();
359 bool HasVLX = STI.hasVLX();
360
361 if (Ty == LLT::scalar(8)) {
362 if (X86::GPRRegBankID == RB.getID())
363 return Isload ? X86::MOV8rm : X86::MOV8mr;
364 } else if (Ty == LLT::scalar(16)) {
365 if (X86::GPRRegBankID == RB.getID())
366 return Isload ? X86::MOV16rm : X86::MOV16mr;
367 } else if (Ty == LLT::scalar(32)) {
368 if (X86::GPRRegBankID == RB.getID())
369 return Isload ? X86::MOV32rm : X86::MOV32mr;
370 if (X86::VECRRegBankID == RB.getID())
371 return Isload ? (HasAVX512 ? X86::VMOVSSZrm
372 : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
373 : (HasAVX512 ? X86::VMOVSSZmr
374 : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
375 } else if (Ty == LLT::scalar(64)) {
376 if (X86::GPRRegBankID == RB.getID())
377 return Isload ? X86::MOV64rm : X86::MOV64mr;
378 if (X86::VECRRegBankID == RB.getID())
379 return Isload ? (HasAVX512 ? X86::VMOVSDZrm
380 : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
381 : (HasAVX512 ? X86::VMOVSDZmr
382 : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
383 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
384 if (Alignment >= 16)
385 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
386 : HasAVX512
387 ? X86::VMOVAPSZ128rm_NOVLX
388 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
389 : (HasVLX ? X86::VMOVAPSZ128mr
390 : HasAVX512
391 ? X86::VMOVAPSZ128mr_NOVLX
392 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
393 else
394 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
395 : HasAVX512
396 ? X86::VMOVUPSZ128rm_NOVLX
397 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
398 : (HasVLX ? X86::VMOVUPSZ128mr
399 : HasAVX512
400 ? X86::VMOVUPSZ128mr_NOVLX
401 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
402 }
403 return Opc;
404}
405
406bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
407 MachineRegisterInfo &MRI,
408 MachineFunction &MF) const {
409
410 unsigned Opc = I.getOpcode();
411
412 if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
413 return false;
414
415 const unsigned DefReg = I.getOperand(0).getReg();
416 LLT Ty = MRI.getType(DefReg);
417 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
418
419 auto &MemOp = **I.memoperands_begin();
420 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
421 if (NewOpc == Opc)
422 return false;
423
424 I.setDesc(TII.get(NewOpc));
425 MachineInstrBuilder MIB(MF, I);
426 if (Opc == TargetOpcode::G_LOAD)
427 addOffset(MIB, 0);
428 else {
429 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
430 I.RemoveOperand(0);
431 addOffset(MIB, 0).addUse(DefReg);
432 }
433 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
434}
435
Igor Breger531a2032017-03-26 08:11:12 +0000436bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
437 MachineRegisterInfo &MRI,
438 MachineFunction &MF) const {
439 if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX)
440 return false;
441
442 const unsigned DefReg = I.getOperand(0).getReg();
443 LLT Ty = MRI.getType(DefReg);
444
445 // Use LEA to calculate frame index.
446 unsigned NewOpc;
447 if (Ty == LLT::pointer(0, 64))
448 NewOpc = X86::LEA64r;
449 else if (Ty == LLT::pointer(0, 32))
450 NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
451 else
452 llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type.");
453
454 I.setDesc(TII.get(NewOpc));
455 MachineInstrBuilder MIB(MF, I);
456 addOffset(MIB, 0);
457
458 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
459}
Daniel Sanders0b5293f2017-04-06 09:49:34 +0000460
461InstructionSelector *
462llvm::createX86InstructionSelector(X86Subtarget &Subtarget,
463 X86RegisterBankInfo &RBI) {
464 return new X86InstructionSelector(Subtarget, RBI);
465}