1 //===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This file implements the targeting of the InstructionSelector class for
12 /// \todo This should be generated by TableGen.
13 //===----------------------------------------------------------------------===//
15 #include "MipsRegisterBankInfo.h"
16 #include "MipsTargetMachine.h"
17 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
18 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
20 #define DEBUG_TYPE "mips-isel"
26 #define GET_GLOBALISEL_PREDICATE_BITSET
27 #include "MipsGenGlobalISel.inc"
28 #undef GET_GLOBALISEL_PREDICATE_BITSET
30 class MipsInstructionSelector
: public InstructionSelector
{
32 MipsInstructionSelector(const MipsTargetMachine
&TM
, const MipsSubtarget
&STI
,
33 const MipsRegisterBankInfo
&RBI
);
35 bool select(MachineInstr
&I
, CodeGenCoverage
&CoverageInfo
) const override
;
36 static const char *getName() { return DEBUG_TYPE
; }
39 bool selectImpl(MachineInstr
&I
, CodeGenCoverage
&CoverageInfo
) const;
41 const MipsTargetMachine
&TM
;
42 const MipsSubtarget
&STI
;
43 const MipsInstrInfo
&TII
;
44 const MipsRegisterInfo
&TRI
;
45 const MipsRegisterBankInfo
&RBI
;
47 #define GET_GLOBALISEL_PREDICATES_DECL
48 #include "MipsGenGlobalISel.inc"
49 #undef GET_GLOBALISEL_PREDICATES_DECL
51 #define GET_GLOBALISEL_TEMPORARIES_DECL
52 #include "MipsGenGlobalISel.inc"
53 #undef GET_GLOBALISEL_TEMPORARIES_DECL
56 } // end anonymous namespace
58 #define GET_GLOBALISEL_IMPL
59 #include "MipsGenGlobalISel.inc"
60 #undef GET_GLOBALISEL_IMPL
62 MipsInstructionSelector::MipsInstructionSelector(
63 const MipsTargetMachine
&TM
, const MipsSubtarget
&STI
,
64 const MipsRegisterBankInfo
&RBI
)
65 : InstructionSelector(), TM(TM
), STI(STI
), TII(*STI
.getInstrInfo()),
66 TRI(*STI
.getRegisterInfo()), RBI(RBI
),
68 #define GET_GLOBALISEL_PREDICATES_INIT
69 #include "MipsGenGlobalISel.inc"
70 #undef GET_GLOBALISEL_PREDICATES_INIT
71 #define GET_GLOBALISEL_TEMPORARIES_INIT
72 #include "MipsGenGlobalISel.inc"
73 #undef GET_GLOBALISEL_TEMPORARIES_INIT
77 static bool selectCopy(MachineInstr
&I
, const TargetInstrInfo
&TII
,
78 MachineRegisterInfo
&MRI
, const TargetRegisterInfo
&TRI
,
79 const RegisterBankInfo
&RBI
) {
80 unsigned DstReg
= I
.getOperand(0).getReg();
81 if (TargetRegisterInfo::isPhysicalRegister(DstReg
))
84 const TargetRegisterClass
*RC
= &Mips::GPR32RegClass
;
86 if (!RBI
.constrainGenericRegister(DstReg
, *RC
, MRI
)) {
87 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII
.getName(I
.getOpcode())
94 bool MipsInstructionSelector::select(MachineInstr
&I
,
95 CodeGenCoverage
&CoverageInfo
) const {
97 MachineBasicBlock
&MBB
= *I
.getParent();
98 MachineFunction
&MF
= *MBB
.getParent();
99 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
101 if (!isPreISelGenericOpcode(I
.getOpcode())) {
103 return selectCopy(I
, TII
, MRI
, TRI
, RBI
);
108 if (selectImpl(I
, CoverageInfo
)) {
112 MachineInstr
*MI
= nullptr;
113 using namespace TargetOpcode
;
115 switch (I
.getOpcode()) {
117 MI
= BuildMI(MBB
, I
, I
.getDebugLoc(), TII
.get(Mips::ADDu
))
118 .add(I
.getOperand(0))
119 .add(I
.getOperand(1))
120 .add(I
.getOperand(2));
123 case G_FRAME_INDEX
: {
124 MI
= BuildMI(MBB
, I
, I
.getDebugLoc(), TII
.get(Mips::ADDiu
))
125 .add(I
.getOperand(0))
126 .add(I
.getOperand(1))
132 const unsigned DestReg
= I
.getOperand(0).getReg();
133 const unsigned DestRegBank
= RBI
.getRegBank(DestReg
, MRI
, TRI
)->getID();
134 const unsigned OpSize
= MRI
.getType(DestReg
).getSizeInBits();
136 if (DestRegBank
!= Mips::GPRBRegBankID
|| OpSize
!= 32)
139 const unsigned NewOpc
= I
.getOpcode() == G_STORE
? Mips::SW
: Mips::LW
;
141 MI
= BuildMI(MBB
, I
, I
.getDebugLoc(), TII
.get(NewOpc
))
142 .add(I
.getOperand(0))
143 .add(I
.getOperand(1))
145 .addMemOperand(*I
.memoperands_begin());
149 int Imm
= I
.getOperand(1).getCImm()->getValue().getLimitedValue();
150 unsigned LUiReg
= MRI
.createVirtualRegister(&Mips::GPR32RegClass
);
151 MachineInstr
*LUi
, *ORi
;
153 LUi
= BuildMI(MBB
, I
, I
.getDebugLoc(), TII
.get(Mips::LUi
))
157 ORi
= BuildMI(MBB
, I
, I
.getDebugLoc(), TII
.get(Mips::ORi
))
158 .addDef(I
.getOperand(0).getReg())
160 .addImm(Imm
& 0xFFFF);
162 if (!constrainSelectedInstRegOperands(*LUi
, TII
, TRI
, RBI
))
164 if (!constrainSelectedInstRegOperands(*ORi
, TII
, TRI
, RBI
))
170 case G_GLOBAL_VALUE
: {
171 if (MF
.getTarget().isPositionIndependent())
174 const llvm::GlobalValue
*GVal
= I
.getOperand(1).getGlobal();
175 unsigned LUiReg
= MRI
.createVirtualRegister(&Mips::GPR32RegClass
);
176 MachineInstr
*LUi
, *ADDiu
;
178 LUi
= BuildMI(MBB
, I
, I
.getDebugLoc(), TII
.get(Mips::LUi
))
180 .addGlobalAddress(GVal
);
181 LUi
->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI
);
183 ADDiu
= BuildMI(MBB
, I
, I
.getDebugLoc(), TII
.get(Mips::ADDiu
))
184 .addDef(I
.getOperand(0).getReg())
186 .addGlobalAddress(GVal
);
187 ADDiu
->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO
);
189 if (!constrainSelectedInstRegOperands(*LUi
, TII
, TRI
, RBI
))
191 if (!constrainSelectedInstRegOperands(*ADDiu
, TII
, TRI
, RBI
))
199 unsigned Opcode
, Def
, LHS
, RHS
;
200 Instr(unsigned Opcode
, unsigned Def
, unsigned LHS
, unsigned RHS
)
201 : Opcode(Opcode
), Def(Def
), LHS(LHS
), RHS(RHS
){};
203 bool hasImm() const {
204 if (Opcode
== Mips::SLTiu
|| Opcode
== Mips::XORi
)
210 SmallVector
<struct Instr
, 2> Instructions
;
211 unsigned ICMPReg
= I
.getOperand(0).getReg();
212 unsigned Temp
= MRI
.createVirtualRegister(&Mips::GPR32RegClass
);
213 unsigned LHS
= I
.getOperand(2).getReg();
214 unsigned RHS
= I
.getOperand(3).getReg();
215 CmpInst::Predicate Cond
=
216 static_cast<CmpInst::Predicate
>(I
.getOperand(1).getPredicate());
219 case CmpInst::ICMP_EQ
: // LHS == RHS -> (LHS ^ RHS) < 1
220 Instructions
.emplace_back(Mips::XOR
, Temp
, LHS
, RHS
);
221 Instructions
.emplace_back(Mips::SLTiu
, ICMPReg
, Temp
, 1);
223 case CmpInst::ICMP_NE
: // LHS != RHS -> 0 < (LHS ^ RHS)
224 Instructions
.emplace_back(Mips::XOR
, Temp
, LHS
, RHS
);
225 Instructions
.emplace_back(Mips::SLTu
, ICMPReg
, Mips::ZERO
, Temp
);
227 case CmpInst::ICMP_UGT
: // LHS > RHS -> RHS < LHS
228 Instructions
.emplace_back(Mips::SLTu
, ICMPReg
, RHS
, LHS
);
230 case CmpInst::ICMP_UGE
: // LHS >= RHS -> !(LHS < RHS)
231 Instructions
.emplace_back(Mips::SLTu
, Temp
, LHS
, RHS
);
232 Instructions
.emplace_back(Mips::XORi
, ICMPReg
, Temp
, 1);
234 case CmpInst::ICMP_ULT
: // LHS < RHS -> LHS < RHS
235 Instructions
.emplace_back(Mips::SLTu
, ICMPReg
, LHS
, RHS
);
237 case CmpInst::ICMP_ULE
: // LHS <= RHS -> !(RHS < LHS)
238 Instructions
.emplace_back(Mips::SLTu
, Temp
, RHS
, LHS
);
239 Instructions
.emplace_back(Mips::XORi
, ICMPReg
, Temp
, 1);
241 case CmpInst::ICMP_SGT
: // LHS > RHS -> RHS < LHS
242 Instructions
.emplace_back(Mips::SLT
, ICMPReg
, RHS
, LHS
);
244 case CmpInst::ICMP_SGE
: // LHS >= RHS -> !(LHS < RHS)
245 Instructions
.emplace_back(Mips::SLT
, Temp
, LHS
, RHS
);
246 Instructions
.emplace_back(Mips::XORi
, ICMPReg
, Temp
, 1);
248 case CmpInst::ICMP_SLT
: // LHS < RHS -> LHS < RHS
249 Instructions
.emplace_back(Mips::SLT
, ICMPReg
, LHS
, RHS
);
251 case CmpInst::ICMP_SLE
: // LHS <= RHS -> !(RHS < LHS)
252 Instructions
.emplace_back(Mips::SLT
, Temp
, RHS
, LHS
);
253 Instructions
.emplace_back(Mips::XORi
, ICMPReg
, Temp
, 1);
259 MachineIRBuilder
B(I
);
260 for (const struct Instr
&Instruction
: Instructions
) {
261 MachineInstrBuilder MIB
=
262 B
.buildInstr(Instruction
.Opcode
, Instruction
.Def
, Instruction
.LHS
);
264 if (Instruction
.hasImm())
265 MIB
.addImm(Instruction
.RHS
);
267 MIB
.addUse(Instruction
.RHS
);
269 if (!MIB
.constrainAllUses(TII
, TRI
, RBI
))
281 return constrainSelectedInstRegOperands(*MI
, TII
, TRI
, RBI
);
285 InstructionSelector
*createMipsInstructionSelector(const MipsTargetMachine
&TM
,
286 MipsSubtarget
&Subtarget
,
287 MipsRegisterBankInfo
&RBI
) {
288 return new MipsInstructionSelector(TM
, Subtarget
, RBI
);
290 } // end namespace llvm