LLVM 20.0.0git
MipsISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- MipsISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips --------===//
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// This file defines an instruction selector for the MIPS target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsISelDAGToDAG.h"
14#include "Mips.h"
15#include "MipsMachineFunction.h"
23#include "llvm/IR/Type.h"
24#include "llvm/Support/Debug.h"
28using namespace llvm;
29
30#define DEBUG_TYPE "mips-isel"
31#define PASS_NAME "MIPS DAG->DAG Pattern Instruction Selection"
32
33//===----------------------------------------------------------------------===//
34// Instruction Selector Implementation
35//===----------------------------------------------------------------------===//
36
37//===----------------------------------------------------------------------===//
38// MipsDAGToDAGISel - MIPS specific code to select MIPS machine
39// instructions for SelectionDAG operations.
40//===----------------------------------------------------------------------===//
41
43 // There are multiple MipsDAGToDAGISel instances added to the pass pipeline.
44 // We need to preserve StackProtector for the next one.
47}
48
52
53 processFunctionAfterISel(MF);
54
55 return Ret;
56}
57
58/// getGlobalBaseReg - Output the instructions required to put the
59/// GOT address into a register.
62 return CurDAG->getRegister(GlobalBaseReg, getTargetLowering()->getPointerTy(
64 .getNode();
65}
66
67/// ComplexPattern used on MipsInstrInfo
68/// Used on Mips Load/Store instructions
69bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
70 SDValue &Offset) const {
71 llvm_unreachable("Unimplemented function.");
72 return false;
73}
74
75bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
76 SDValue &Offset) const {
77 llvm_unreachable("Unimplemented function.");
78 return false;
79}
80
81bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
82 SDValue &Offset) const {
83 llvm_unreachable("Unimplemented function.");
84 return false;
85}
86
87bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base,
88 SDValue &Offset) const {
89 llvm_unreachable("Unimplemented function.");
90 return false;
91}
92
93bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base,
94 SDValue &Offset) const {
95 llvm_unreachable("Unimplemented function.");
96 return false;
97}
98
99bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base,
100 SDValue &Offset) const {
101 llvm_unreachable("Unimplemented function.");
102 return false;
103}
104
105bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
106 SDValue &Offset) const {
107 llvm_unreachable("Unimplemented function.");
108 return false;
109}
110
111bool MipsDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base,
112 SDValue &Offset) const {
113 llvm_unreachable("Unimplemented function.");
114 return false;
115}
116
117bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base,
118 SDValue &Offset) const {
119 llvm_unreachable("Unimplemented function.");
120 return false;
121}
122
123bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base,
124 SDValue &Offset) const {
125 llvm_unreachable("Unimplemented function.");
126 return false;
127}
128
129bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base,
130 SDValue &Offset) const {
131 llvm_unreachable("Unimplemented function.");
132 return false;
133}
134
135bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
136 SDValue &Offset) {
137 llvm_unreachable("Unimplemented function.");
138 return false;
139}
140
141bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
142 SDValue &Offset) {
143 llvm_unreachable("Unimplemented function.");
144 return false;
145}
146
147bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm,
148 unsigned MinSizeInBits) const {
149 llvm_unreachable("Unimplemented function.");
150 return false;
151}
152
153bool MipsDAGToDAGISel::selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed,
154 unsigned ImmBitSize) const {
155 llvm_unreachable("Unimplemented function.");
156}
157
158bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
159 llvm_unreachable("Unimplemented function.");
160 return false;
161}
162
163bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const {
164 llvm_unreachable("Unimplemented function.");
165 return false;
166}
167
168bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
169 llvm_unreachable("Unimplemented function.");
170 return false;
171}
172
173bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
174 llvm_unreachable("Unimplemented function.");
175 return false;
176}
177
178bool MipsDAGToDAGISel::selectVSplatImmEq1(SDValue N) const {
179 llvm_unreachable("Unimplemented function.");
180}
181
182/// Convert vector addition with vector subtraction if that allows to encode
183/// constant as an immediate and thus avoid extra 'ldi' instruction.
184/// add X, <-1, -1...> --> sub X, <1, 1...>
185bool MipsDAGToDAGISel::selectVecAddAsVecSubIfProfitable(SDNode *Node) {
186 assert(Node->getOpcode() == ISD::ADD && "Should only get 'add' here.");
187
188 EVT VT = Node->getValueType(0);
189 assert(VT.isVector() && "Should only be called for vectors.");
190
191 SDValue X = Node->getOperand(0);
192 SDValue C = Node->getOperand(1);
193
194 auto *BVN = dyn_cast<BuildVectorSDNode>(C);
195 if (!BVN)
196 return false;
197
198 APInt SplatValue, SplatUndef;
199 unsigned SplatBitSize;
200 bool HasAnyUndefs;
201
202 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
203 8, !Subtarget->isLittle()))
204 return false;
205
206 auto IsInlineConstant = [](const APInt &Imm) { return Imm.isIntN(5); };
207
208 if (IsInlineConstant(SplatValue))
209 return false; // Can already be encoded as an immediate.
210
211 APInt NegSplatValue = 0 - SplatValue;
212 if (!IsInlineConstant(NegSplatValue))
213 return false; // Even if we negate it it won't help.
214
215 SDLoc DL(Node);
216
218 ISD::SUB, DL, VT, {CurDAG->getConstant(0, DL, VT), C});
219 assert(NegC && "Constant-folding failed!");
220 SDValue NewNode = CurDAG->getNode(ISD::SUB, DL, VT, X, NegC);
221
222 ReplaceNode(Node, NewNode.getNode());
223 SelectCode(NewNode.getNode());
224 return true;
225}
226
227/// Select instructions not customized! Used for
228/// expanded, promoted and normal instructions
229void MipsDAGToDAGISel::Select(SDNode *Node) {
230 unsigned Opcode = Node->getOpcode();
231
232 // If we have a custom node, we already have selected!
233 if (Node->isMachineOpcode()) {
234 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
235 Node->setNodeId(-1);
236 return;
237 }
238
239 // See if subclasses can handle this node.
240 if (trySelect(Node))
241 return;
242
243 switch(Opcode) {
244 default: break;
245
246 case ISD::ADD:
247 if (Node->getSimpleValueType(0).isVector() &&
248 selectVecAddAsVecSubIfProfitable(Node))
249 return;
250 break;
251
252 // Get target GOT address.
255 return;
256
257#ifndef NDEBUG
258 case ISD::LOAD:
259 case ISD::STORE:
261 cast<MemSDNode>(Node)->getAlign() >=
262 cast<MemSDNode>(Node)->getMemoryVT().getStoreSize()) &&
263 "Unexpected unaligned loads/stores.");
264 break;
265#endif
266 }
267
268 // Select the default instruction
269 SelectCode(Node);
270}
271
272bool MipsDAGToDAGISel::SelectInlineAsmMemoryOperand(
273 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
274 std::vector<SDValue> &OutOps) {
275 // All memory constraints can at least accept raw pointers.
276 switch(ConstraintID) {
277 default:
278 llvm_unreachable("Unexpected asm memory constraint");
282 OutOps.push_back(Op);
283 return false;
284 }
285 return true;
286}
287
288bool MipsDAGToDAGISel::isUnneededShiftMask(SDNode *N,
289 unsigned ShAmtBits) const {
290 assert(N->getOpcode() == ISD::AND && "Unexpected opcode");
291
292 const APInt &RHS = N->getConstantOperandAPInt(1);
293 if (RHS.countr_one() >= ShAmtBits) {
295 dbgs()
296 << DEBUG_TYPE
297 << " Need optimize 'and & shl/srl/sra' and operand value bits is "
298 << RHS.countr_one() << "\n");
299 return true;
300 }
301
302 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));
303 return (Known.Zero | RHS).countr_one() >= ShAmtBits;
304}
305
307
309 std::unique_ptr<SelectionDAGISel> S)
311
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DEBUG(...)
Definition: Debug.h:106
uint64_t Addr
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#define DEBUG_TYPE
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define PASS_NAME
Value * RHS
DEMANGLE_DUMP_METHOD void dump() const
Class for arbitrary precision integers.
Definition: APInt.h:78
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class represents an Operation in the Expression.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MipsDAGToDAGISelLegacy(std::unique_ptr< SelectionDAGISel > S)
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...
SDNode * getGlobalBaseReg()
getGlobalBaseReg - Output the instructions required to put the GOT address into a register.
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
bool isLittle() const
bool systemSupportsUnalignedAccess() const
Does the system support unaligned memory access.
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.
SDNode * getNode() const
get the SDNode which holds the desired result
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineFunction * MF
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
virtual bool runOnMachineFunction(MachineFunction &mf)
const TargetLowering * getTargetLowering() const
SDValue getRegister(Register Reg, EVT VT)
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:495
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:1102
@ GLOBAL_OFFSET_TABLE
The address of the GOT.
Definition: ISDOpcodes.h:93
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:709
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1873
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
bool isVector() const
Return true if this is a vector value type.
Definition: ValueTypes.h:168