]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/X86/X86InstructionSelector.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r302418, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / X86 / X86InstructionSelector.cpp
1 //===- 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
15 #include "X86InstrBuilder.h"
16 #include "X86InstrInfo.h"
17 #include "X86RegisterBankInfo.h"
18 #include "X86RegisterInfo.h"
19 #include "X86Subtarget.h"
20 #include "X86TargetMachine.h"
21 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
22 #include "llvm/CodeGen/MachineBasicBlock.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/CodeGen/MachineInstr.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 #include "llvm/CodeGen/MachineOperand.h"
27 #include "llvm/CodeGen/MachineRegisterInfo.h"
28 #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
34 using namespace llvm;
35
36 #ifndef LLVM_BUILD_GLOBAL_ISEL
37 #error "You shouldn't build this"
38 #endif
39
40 namespace {
41
42 #define GET_GLOBALISEL_PREDICATE_BITSET
43 #include "X86GenGlobalISel.inc"
44 #undef GET_GLOBALISEL_PREDICATE_BITSET
45
46 class X86InstructionSelector : public InstructionSelector {
47 public:
48   X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
49                          const X86RegisterBankInfo &RBI);
50
51   bool select(MachineInstr &I) const override;
52
53 private:
54   /// tblgen-erated 'select' implementation, used as the initial selector for
55   /// the patterns that don't require complex C++.
56   bool selectImpl(MachineInstr &I) const;
57
58   // TODO: remove after suported by Tablegen-erated instruction selection.
59   unsigned getFAddOp(LLT &Ty, const RegisterBank &RB) const;
60   unsigned getFSubOp(LLT &Ty, const RegisterBank &RB) const;
61   unsigned getLoadStoreOp(LLT &Ty, const RegisterBank &RB, unsigned Opc,
62                           uint64_t Alignment) const;
63
64   bool selectBinaryOp(MachineInstr &I, MachineRegisterInfo &MRI,
65                       MachineFunction &MF) const;
66   bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
67                          MachineFunction &MF) const;
68   bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
69                              MachineFunction &MF) const;
70   bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
71                       MachineFunction &MF) const;
72   bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
73                    MachineFunction &MF) const;
74
75   const X86TargetMachine &TM;
76   const X86Subtarget &STI;
77   const X86InstrInfo &TII;
78   const X86RegisterInfo &TRI;
79   const X86RegisterBankInfo &RBI;
80
81 #define GET_GLOBALISEL_PREDICATES_DECL
82 #include "X86GenGlobalISel.inc"
83 #undef GET_GLOBALISEL_PREDICATES_DECL
84
85 #define GET_GLOBALISEL_TEMPORARIES_DECL
86 #include "X86GenGlobalISel.inc"
87 #undef GET_GLOBALISEL_TEMPORARIES_DECL
88 };
89
90 } // end anonymous namespace
91
92 #define GET_GLOBALISEL_IMPL
93 #include "X86GenGlobalISel.inc"
94 #undef GET_GLOBALISEL_IMPL
95
96 X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
97                                                const X86Subtarget &STI,
98                                                const X86RegisterBankInfo &RBI)
99     : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
100       TRI(*STI.getRegisterInfo()), RBI(RBI),
101 #define GET_GLOBALISEL_PREDICATES_INIT
102 #include "X86GenGlobalISel.inc"
103 #undef GET_GLOBALISEL_PREDICATES_INIT
104 #define GET_GLOBALISEL_TEMPORARIES_INIT
105 #include "X86GenGlobalISel.inc"
106 #undef GET_GLOBALISEL_TEMPORARIES_INIT
107 {
108 }
109
110 // FIXME: This should be target-independent, inferred from the types declared
111 // for each class in the bank.
112 static const TargetRegisterClass *
113 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
114   if (RB.getID() == X86::GPRRegBankID) {
115     if (Ty.getSizeInBits() <= 8)
116       return &X86::GR8RegClass;
117     if (Ty.getSizeInBits() == 16)
118       return &X86::GR16RegClass;
119     if (Ty.getSizeInBits() == 32)
120       return &X86::GR32RegClass;
121     if (Ty.getSizeInBits() == 64)
122       return &X86::GR64RegClass;
123   }
124   if (RB.getID() == X86::VECRRegBankID) {
125     if (Ty.getSizeInBits() == 32)
126       return &X86::FR32XRegClass;
127     if (Ty.getSizeInBits() == 64)
128       return &X86::FR64XRegClass;
129     if (Ty.getSizeInBits() == 128)
130       return &X86::VR128XRegClass;
131     if (Ty.getSizeInBits() == 256)
132       return &X86::VR256XRegClass;
133     if (Ty.getSizeInBits() == 512)
134       return &X86::VR512RegClass;
135   }
136
137   llvm_unreachable("Unknown RegBank!");
138 }
139
140 // Set X86 Opcode and constrain DestReg.
141 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
142                        MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
143                        const RegisterBankInfo &RBI) {
144
145   unsigned DstReg = I.getOperand(0).getReg();
146   if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
147     assert(I.isCopy() && "Generic operators do not allow physical registers");
148     return true;
149   }
150
151   const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
152   const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
153   unsigned SrcReg = I.getOperand(1).getReg();
154   const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
155
156   assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
157          "No phys reg on generic operators");
158   assert((DstSize == SrcSize ||
159           // Copies are a mean to setup initial types, the number of
160           // bits may not exactly match.
161           (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
162            DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
163          "Copy with different width?!");
164
165   const TargetRegisterClass *RC = nullptr;
166
167   switch (RegBank.getID()) {
168   case X86::GPRRegBankID:
169     assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
170     RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
171
172     // Change the physical register
173     if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
174       if (RC == &X86::GR32RegClass)
175         I.getOperand(1).setSubReg(X86::sub_32bit);
176       else if (RC == &X86::GR16RegClass)
177         I.getOperand(1).setSubReg(X86::sub_16bit);
178       else if (RC == &X86::GR8RegClass)
179         I.getOperand(1).setSubReg(X86::sub_8bit);
180
181       I.getOperand(1).substPhysReg(SrcReg, TRI);
182     }
183     break;
184   case X86::VECRRegBankID:
185     RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
186     break;
187   default:
188     llvm_unreachable("Unknown RegBank!");
189   }
190
191   // No need to constrain SrcReg. It will get constrained when
192   // we hit another of its use or its defs.
193   // Copies do not have constraints.
194   const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
195   if (!OldRC || !RC->hasSubClassEq(OldRC)) {
196     if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
197       DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
198                    << " operand\n");
199       return false;
200     }
201   }
202   I.setDesc(TII.get(X86::COPY));
203   return true;
204 }
205
206 bool X86InstructionSelector::select(MachineInstr &I) const {
207   assert(I.getParent() && "Instruction should be in a basic block!");
208   assert(I.getParent()->getParent() && "Instruction should be in a function!");
209
210   MachineBasicBlock &MBB = *I.getParent();
211   MachineFunction &MF = *MBB.getParent();
212   MachineRegisterInfo &MRI = MF.getRegInfo();
213
214   unsigned Opcode = I.getOpcode();
215   if (!isPreISelGenericOpcode(Opcode)) {
216     // Certain non-generic instructions also need some special handling.
217
218     if (I.isCopy())
219       return selectCopy(I, TII, MRI, TRI, RBI);
220
221     // TODO: handle more cases - LOAD_STACK_GUARD, PHI
222     return true;
223   }
224
225   assert(I.getNumOperands() == I.getNumExplicitOperands() &&
226          "Generic instruction has unexpected implicit operands\n");
227
228   if (selectImpl(I))
229      return true;
230
231   DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
232
233   // TODO: This should be implemented by tblgen.
234   if (selectBinaryOp(I, MRI, MF))
235     return true;
236   if (selectLoadStoreOp(I, MRI, MF))
237     return true;
238   if (selectFrameIndexOrGep(I, MRI, MF))
239     return true;
240   if (selectConstant(I, MRI, MF))
241     return true;
242   if (selectTrunc(I, MRI, MF))
243     return true;
244
245   return false;
246 }
247
248 unsigned X86InstructionSelector::getFAddOp(LLT &Ty,
249                                            const RegisterBank &RB) const {
250
251   if (X86::VECRRegBankID != RB.getID())
252     return TargetOpcode::G_FADD;
253
254   if (Ty == LLT::scalar(32)) {
255     if (STI.hasAVX512()) {
256       return X86::VADDSSZrr;
257     } else if (STI.hasAVX()) {
258       return X86::VADDSSrr;
259     } else if (STI.hasSSE1()) {
260       return X86::ADDSSrr;
261     }
262   } else if (Ty == LLT::scalar(64)) {
263     if (STI.hasAVX512()) {
264       return X86::VADDSDZrr;
265     } else if (STI.hasAVX()) {
266       return X86::VADDSDrr;
267     } else if (STI.hasSSE2()) {
268       return X86::ADDSDrr;
269     }
270   } else if (Ty == LLT::vector(4, 32)) {
271     if ((STI.hasAVX512()) && (STI.hasVLX())) {
272       return X86::VADDPSZ128rr;
273     } else if (STI.hasAVX()) {
274       return X86::VADDPSrr;
275     } else if (STI.hasSSE1()) {
276       return X86::ADDPSrr;
277     }
278   }
279
280   return TargetOpcode::G_FADD;
281 }
282
283 unsigned X86InstructionSelector::getFSubOp(LLT &Ty,
284                                            const RegisterBank &RB) const {
285
286   if (X86::VECRRegBankID != RB.getID())
287     return TargetOpcode::G_FSUB;
288
289   if (Ty == LLT::scalar(32)) {
290     if (STI.hasAVX512()) {
291       return X86::VSUBSSZrr;
292     } else if (STI.hasAVX()) {
293       return X86::VSUBSSrr;
294     } else if (STI.hasSSE1()) {
295       return X86::SUBSSrr;
296     }
297   } else if (Ty == LLT::scalar(64)) {
298     if (STI.hasAVX512()) {
299       return X86::VSUBSDZrr;
300     } else if (STI.hasAVX()) {
301       return X86::VSUBSDrr;
302     } else if (STI.hasSSE2()) {
303       return X86::SUBSDrr;
304     }
305   } else if (Ty == LLT::vector(4, 32)) {
306     if ((STI.hasAVX512()) && (STI.hasVLX())) {
307       return X86::VSUBPSZ128rr;
308     } else if (STI.hasAVX()) {
309       return X86::VSUBPSrr;
310     } else if (STI.hasSSE1()) {
311       return X86::SUBPSrr;
312     }
313   }
314
315   return TargetOpcode::G_FSUB;
316 }
317
318 bool X86InstructionSelector::selectBinaryOp(MachineInstr &I,
319                                             MachineRegisterInfo &MRI,
320                                             MachineFunction &MF) const {
321
322   const unsigned DefReg = I.getOperand(0).getReg();
323   LLT Ty = MRI.getType(DefReg);
324   const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
325
326   unsigned NewOpc = I.getOpcode();
327
328   switch (NewOpc) {
329   case TargetOpcode::G_FADD:
330     NewOpc = getFAddOp(Ty, RB);
331     break;
332   case TargetOpcode::G_FSUB:
333     NewOpc = getFSubOp(Ty, RB);
334     break;
335   default:
336     break;
337   }
338
339   if (NewOpc == I.getOpcode())
340     return false;
341
342   I.setDesc(TII.get(NewOpc));
343
344   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
345 }
346
347 unsigned X86InstructionSelector::getLoadStoreOp(LLT &Ty, const RegisterBank &RB,
348                                                 unsigned Opc,
349                                                 uint64_t Alignment) const {
350   bool Isload = (Opc == TargetOpcode::G_LOAD);
351   bool HasAVX = STI.hasAVX();
352   bool HasAVX512 = STI.hasAVX512();
353   bool HasVLX = STI.hasVLX();
354
355   if (Ty == LLT::scalar(8)) {
356     if (X86::GPRRegBankID == RB.getID())
357       return Isload ? X86::MOV8rm : X86::MOV8mr;
358   } else if (Ty == LLT::scalar(16)) {
359     if (X86::GPRRegBankID == RB.getID())
360       return Isload ? X86::MOV16rm : X86::MOV16mr;
361   } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
362     if (X86::GPRRegBankID == RB.getID())
363       return Isload ? X86::MOV32rm : X86::MOV32mr;
364     if (X86::VECRRegBankID == RB.getID())
365       return Isload ? (HasAVX512 ? X86::VMOVSSZrm
366                                  : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm)
367                     : (HasAVX512 ? X86::VMOVSSZmr
368                                  : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
369   } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
370     if (X86::GPRRegBankID == RB.getID())
371       return Isload ? X86::MOV64rm : X86::MOV64mr;
372     if (X86::VECRRegBankID == RB.getID())
373       return Isload ? (HasAVX512 ? X86::VMOVSDZrm
374                                  : HasAVX ? X86::VMOVSDrm : X86::MOVSDrm)
375                     : (HasAVX512 ? X86::VMOVSDZmr
376                                  : HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
377   } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
378     if (Alignment >= 16)
379       return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
380                               : HasAVX512
381                                     ? X86::VMOVAPSZ128rm_NOVLX
382                                     : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
383                     : (HasVLX ? X86::VMOVAPSZ128mr
384                               : HasAVX512
385                                     ? X86::VMOVAPSZ128mr_NOVLX
386                                     : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
387     else
388       return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
389                               : HasAVX512
390                                     ? X86::VMOVUPSZ128rm_NOVLX
391                                     : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
392                     : (HasVLX ? X86::VMOVUPSZ128mr
393                               : HasAVX512
394                                     ? X86::VMOVUPSZ128mr_NOVLX
395                                     : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
396   }
397   return Opc;
398 }
399
400 bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
401                                                MachineRegisterInfo &MRI,
402                                                MachineFunction &MF) const {
403
404   unsigned Opc = I.getOpcode();
405
406   if (Opc != TargetOpcode::G_STORE && Opc != TargetOpcode::G_LOAD)
407     return false;
408
409   const unsigned DefReg = I.getOperand(0).getReg();
410   LLT Ty = MRI.getType(DefReg);
411   const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
412
413   auto &MemOp = **I.memoperands_begin();
414   unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
415   if (NewOpc == Opc)
416     return false;
417
418   I.setDesc(TII.get(NewOpc));
419   MachineInstrBuilder MIB(MF, I);
420   if (Opc == TargetOpcode::G_LOAD)
421     addOffset(MIB, 0);
422   else {
423     // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
424     I.RemoveOperand(0);
425     addOffset(MIB, 0).addUse(DefReg);
426   }
427   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
428 }
429
430 bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
431                                                    MachineRegisterInfo &MRI,
432                                                    MachineFunction &MF) const {
433   unsigned Opc = I.getOpcode();
434
435   if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
436     return false;
437
438   const unsigned DefReg = I.getOperand(0).getReg();
439   LLT Ty = MRI.getType(DefReg);
440
441   // Use LEA to calculate frame index and GEP
442   unsigned NewOpc;
443   if (Ty == LLT::pointer(0, 64))
444     NewOpc = X86::LEA64r;
445   else if (Ty == LLT::pointer(0, 32))
446     NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
447   else
448     llvm_unreachable("Can't select G_FRAME_INDEX/G_GEP, unsupported type.");
449
450   I.setDesc(TII.get(NewOpc));
451   MachineInstrBuilder MIB(MF, I);
452
453   if (Opc == TargetOpcode::G_FRAME_INDEX) {
454     addOffset(MIB, 0);
455   } else {
456     MachineOperand &InxOp = I.getOperand(2);
457     I.addOperand(InxOp);        // set IndexReg
458     InxOp.ChangeToImmediate(1); // set Scale
459     MIB.addImm(0).addReg(0);
460   }
461
462   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
463 }
464
465 bool X86InstructionSelector::selectConstant(MachineInstr &I,
466                                             MachineRegisterInfo &MRI,
467                                             MachineFunction &MF) const {
468   if (I.getOpcode() != TargetOpcode::G_CONSTANT)
469     return false;
470
471   const unsigned DefReg = I.getOperand(0).getReg();
472   LLT Ty = MRI.getType(DefReg);
473
474   assert(Ty.isScalar() && "invalid element type.");
475
476   uint64_t Val = 0;
477   if (I.getOperand(1).isCImm()) {
478     Val = I.getOperand(1).getCImm()->getZExtValue();
479     I.getOperand(1).ChangeToImmediate(Val);
480   } else if (I.getOperand(1).isImm()) {
481     Val = I.getOperand(1).getImm();
482   } else
483     llvm_unreachable("Unsupported operand type.");
484
485   unsigned NewOpc;
486   switch (Ty.getSizeInBits()) {
487   case 8:
488     NewOpc = X86::MOV8ri;
489     break;
490   case 16:
491     NewOpc = X86::MOV16ri;
492     break;
493   case 32:
494     NewOpc = X86::MOV32ri;
495     break;
496   case 64: {
497     // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
498     if (isInt<32>(Val))
499       NewOpc = X86::MOV64ri32;
500     else
501       NewOpc = X86::MOV64ri;
502     break;
503   }
504   default:
505     llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
506   }
507
508   I.setDesc(TII.get(NewOpc));
509   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
510 }
511
512 bool X86InstructionSelector::selectTrunc(MachineInstr &I,
513                                          MachineRegisterInfo &MRI,
514                                          MachineFunction &MF) const {
515   if (I.getOpcode() != TargetOpcode::G_TRUNC)
516     return false;
517
518   const unsigned DstReg = I.getOperand(0).getReg();
519   const unsigned SrcReg = I.getOperand(1).getReg();
520
521   const LLT DstTy = MRI.getType(DstReg);
522   const LLT SrcTy = MRI.getType(SrcReg);
523
524   const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
525   const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
526
527   if (DstRB.getID() != SrcRB.getID()) {
528     DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
529     return false;
530   }
531
532   if (DstRB.getID() != X86::GPRRegBankID)
533     return false;
534
535   const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
536   if (!DstRC)
537     return false;
538
539   const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
540   if (!SrcRC)
541     return false;
542
543   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
544       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
545     DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
546     return false;
547   }
548
549   if (DstRC == SrcRC) {
550     // Nothing to be done
551   } else if (DstRC == &X86::GR32RegClass) {
552     I.getOperand(1).setSubReg(X86::sub_32bit);
553   } else if (DstRC == &X86::GR16RegClass) {
554     I.getOperand(1).setSubReg(X86::sub_16bit);
555   } else if (DstRC == &X86::GR8RegClass) {
556     I.getOperand(1).setSubReg(X86::sub_8bit);
557   } else {
558     return false;
559   }
560
561   I.setDesc(TII.get(X86::COPY));
562   return true;
563 }
564
565 InstructionSelector *
566 llvm::createX86InstructionSelector(const X86TargetMachine &TM,
567                                    X86Subtarget &Subtarget,
568                                    X86RegisterBankInfo &RBI) {
569   return new X86InstructionSelector(TM, Subtarget, RBI);
570 }