LLVM 20.0.0git
Mips16ISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- Mips16ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips16 ----===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// Subclass of MipsDAGToDAGISel specialized for mips16.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Mips16ISelDAGToDAG.h"
15#include "Mips.h"
16#include "MipsMachineFunction.h"
17#include "MipsRegisterInfo.h"
24using namespace llvm;
25
26#define DEBUG_TYPE "mips-isel"
27
28bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
30 if (!Subtarget->inMips16Mode())
31 return false;
33}
34/// Select multiply instructions.
35std::pair<SDNode *, SDNode *>
36Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, const SDLoc &DL, EVT Ty,
37 bool HasLo, bool HasHi) {
38 SDNode *Lo = nullptr, *Hi = nullptr;
39 SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0),
40 N->getOperand(1));
41 SDValue InGlue = SDValue(Mul, 0);
42
43 if (HasLo) {
44 unsigned Opcode = Mips::Mflo16;
45 Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InGlue);
46 InGlue = SDValue(Lo, 1);
47 }
48 if (HasHi) {
49 unsigned Opcode = Mips::Mfhi16;
50 Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InGlue);
51 }
52 return std::make_pair(Lo, Hi);
53}
54
55void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) {
57
58 if (!MipsFI->globalBaseRegSet())
59 return;
60
66 Register V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(MF);
67 const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass;
68
69 V0 = RegInfo.createVirtualRegister(RC);
70 V1 = RegInfo.createVirtualRegister(RC);
71 V2 = RegInfo.createVirtualRegister(RC);
72
73
74 BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0)
76 BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), V1)
78
79 BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16);
80 BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg)
81 .addReg(V1)
82 .addReg(V2);
83}
84
85void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
86 initGlobalBaseReg(MF);
87}
88
89bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base,
90 SDValue &Offset) {
91 SDLoc DL(Addr);
92 EVT ValTy = Addr.getValueType();
93
94 // if Address is FI, get the TargetFrameIndex.
95 if (SPAllowed) {
96 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
97 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
98 Offset = CurDAG->getTargetConstant(0, DL, ValTy);
99 return true;
100 }
101 }
102 // on PIC code Load GA
103 if (Addr.getOpcode() == MipsISD::Wrapper) {
104 Base = Addr.getOperand(0);
105 Offset = Addr.getOperand(1);
106 return true;
107 }
108 if (!TM.isPositionIndependent()) {
109 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
110 Addr.getOpcode() == ISD::TargetGlobalAddress))
111 return false;
112 }
113 // Addresses of the form FI+const or FI|const
115 auto *CN = cast<ConstantSDNode>(Addr.getOperand(1));
116 if (isInt<16>(CN->getSExtValue())) {
117 // If the first operand is a FI, get the TargetFI Node
118 if (SPAllowed) {
119 if (FrameIndexSDNode *FIN =
120 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
121 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
122 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy);
123 return true;
124 }
125 }
126
127 Base = Addr.getOperand(0);
128 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy);
129 return true;
130 }
131 }
132 // Operand is a result from an ADD.
133 if (Addr.getOpcode() == ISD::ADD) {
134 // When loading from constant pools, load the lower address part in
135 // the instruction itself. Example, instead of:
136 // lui $2, %hi($CPI1_0)
137 // addiu $2, $2, %lo($CPI1_0)
138 // lwc1 $f0, 0($2)
139 // Generate:
140 // lui $2, %hi($CPI1_0)
141 // lwc1 $f0, %lo($CPI1_0)($2)
142 if (Addr.getOperand(1).getOpcode() == MipsISD::Lo ||
143 Addr.getOperand(1).getOpcode() == MipsISD::GPRel) {
144 SDValue Opnd0 = Addr.getOperand(1).getOperand(0);
145 if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) ||
146 isa<JumpTableSDNode>(Opnd0)) {
147 Base = Addr.getOperand(0);
148 Offset = Opnd0;
149 return true;
150 }
151 }
152 }
153 Base = Addr;
154 Offset = CurDAG->getTargetConstant(0, DL, ValTy);
155 return true;
156}
157
158bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
159 SDValue &Offset) {
160 return selectAddr(false, Addr, Base, Offset);
161}
162
163bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
164 SDValue &Offset) {
165 return selectAddr(true, Addr, Base, Offset);
166}
167
168/// Select instructions not customized! Used for
169/// expanded, promoted and normal instructions
170bool Mips16DAGToDAGISel::trySelect(SDNode *Node) {
171 unsigned Opcode = Node->getOpcode();
172 SDLoc DL(Node);
173
174 ///
175 // Instruction Selection not handled by the auto-generated
176 // tablegen selection should be handled here.
177 ///
178 EVT NodeTy = Node->getValueType(0);
179 unsigned MultOpc;
180
181 switch (Opcode) {
182 default:
183 break;
184
185 /// Mul with two results
186 case ISD::SMUL_LOHI:
187 case ISD::UMUL_LOHI: {
188 MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 : Mips::MultRxRy16);
189 std::pair<SDNode *, SDNode *> LoHi =
190 selectMULT(Node, MultOpc, DL, NodeTy, true, true);
191 if (!SDValue(Node, 0).use_empty())
192 ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0));
193
194 if (!SDValue(Node, 1).use_empty())
195 ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0));
196
198 return true;
199 }
200
201 case ISD::MULHS:
202 case ISD::MULHU: {
203 MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy16 : Mips::MultRxRy16);
204 auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, false, true);
205 ReplaceNode(Node, LoHi.second);
206 return true;
207 }
208 }
209
210 return false;
211}
212
215 : MipsDAGToDAGISelLegacy(std::make_unique<Mips16DAGToDAGISel>(TM, OL)) {}
216
218 CodeGenOptLevel OptLevel) {
219 return new Mips16DAGToDAGISelLegacy(TM, OptLevel);
220}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
uint64_t Addr
#define I(x, y, z)
Definition: MD5.cpp:58
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Mips16DAGToDAGISelLegacy(MipsTargetMachine &TM, CodeGenOptLevel OL)
bool runOnMachineFunction(MachineFunction &MF) override
const MipsSubtarget * Subtarget
Keep a pointer to the MipsSubtarget around so that we can make the right decision when generating cod...
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
Register getGlobalBaseReg(MachineFunction &MF)
const MipsInstrInfo * getInstrInfo() const override
bool inMips16Mode() const
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
MachineFunction * MF
const TargetInstrInfo * TII
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDValue getTargetFrameIndex(int FI, EVT VT)
Definition: SelectionDAG.h:753
void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:698
bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
TargetInstrInfo - Interface to description of machine instruction set.
bool isPositionIndependent() const
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition: ISDOpcodes.h:257
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ TargetExternalSymbol
Definition: ISDOpcodes.h:175
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:170
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:674
@ MO_ABS_HI
MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol address.
Definition: MipsBaseInfo.h:52
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
@ Mul
Product of integers.
FunctionPass * createMips16ISelDag(MipsTargetMachine &TM, CodeGenOptLevel OptLevel)
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define N
Extended Value Type.
Definition: ValueTypes.h:35