1 //===-- Mips16ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips16 ----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Subclass of MipsDAGToDAGISel specialized for mips16.
11 //===----------------------------------------------------------------------===//
13 #include "Mips16ISelDAGToDAG.h"
14 #include "MCTargetDesc/MipsBaseInfo.h"
16 #include "MipsMachineFunction.h"
17 #include "MipsRegisterInfo.h"
18 #include "llvm/CodeGen/MachineConstantPool.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/CodeGen/SelectionDAGNodes.h"
24 #include "llvm/IR/CFG.h"
25 #include "llvm/IR/GlobalValue.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/Intrinsics.h"
28 #include "llvm/IR/Type.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Target/TargetMachine.h"
35 #define DEBUG_TYPE "mips-isel"
37 bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction
&MF
) {
38 Subtarget
= &static_cast<const MipsSubtarget
&>(MF
.getSubtarget());
39 if (!Subtarget
->inMips16Mode())
41 return MipsDAGToDAGISel::runOnMachineFunction(MF
);
43 /// Select multiply instructions.
44 std::pair
<SDNode
*, SDNode
*>
45 Mips16DAGToDAGISel::selectMULT(SDNode
*N
, unsigned Opc
, const SDLoc
&DL
, EVT Ty
,
46 bool HasLo
, bool HasHi
) {
47 SDNode
*Lo
= nullptr, *Hi
= nullptr;
48 SDNode
*Mul
= CurDAG
->getMachineNode(Opc
, DL
, MVT::Glue
, N
->getOperand(0),
50 SDValue InFlag
= SDValue(Mul
, 0);
53 unsigned Opcode
= Mips::Mflo16
;
54 Lo
= CurDAG
->getMachineNode(Opcode
, DL
, Ty
, MVT::Glue
, InFlag
);
55 InFlag
= SDValue(Lo
, 1);
58 unsigned Opcode
= Mips::Mfhi16
;
59 Hi
= CurDAG
->getMachineNode(Opcode
, DL
, Ty
, InFlag
);
61 return std::make_pair(Lo
, Hi
);
64 void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction
&MF
) {
65 MipsFunctionInfo
*MipsFI
= MF
.getInfo
<MipsFunctionInfo
>();
67 if (!MipsFI
->globalBaseRegSet())
70 MachineBasicBlock
&MBB
= MF
.front();
71 MachineBasicBlock::iterator I
= MBB
.begin();
72 MachineRegisterInfo
&RegInfo
= MF
.getRegInfo();
73 const TargetInstrInfo
&TII
= *Subtarget
->getInstrInfo();
75 Register V0
, V1
, V2
, GlobalBaseReg
= MipsFI
->getGlobalBaseReg();
76 const TargetRegisterClass
*RC
= &Mips::CPU16RegsRegClass
;
78 V0
= RegInfo
.createVirtualRegister(RC
);
79 V1
= RegInfo
.createVirtualRegister(RC
);
80 V2
= RegInfo
.createVirtualRegister(RC
);
83 BuildMI(MBB
, I
, DL
, TII
.get(Mips::LiRxImmX16
), V0
)
84 .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI
);
85 BuildMI(MBB
, I
, DL
, TII
.get(Mips::AddiuRxPcImmX16
), V1
)
86 .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO
);
88 BuildMI(MBB
, I
, DL
, TII
.get(Mips::SllX16
), V2
).addReg(V0
).addImm(16);
89 BuildMI(MBB
, I
, DL
, TII
.get(Mips::AdduRxRyRz16
), GlobalBaseReg
)
94 void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction
&MF
) {
95 initGlobalBaseReg(MF
);
98 bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed
, SDValue Addr
, SDValue
&Base
,
101 EVT ValTy
= Addr
.getValueType();
103 // if Address is FI, get the TargetFrameIndex.
105 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
106 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), ValTy
);
107 Offset
= CurDAG
->getTargetConstant(0, DL
, ValTy
);
111 // on PIC code Load GA
112 if (Addr
.getOpcode() == MipsISD::Wrapper
) {
113 Base
= Addr
.getOperand(0);
114 Offset
= Addr
.getOperand(1);
117 if (!TM
.isPositionIndependent()) {
118 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
119 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
122 // Addresses of the form FI+const or FI|const
123 if (CurDAG
->isBaseWithConstantOffset(Addr
)) {
124 ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1));
125 if (isInt
<16>(CN
->getSExtValue())) {
126 // If the first operand is a FI, get the TargetFI Node
128 if (FrameIndexSDNode
*FIN
=
129 dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0))) {
130 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), ValTy
);
131 Offset
= CurDAG
->getTargetConstant(CN
->getZExtValue(), DL
, ValTy
);
136 Base
= Addr
.getOperand(0);
137 Offset
= CurDAG
->getTargetConstant(CN
->getZExtValue(), DL
, ValTy
);
141 // Operand is a result from an ADD.
142 if (Addr
.getOpcode() == ISD::ADD
) {
143 // When loading from constant pools, load the lower address part in
144 // the instruction itself. Example, instead of:
145 // lui $2, %hi($CPI1_0)
146 // addiu $2, $2, %lo($CPI1_0)
149 // lui $2, %hi($CPI1_0)
150 // lwc1 $f0, %lo($CPI1_0)($2)
151 if (Addr
.getOperand(1).getOpcode() == MipsISD::Lo
||
152 Addr
.getOperand(1).getOpcode() == MipsISD::GPRel
) {
153 SDValue Opnd0
= Addr
.getOperand(1).getOperand(0);
154 if (isa
<ConstantPoolSDNode
>(Opnd0
) || isa
<GlobalAddressSDNode
>(Opnd0
) ||
155 isa
<JumpTableSDNode
>(Opnd0
)) {
156 Base
= Addr
.getOperand(0);
163 Offset
= CurDAG
->getTargetConstant(0, DL
, ValTy
);
167 bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr
, SDValue
&Base
,
169 return selectAddr(false, Addr
, Base
, Offset
);
172 bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr
, SDValue
&Base
,
174 return selectAddr(true, Addr
, Base
, Offset
);
177 /// Select instructions not customized! Used for
178 /// expanded, promoted and normal instructions
179 bool Mips16DAGToDAGISel::trySelect(SDNode
*Node
) {
180 unsigned Opcode
= Node
->getOpcode();
184 // Instruction Selection not handled by the auto-generated
185 // tablegen selection should be handled here.
187 EVT NodeTy
= Node
->getValueType(0);
194 /// Mul with two results
196 case ISD::UMUL_LOHI
: {
197 MultOpc
= (Opcode
== ISD::UMUL_LOHI
? Mips::MultuRxRy16
: Mips::MultRxRy16
);
198 std::pair
<SDNode
*, SDNode
*> LoHi
=
199 selectMULT(Node
, MultOpc
, DL
, NodeTy
, true, true);
200 if (!SDValue(Node
, 0).use_empty())
201 ReplaceUses(SDValue(Node
, 0), SDValue(LoHi
.first
, 0));
203 if (!SDValue(Node
, 1).use_empty())
204 ReplaceUses(SDValue(Node
, 1), SDValue(LoHi
.second
, 0));
206 CurDAG
->RemoveDeadNode(Node
);
212 MultOpc
= (Opcode
== ISD::MULHU
? Mips::MultuRxRy16
: Mips::MultRxRy16
);
213 auto LoHi
= selectMULT(Node
, MultOpc
, DL
, NodeTy
, false, true);
214 ReplaceNode(Node
, LoHi
.second
);
222 FunctionPass
*llvm::createMips16ISelDag(MipsTargetMachine
&TM
,
223 CodeGenOpt::Level OptLevel
) {
224 return new Mips16DAGToDAGISel(TM
, OptLevel
);