]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / Mips / MipsInstructionSelector.cpp
1 //===- MipsInstructionSelector.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 /// Mips.
12 /// \todo This should be generated by TableGen.
13 //===----------------------------------------------------------------------===//
14
15 #include "MipsRegisterBankInfo.h"
16 #include "MipsTargetMachine.h"
17 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
18
19 #define DEBUG_TYPE "mips-isel"
20
21 using namespace llvm;
22
23 namespace {
24
25 #define GET_GLOBALISEL_PREDICATE_BITSET
26 #include "MipsGenGlobalISel.inc"
27 #undef GET_GLOBALISEL_PREDICATE_BITSET
28
29 class MipsInstructionSelector : public InstructionSelector {
30 public:
31   MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
32                           const MipsRegisterBankInfo &RBI);
33
34   bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
35   static const char *getName() { return DEBUG_TYPE; }
36
37 private:
38   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
39
40   const MipsTargetMachine &TM;
41   const MipsSubtarget &STI;
42   const MipsInstrInfo &TII;
43   const MipsRegisterInfo &TRI;
44   const MipsRegisterBankInfo &RBI;
45
46 #define GET_GLOBALISEL_PREDICATES_DECL
47 #include "MipsGenGlobalISel.inc"
48 #undef GET_GLOBALISEL_PREDICATES_DECL
49
50 #define GET_GLOBALISEL_TEMPORARIES_DECL
51 #include "MipsGenGlobalISel.inc"
52 #undef GET_GLOBALISEL_TEMPORARIES_DECL
53 };
54
55 } // end anonymous namespace
56
57 #define GET_GLOBALISEL_IMPL
58 #include "MipsGenGlobalISel.inc"
59 #undef GET_GLOBALISEL_IMPL
60
61 MipsInstructionSelector::MipsInstructionSelector(
62     const MipsTargetMachine &TM, const MipsSubtarget &STI,
63     const MipsRegisterBankInfo &RBI)
64     : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
65       TRI(*STI.getRegisterInfo()), RBI(RBI),
66
67 #define GET_GLOBALISEL_PREDICATES_INIT
68 #include "MipsGenGlobalISel.inc"
69 #undef GET_GLOBALISEL_PREDICATES_INIT
70 #define GET_GLOBALISEL_TEMPORARIES_INIT
71 #include "MipsGenGlobalISel.inc"
72 #undef GET_GLOBALISEL_TEMPORARIES_INIT
73 {
74 }
75
76 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
77                        MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
78                        const RegisterBankInfo &RBI) {
79   unsigned DstReg = I.getOperand(0).getReg();
80   if (TargetRegisterInfo::isPhysicalRegister(DstReg))
81     return true;
82
83   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
84
85   if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
86     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
87                       << " operand\n");
88     return false;
89   }
90   return true;
91 }
92
93 bool MipsInstructionSelector::select(MachineInstr &I,
94                                      CodeGenCoverage &CoverageInfo) const {
95
96   MachineBasicBlock &MBB = *I.getParent();
97   MachineFunction &MF = *MBB.getParent();
98   MachineRegisterInfo &MRI = MF.getRegInfo();
99
100   if (!isPreISelGenericOpcode(I.getOpcode())) {
101     if (I.isCopy())
102       return selectCopy(I, TII, MRI, TRI, RBI);
103
104     return true;
105   }
106
107   if (selectImpl(I, CoverageInfo)) {
108     return true;
109   }
110
111   MachineInstr *MI = nullptr;
112   using namespace TargetOpcode;
113
114   switch (I.getOpcode()) {
115   case G_GEP: {
116     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
117              .add(I.getOperand(0))
118              .add(I.getOperand(1))
119              .add(I.getOperand(2));
120     break;
121   }
122   case G_FRAME_INDEX: {
123     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
124              .add(I.getOperand(0))
125              .add(I.getOperand(1))
126              .addImm(0);
127     break;
128   }
129   case G_STORE:
130   case G_LOAD: {
131     const unsigned DestReg = I.getOperand(0).getReg();
132     const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
133     const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
134
135     if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32)
136       return false;
137
138     const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW;
139
140     MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
141              .add(I.getOperand(0))
142              .add(I.getOperand(1))
143              .addImm(0)
144              .addMemOperand(*I.memoperands_begin());
145     break;
146   }
147   case G_CONSTANT: {
148     int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue();
149     unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
150     MachineInstr *LUi, *ORi;
151
152     LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
153               .addDef(LUiReg)
154               .addImm(Imm >> 16);
155
156     ORi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ORi))
157               .addDef(I.getOperand(0).getReg())
158               .addUse(LUiReg)
159               .addImm(Imm & 0xFFFF);
160
161     if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
162       return false;
163     if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
164       return false;
165
166     I.eraseFromParent();
167     return true;
168   }
169   case G_GLOBAL_VALUE: {
170     if (MF.getTarget().isPositionIndependent())
171       return false;
172
173     const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
174     unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
175     MachineInstr *LUi, *ADDiu;
176
177     LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
178               .addDef(LUiReg)
179               .addGlobalAddress(GVal);
180     LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
181
182     ADDiu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
183                 .addDef(I.getOperand(0).getReg())
184                 .addUse(LUiReg)
185                 .addGlobalAddress(GVal);
186     ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
187
188     if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
189       return false;
190     if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
191       return false;
192
193     I.eraseFromParent();
194     return true;
195   }
196
197   default:
198     return false;
199   }
200
201   I.eraseFromParent();
202   return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
203 }
204
205 namespace llvm {
206 InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM,
207                                                    MipsSubtarget &Subtarget,
208                                                    MipsRegisterBankInfo &RBI) {
209   return new MipsInstructionSelector(TM, Subtarget, RBI);
210 }
211 } // end namespace llvm