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 "MipsMachineFunction.h"
18 #include "MipsRegisterInfo.h"
19 #include "llvm/CodeGen/MachineConstantPool.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineRegisterInfo.h"
24 #include "llvm/CodeGen/SelectionDAGNodes.h"
25 #include "llvm/IR/CFG.h"
26 #include "llvm/IR/GlobalValue.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/IR/Intrinsics.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include "llvm/Target/TargetMachine.h"
36 #define DEBUG_TYPE "mips-isel"
38 bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction
&MF
) {
39 Subtarget
= &static_cast<const MipsSubtarget
&>(MF
.getSubtarget());
40 if (!Subtarget
->inMips16Mode())
42 return MipsDAGToDAGISel::runOnMachineFunction(MF
);
44 /// Select multiply instructions.
45 std::pair
<SDNode
*, SDNode
*>
46 Mips16DAGToDAGISel::selectMULT(SDNode
*N
, unsigned Opc
, const SDLoc
&DL
, EVT Ty
,
47 bool HasLo
, bool HasHi
) {
48 SDNode
*Lo
= nullptr, *Hi
= nullptr;
49 SDNode
*Mul
= CurDAG
->getMachineNode(Opc
, DL
, MVT::Glue
, N
->getOperand(0),
51 SDValue InFlag
= SDValue(Mul
, 0);
54 unsigned Opcode
= Mips::Mflo16
;
55 Lo
= CurDAG
->getMachineNode(Opcode
, DL
, Ty
, MVT::Glue
, InFlag
);
56 InFlag
= SDValue(Lo
, 1);
59 unsigned Opcode
= Mips::Mfhi16
;
60 Hi
= CurDAG
->getMachineNode(Opcode
, DL
, Ty
, InFlag
);
62 return std::make_pair(Lo
, Hi
);
65 void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction
&MF
) {
66 MipsFunctionInfo
*MipsFI
= MF
.getInfo
<MipsFunctionInfo
>();
68 if (!MipsFI
->globalBaseRegSet())
71 MachineBasicBlock
&MBB
= MF
.front();
72 MachineBasicBlock::iterator I
= MBB
.begin();
73 MachineRegisterInfo
&RegInfo
= MF
.getRegInfo();
74 const TargetInstrInfo
&TII
= *Subtarget
->getInstrInfo();
76 unsigned V0
, V1
, V2
, GlobalBaseReg
= MipsFI
->getGlobalBaseReg();
77 const TargetRegisterClass
*RC
= &Mips::CPU16RegsRegClass
;
79 V0
= RegInfo
.createVirtualRegister(RC
);
80 V1
= RegInfo
.createVirtualRegister(RC
);
81 V2
= RegInfo
.createVirtualRegister(RC
);
84 BuildMI(MBB
, I
, DL
, TII
.get(Mips::LiRxImmX16
), V0
)
85 .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI
);
86 BuildMI(MBB
, I
, DL
, TII
.get(Mips::AddiuRxPcImmX16
), V1
)
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
)
95 void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction
&MF
) {
96 initGlobalBaseReg(MF
);
99 bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed
, SDValue Addr
, SDValue
&Base
,
102 EVT ValTy
= Addr
.getValueType();
104 // if Address is FI, get the TargetFrameIndex.
106 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
107 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), ValTy
);
108 Offset
= CurDAG
->getTargetConstant(0, DL
, ValTy
);
112 // on PIC code Load GA
113 if (Addr
.getOpcode() == MipsISD::Wrapper
) {
114 Base
= Addr
.getOperand(0);
115 Offset
= Addr
.getOperand(1);
118 if (!TM
.isPositionIndependent()) {
119 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
120 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
123 // Addresses of the form FI+const or FI|const
124 if (CurDAG
->isBaseWithConstantOffset(Addr
)) {
125 ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1));
126 if (isInt
<16>(CN
->getSExtValue())) {
127 // If the first operand is a FI, get the TargetFI Node
129 if (FrameIndexSDNode
*FIN
=
130 dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0))) {
131 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), ValTy
);
132 Offset
= CurDAG
->getTargetConstant(CN
->getZExtValue(), DL
, ValTy
);
137 Base
= Addr
.getOperand(0);
138 Offset
= CurDAG
->getTargetConstant(CN
->getZExtValue(), DL
, ValTy
);
142 // Operand is a result from an ADD.
143 if (Addr
.getOpcode() == ISD::ADD
) {
144 // When loading from constant pools, load the lower address part in
145 // the instruction itself. Example, instead of:
146 // lui $2, %hi($CPI1_0)
147 // addiu $2, $2, %lo($CPI1_0)
150 // lui $2, %hi($CPI1_0)
151 // lwc1 $f0, %lo($CPI1_0)($2)
152 if (Addr
.getOperand(1).getOpcode() == MipsISD::Lo
||
153 Addr
.getOperand(1).getOpcode() == MipsISD::GPRel
) {
154 SDValue Opnd0
= Addr
.getOperand(1).getOperand(0);
155 if (isa
<ConstantPoolSDNode
>(Opnd0
) || isa
<GlobalAddressSDNode
>(Opnd0
) ||
156 isa
<JumpTableSDNode
>(Opnd0
)) {
157 Base
= Addr
.getOperand(0);
164 Offset
= CurDAG
->getTargetConstant(0, DL
, ValTy
);
168 bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr
, SDValue
&Base
,
170 return selectAddr(false, Addr
, Base
, Offset
);
173 bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr
, SDValue
&Base
,
175 return selectAddr(true, Addr
, Base
, Offset
);
178 /// Select instructions not customized! Used for
179 /// expanded, promoted and normal instructions
180 bool Mips16DAGToDAGISel::trySelect(SDNode
*Node
) {
181 unsigned Opcode
= Node
->getOpcode();
185 // Instruction Selection not handled by the auto-generated
186 // tablegen selection should be handled here.
188 EVT NodeTy
= Node
->getValueType(0);
195 /// Mul with two results
197 case ISD::UMUL_LOHI
: {
198 MultOpc
= (Opcode
== ISD::UMUL_LOHI
? Mips::MultuRxRy16
: Mips::MultRxRy16
);
199 std::pair
<SDNode
*, SDNode
*> LoHi
=
200 selectMULT(Node
, MultOpc
, DL
, NodeTy
, true, true);
201 if (!SDValue(Node
, 0).use_empty())
202 ReplaceUses(SDValue(Node
, 0), SDValue(LoHi
.first
, 0));
204 if (!SDValue(Node
, 1).use_empty())
205 ReplaceUses(SDValue(Node
, 1), SDValue(LoHi
.second
, 0));
207 CurDAG
->RemoveDeadNode(Node
);
213 MultOpc
= (Opcode
== ISD::MULHU
? Mips::MultuRxRy16
: Mips::MultRxRy16
);
214 auto LoHi
= selectMULT(Node
, MultOpc
, DL
, NodeTy
, false, true);
215 ReplaceNode(Node
, LoHi
.second
);
223 FunctionPass
*llvm::createMips16ISelDag(MipsTargetMachine
&TM
,
224 CodeGenOpt::Level OptLevel
) {
225 return new Mips16DAGToDAGISel(TM
, OptLevel
);