]>
git.proxmox.com Git - rustc.git/blob - src/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
1 //===-- Mips16ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips16 ----===//
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 // Subclass of MipsDAGToDAGISel specialized for mips16.
12 //===----------------------------------------------------------------------===//
14 #include "Mips16ISelDAGToDAG.h"
15 #include "MCTargetDesc/MipsBaseInfo.h"
17 #include "MipsAnalyzeImmediate.h"
18 #include "MipsMachineFunction.h"
19 #include "MipsRegisterInfo.h"
20 #include "llvm/CodeGen/MachineConstantPool.h"
21 #include "llvm/CodeGen/MachineFrameInfo.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/SelectionDAGNodes.h"
26 #include "llvm/IR/CFG.h"
27 #include "llvm/IR/GlobalValue.h"
28 #include "llvm/IR/Instructions.h"
29 #include "llvm/IR/Intrinsics.h"
30 #include "llvm/IR/Type.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include "llvm/Target/TargetMachine.h"
37 #define DEBUG_TYPE "mips-isel"
39 bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction
&MF
) {
40 Subtarget
= &TM
.getSubtarget
<MipsSubtarget
>();
41 if (!Subtarget
->inMips16Mode())
43 return MipsDAGToDAGISel::runOnMachineFunction(MF
);
45 /// Select multiply instructions.
46 std::pair
<SDNode
*, SDNode
*>
47 Mips16DAGToDAGISel::selectMULT(SDNode
*N
, unsigned Opc
, SDLoc DL
, EVT Ty
,
48 bool HasLo
, bool HasHi
) {
49 SDNode
*Lo
= nullptr, *Hi
= nullptr;
50 SDNode
*Mul
= CurDAG
->getMachineNode(Opc
, DL
, MVT::Glue
, N
->getOperand(0),
52 SDValue InFlag
= SDValue(Mul
, 0);
55 unsigned Opcode
= Mips::Mflo16
;
56 Lo
= CurDAG
->getMachineNode(Opcode
, DL
, Ty
, MVT::Glue
, InFlag
);
57 InFlag
= SDValue(Lo
, 1);
60 unsigned Opcode
= Mips::Mfhi16
;
61 Hi
= CurDAG
->getMachineNode(Opcode
, DL
, Ty
, InFlag
);
63 return std::make_pair(Lo
, Hi
);
66 void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction
&MF
) {
67 MipsFunctionInfo
*MipsFI
= MF
.getInfo
<MipsFunctionInfo
>();
69 if (!MipsFI
->globalBaseRegSet())
72 MachineBasicBlock
&MBB
= MF
.front();
73 MachineBasicBlock::iterator I
= MBB
.begin();
74 MachineRegisterInfo
&RegInfo
= MF
.getRegInfo();
75 const TargetInstrInfo
&TII
= *MF
.getSubtarget().getInstrInfo();
76 DebugLoc DL
= I
!= MBB
.end() ? I
->getDebugLoc() : DebugLoc();
77 unsigned V0
, V1
, V2
, GlobalBaseReg
= MipsFI
->getGlobalBaseReg();
78 const TargetRegisterClass
*RC
= &Mips::CPU16RegsRegClass
;
80 V0
= RegInfo
.createVirtualRegister(RC
);
81 V1
= RegInfo
.createVirtualRegister(RC
);
82 V2
= RegInfo
.createVirtualRegister(RC
);
84 BuildMI(MBB
, I
, DL
, TII
.get(Mips::GotPrologue16
), V0
).
85 addReg(V1
, RegState::Define
).
86 addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI
).
87 addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO
);
89 BuildMI(MBB
, I
, DL
, TII
.get(Mips::SllX16
), V2
).addReg(V0
).addImm(16);
90 BuildMI(MBB
, I
, DL
, TII
.get(Mips::AdduRxRyRz16
), GlobalBaseReg
)
91 .addReg(V1
).addReg(V2
);
94 // Insert instructions to initialize the Mips16 SP Alias register in the
95 // first MBB of the function.
97 void Mips16DAGToDAGISel::initMips16SPAliasReg(MachineFunction
&MF
) {
98 MipsFunctionInfo
*MipsFI
= MF
.getInfo
<MipsFunctionInfo
>();
100 if (!MipsFI
->mips16SPAliasRegSet())
103 MachineBasicBlock
&MBB
= MF
.front();
104 MachineBasicBlock::iterator I
= MBB
.begin();
105 const TargetInstrInfo
&TII
= *MF
.getSubtarget().getInstrInfo();
106 DebugLoc DL
= I
!= MBB
.end() ? I
->getDebugLoc() : DebugLoc();
107 unsigned Mips16SPAliasReg
= MipsFI
->getMips16SPAliasReg();
109 BuildMI(MBB
, I
, DL
, TII
.get(Mips::MoveR3216
), Mips16SPAliasReg
)
113 void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction
&MF
) {
114 initGlobalBaseReg(MF
);
115 initMips16SPAliasReg(MF
);
118 /// getMips16SPAliasReg - Output the instructions required to put the
119 /// SP into a Mips16 accessible aliased register.
120 SDValue
Mips16DAGToDAGISel::getMips16SPAliasReg() {
121 unsigned Mips16SPAliasReg
=
122 MF
->getInfo
<MipsFunctionInfo
>()->getMips16SPAliasReg();
123 return CurDAG
->getRegister(Mips16SPAliasReg
,
124 getTargetLowering()->getPointerTy());
127 void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode
*Parent
, SDValue
&AliasReg
) {
128 SDValue AliasFPReg
= CurDAG
->getRegister(Mips::S0
,
129 getTargetLowering()->getPointerTy());
131 switch (Parent
->getOpcode()) {
133 LoadSDNode
*SD
= dyn_cast
<LoadSDNode
>(Parent
);
134 switch (SD
->getMemoryVT().getSizeInBits()) {
137 AliasReg
= TM
.getSubtargetImpl()->getFrameLowering()->hasFP(*MF
)
139 : getMips16SPAliasReg();
145 StoreSDNode
*SD
= dyn_cast
<StoreSDNode
>(Parent
);
146 switch (SD
->getMemoryVT().getSizeInBits()) {
149 AliasReg
= TM
.getSubtargetImpl()->getFrameLowering()->hasFP(*MF
)
151 : getMips16SPAliasReg();
158 AliasReg
= CurDAG
->getRegister(Mips::SP
, getTargetLowering()->getPointerTy());
163 bool Mips16DAGToDAGISel::selectAddr16(
164 SDNode
*Parent
, SDValue Addr
, SDValue
&Base
, SDValue
&Offset
,
166 EVT ValTy
= Addr
.getValueType();
168 Alias
= CurDAG
->getTargetConstant(0, ValTy
);
170 // if Address is FI, get the TargetFrameIndex.
171 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
172 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), ValTy
);
173 Offset
= CurDAG
->getTargetConstant(0, ValTy
);
174 getMips16SPRefReg(Parent
, Alias
);
177 // on PIC code Load GA
178 if (Addr
.getOpcode() == MipsISD::Wrapper
) {
179 Base
= Addr
.getOperand(0);
180 Offset
= Addr
.getOperand(1);
183 if (TM
.getRelocationModel() != Reloc::PIC_
) {
184 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
185 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
188 // Addresses of the form FI+const or FI|const
189 if (CurDAG
->isBaseWithConstantOffset(Addr
)) {
190 ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1));
191 if (isInt
<16>(CN
->getSExtValue())) {
193 // If the first operand is a FI, get the TargetFI Node
194 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>
195 (Addr
.getOperand(0))) {
196 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), ValTy
);
197 getMips16SPRefReg(Parent
, Alias
);
200 Base
= Addr
.getOperand(0);
202 Offset
= CurDAG
->getTargetConstant(CN
->getZExtValue(), ValTy
);
206 // Operand is a result from an ADD.
207 if (Addr
.getOpcode() == ISD::ADD
) {
208 // When loading from constant pools, load the lower address part in
209 // the instruction itself. Example, instead of:
210 // lui $2, %hi($CPI1_0)
211 // addiu $2, $2, %lo($CPI1_0)
214 // lui $2, %hi($CPI1_0)
215 // lwc1 $f0, %lo($CPI1_0)($2)
216 if (Addr
.getOperand(1).getOpcode() == MipsISD::Lo
||
217 Addr
.getOperand(1).getOpcode() == MipsISD::GPRel
) {
218 SDValue Opnd0
= Addr
.getOperand(1).getOperand(0);
219 if (isa
<ConstantPoolSDNode
>(Opnd0
) || isa
<GlobalAddressSDNode
>(Opnd0
) ||
220 isa
<JumpTableSDNode
>(Opnd0
)) {
221 Base
= Addr
.getOperand(0);
227 // If an indexed floating point load/store can be emitted, return false.
228 const LSBaseSDNode
*LS
= dyn_cast
<LSBaseSDNode
>(Parent
);
231 if (LS
->getMemoryVT() == MVT::f32
&& Subtarget
->hasMips4_32r2())
233 if (LS
->getMemoryVT() == MVT::f64
&& Subtarget
->hasMips4_32r2())
238 Offset
= CurDAG
->getTargetConstant(0, ValTy
);
242 /// Select instructions not customized! Used for
243 /// expanded, promoted and normal instructions
244 std::pair
<bool, SDNode
*> Mips16DAGToDAGISel::selectNode(SDNode
*Node
) {
245 unsigned Opcode
= Node
->getOpcode();
249 // Instruction Selection not handled by the auto-generated
250 // tablegen selection should be handled here.
252 EVT NodeTy
= Node
->getValueType(0);
260 SDValue InFlag
= Node
->getOperand(2), CmpLHS
;
261 unsigned Opc
= InFlag
.getOpcode(); (void)Opc
;
262 assert(((Opc
== ISD::ADDC
|| Opc
== ISD::ADDE
) ||
263 (Opc
== ISD::SUBC
|| Opc
== ISD::SUBE
)) &&
264 "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
267 if (Opcode
== ISD::ADDE
) {
268 CmpLHS
= InFlag
.getValue(0);
269 MOp
= Mips::AdduRxRyRz16
;
271 CmpLHS
= InFlag
.getOperand(0);
272 MOp
= Mips::SubuRxRyRz16
;
275 SDValue Ops
[] = { CmpLHS
, InFlag
.getOperand(1) };
277 SDValue LHS
= Node
->getOperand(0);
278 SDValue RHS
= Node
->getOperand(1);
280 EVT VT
= LHS
.getValueType();
282 unsigned Sltu_op
= Mips::SltuRxRyRz16
;
283 SDNode
*Carry
= CurDAG
->getMachineNode(Sltu_op
, DL
, VT
, Ops
);
284 unsigned Addu_op
= Mips::AdduRxRyRz16
;
285 SDNode
*AddCarry
= CurDAG
->getMachineNode(Addu_op
, DL
, VT
,
286 SDValue(Carry
,0), RHS
);
288 SDNode
*Result
= CurDAG
->SelectNodeTo(Node
, MOp
, VT
, MVT::Glue
, LHS
,
289 SDValue(AddCarry
,0));
290 return std::make_pair(true, Result
);
293 /// Mul with two results
295 case ISD::UMUL_LOHI
: {
296 MultOpc
= (Opcode
== ISD::UMUL_LOHI
? Mips::MultuRxRy16
: Mips::MultRxRy16
);
297 std::pair
<SDNode
*, SDNode
*> LoHi
= selectMULT(Node
, MultOpc
, DL
, NodeTy
,
299 if (!SDValue(Node
, 0).use_empty())
300 ReplaceUses(SDValue(Node
, 0), SDValue(LoHi
.first
, 0));
302 if (!SDValue(Node
, 1).use_empty())
303 ReplaceUses(SDValue(Node
, 1), SDValue(LoHi
.second
, 0));
305 return std::make_pair(true, nullptr);
310 MultOpc
= (Opcode
== ISD::MULHU
? Mips::MultuRxRy16
: Mips::MultRxRy16
);
311 SDNode
*Result
= selectMULT(Node
, MultOpc
, DL
, NodeTy
, false, true).second
;
312 return std::make_pair(true, Result
);
316 return std::make_pair(false, nullptr);
319 FunctionPass
*llvm::createMips16ISelDag(MipsTargetMachine
&TM
) {
320 return new Mips16DAGToDAGISel(TM
);