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"
24#include "llvm/IR/CFG.h"
25#include "llvm/IR/GlobalValue.h"
27#include "llvm/IR/Intrinsics.h"
28#include "llvm/IR/Type.h"
29#include "llvm/Support/Debug.h"
33using namespace llvm;
34
35#define DEBUG_TYPE "mips-isel"
36
37bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
39 if (!Subtarget->inMips16Mode())
40 return false;
42}
43/// Select multiply instructions.
44std::pair<SDNode *, SDNode *>
45Mips16DAGToDAGISel::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),
49 N->getOperand(1));
50 SDValue InGlue = SDValue(Mul, 0);
51
52 if (HasLo) {
53 unsigned Opcode = Mips::Mflo16;
54 Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InGlue);
55 InGlue = SDValue(Lo, 1);
56 }
57 if (HasHi) {
58 unsigned Opcode = Mips::Mfhi16;
59 Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InGlue);
60 }
61 return std::make_pair(Lo, Hi);
62}
63
64void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) {
66
67 if (!MipsFI->globalBaseRegSet())
68 return;
69
75 Register V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(MF);
76 const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass;
77
78 V0 = RegInfo.createVirtualRegister(RC);
79 V1 = RegInfo.createVirtualRegister(RC);
80 V2 = RegInfo.createVirtualRegister(RC);
81
82
83 BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0)
85 BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), V1)
87
88 BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16);
89 BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg)
90 .addReg(V1)
91 .addReg(V2);
92}
93
94void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
95 initGlobalBaseReg(MF);
96}
97
98bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base,
99 SDValue &Offset) {
100 SDLoc DL(Addr);
101 EVT ValTy = Addr.getValueType();
102
103 // if Address is FI, get the TargetFrameIndex.
104 if (SPAllowed) {
105 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
106 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
107 Offset = CurDAG->getTargetConstant(0, DL, ValTy);
108 return true;
109 }
110 }
111 // on PIC code Load GA
112 if (Addr.getOpcode() == MipsISD::Wrapper) {
113 Base = Addr.getOperand(0);
114 Offset = Addr.getOperand(1);
115 return true;
116 }
117 if (!TM.isPositionIndependent()) {
118 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
119 Addr.getOpcode() == ISD::TargetGlobalAddress))
120 return false;
121 }
122 // Addresses of the form FI+const or FI|const
124 auto *CN = cast<ConstantSDNode>(Addr.getOperand(1));
125 if (isInt<16>(CN->getSExtValue())) {
126 // If the first operand is a FI, get the TargetFI Node
127 if (SPAllowed) {
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);
132 return true;
133 }
134 }
135
136 Base = Addr.getOperand(0);
137 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy);
138 return true;
139 }
140 }
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)
147 // lwc1 $f0, 0($2)
148 // Generate:
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);
157 Offset = Opnd0;
158 return true;
159 }
160 }
161 }
162 Base = Addr;
163 Offset = CurDAG->getTargetConstant(0, DL, ValTy);
164 return true;
165}
166
167bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
168 SDValue &Offset) {
169 return selectAddr(false, Addr, Base, Offset);
170}
171
172bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
173 SDValue &Offset) {
174 return selectAddr(true, Addr, Base, Offset);
175}
176
177/// Select instructions not customized! Used for
178/// expanded, promoted and normal instructions
179bool Mips16DAGToDAGISel::trySelect(SDNode *Node) {
180 unsigned Opcode = Node->getOpcode();
181 SDLoc DL(Node);
182
183 ///
184 // Instruction Selection not handled by the auto-generated
185 // tablegen selection should be handled here.
186 ///
187 EVT NodeTy = Node->getValueType(0);
188 unsigned MultOpc;
189
190 switch (Opcode) {
191 default:
192 break;
193
194 /// Mul with two results
195 case ISD::SMUL_LOHI:
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));
202
203 if (!SDValue(Node, 1).use_empty())
204 ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0));
205
207 return true;
208 }
209
210 case ISD::MULHS:
211 case ISD::MULHU: {
212 MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy16 : Mips::MultRxRy16);
213 auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, false, true);
214 ReplaceNode(Node, LoHi.second);
215 return true;
216 }
217 }
218
219 return false;
220}
221
224 : MipsDAGToDAGISelLegacy(std::make_unique<Mips16DAGToDAGISel>(TM, OL)) {}
225
227 CodeGenOptLevel OptLevel) {
228 return new Mips16DAGToDAGISelLegacy(TM, OptLevel);
229}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
uint64_t Addr
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
const char LLVMTargetMachineRef TM
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:738
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:687
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:673
@ 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