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