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"
15#include "Mips.h"
16#include "Mips16ISelDAGToDAG.h"
17#include "MipsMachineFunction.h"
18#include "MipsRegisterInfo.h"
19#include "MipsSEISelDAGToDAG.h"
28#include "llvm/IR/CFG.h"
29#include "llvm/IR/GlobalValue.h"
31#include "llvm/IR/Intrinsics.h"
32#include "llvm/IR/Type.h"
33#include "llvm/Support/Debug.h"
38using namespace llvm;
39
40#define DEBUG_TYPE "mips-isel"
41#define PASS_NAME "MIPS DAG->DAG Pattern Instruction Selection"
42
43//===----------------------------------------------------------------------===//
44// Instruction Selector Implementation
45//===----------------------------------------------------------------------===//
46
47//===----------------------------------------------------------------------===//
48// MipsDAGToDAGISel - MIPS specific code to select MIPS machine
49// instructions for SelectionDAG operations.
50//===----------------------------------------------------------------------===//
51
53 // There are multiple MipsDAGToDAGISel instances added to the pass pipeline.
54 // We need to preserve StackProtector for the next one.
57}
58
62
63 processFunctionAfterISel(MF);
64
65 return Ret;
66}
67
68/// getGlobalBaseReg - Output the instructions required to put the
69/// GOT address into a register.
72 return CurDAG->getRegister(GlobalBaseReg, getTargetLowering()->getPointerTy(
74 .getNode();
75}
76
77/// ComplexPattern used on MipsInstrInfo
78/// Used on Mips Load/Store instructions
79bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
80 SDValue &Offset) const {
81 llvm_unreachable("Unimplemented function.");
82 return false;
83}
84
85bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
86 SDValue &Offset) const {
87 llvm_unreachable("Unimplemented function.");
88 return false;
89}
90
91bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
92 SDValue &Offset) const {
93 llvm_unreachable("Unimplemented function.");
94 return false;
95}
96
97bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base,
98 SDValue &Offset) const {
99 llvm_unreachable("Unimplemented function.");
100 return false;
101}
102
103bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base,
104 SDValue &Offset) const {
105 llvm_unreachable("Unimplemented function.");
106 return false;
107}
108
109bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base,
110 SDValue &Offset) const {
111 llvm_unreachable("Unimplemented function.");
112 return false;
113}
114
115bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
116 SDValue &Offset) const {
117 llvm_unreachable("Unimplemented function.");
118 return false;
119}
120
121bool MipsDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base,
122 SDValue &Offset) const {
123 llvm_unreachable("Unimplemented function.");
124 return false;
125}
126
127bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base,
128 SDValue &Offset) const {
129 llvm_unreachable("Unimplemented function.");
130 return false;
131}
132
133bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base,
134 SDValue &Offset) const {
135 llvm_unreachable("Unimplemented function.");
136 return false;
137}
138
139bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base,
140 SDValue &Offset) const {
141 llvm_unreachable("Unimplemented function.");
142 return false;
143}
144
145bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
146 SDValue &Offset) {
147 llvm_unreachable("Unimplemented function.");
148 return false;
149}
150
151bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
152 SDValue &Offset) {
153 llvm_unreachable("Unimplemented function.");
154 return false;
155}
156
157bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm,
158 unsigned MinSizeInBits) const {
159 llvm_unreachable("Unimplemented function.");
160 return false;
161}
162
163bool MipsDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const {
164 llvm_unreachable("Unimplemented function.");
165 return false;
166}
167
168bool MipsDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const {
169 llvm_unreachable("Unimplemented function.");
170 return false;
171}
172
173bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const {
174 llvm_unreachable("Unimplemented function.");
175 return false;
176}
177
178bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const {
179 llvm_unreachable("Unimplemented function.");
180 return false;
181}
182
183bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const {
184 llvm_unreachable("Unimplemented function.");
185 return false;
186}
187
188bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const {
189 llvm_unreachable("Unimplemented function.");
190 return false;
191}
192
193bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const {
194 llvm_unreachable("Unimplemented function.");
195 return false;
196}
197
198bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const {
199 llvm_unreachable("Unimplemented function.");
200 return false;
201}
202
203bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
204 llvm_unreachable("Unimplemented function.");
205 return false;
206}
207
208bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const {
209 llvm_unreachable("Unimplemented function.");
210 return false;
211}
212
213bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
214 llvm_unreachable("Unimplemented function.");
215 return false;
216}
217
218bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
219 llvm_unreachable("Unimplemented function.");
220 return false;
221}
222
223/// Convert vector addition with vector subtraction if that allows to encode
224/// constant as an immediate and thus avoid extra 'ldi' instruction.
225/// add X, <-1, -1...> --> sub X, <1, 1...>
226bool MipsDAGToDAGISel::selectVecAddAsVecSubIfProfitable(SDNode *Node) {
227 assert(Node->getOpcode() == ISD::ADD && "Should only get 'add' here.");
228
229 EVT VT = Node->getValueType(0);
230 assert(VT.isVector() && "Should only be called for vectors.");
231
232 SDValue X = Node->getOperand(0);
233 SDValue C = Node->getOperand(1);
234
235 auto *BVN = dyn_cast<BuildVectorSDNode>(C);
236 if (!BVN)
237 return false;
238
239 APInt SplatValue, SplatUndef;
240 unsigned SplatBitSize;
241 bool HasAnyUndefs;
242
243 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
244 8, !Subtarget->isLittle()))
245 return false;
246
247 auto IsInlineConstant = [](const APInt &Imm) { return Imm.isIntN(5); };
248
249 if (IsInlineConstant(SplatValue))
250 return false; // Can already be encoded as an immediate.
251
252 APInt NegSplatValue = 0 - SplatValue;
253 if (!IsInlineConstant(NegSplatValue))
254 return false; // Even if we negate it it won't help.
255
256 SDLoc DL(Node);
257
259 ISD::SUB, DL, VT, {CurDAG->getConstant(0, DL, VT), C});
260 assert(NegC && "Constant-folding failed!");
261 SDValue NewNode = CurDAG->getNode(ISD::SUB, DL, VT, X, NegC);
262
263 ReplaceNode(Node, NewNode.getNode());
264 SelectCode(NewNode.getNode());
265 return true;
266}
267
268/// Select instructions not customized! Used for
269/// expanded, promoted and normal instructions
270void MipsDAGToDAGISel::Select(SDNode *Node) {
271 unsigned Opcode = Node->getOpcode();
272
273 // If we have a custom node, we already have selected!
274 if (Node->isMachineOpcode()) {
275 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
276 Node->setNodeId(-1);
277 return;
278 }
279
280 // See if subclasses can handle this node.
281 if (trySelect(Node))
282 return;
283
284 switch(Opcode) {
285 default: break;
286
287 case ISD::ADD:
288 if (Node->getSimpleValueType(0).isVector() &&
289 selectVecAddAsVecSubIfProfitable(Node))
290 return;
291 break;
292
293 // Get target GOT address.
296 return;
297
298#ifndef NDEBUG
299 case ISD::LOAD:
300 case ISD::STORE:
302 cast<MemSDNode>(Node)->getAlign() >=
303 cast<MemSDNode>(Node)->getMemoryVT().getStoreSize()) &&
304 "Unexpected unaligned loads/stores.");
305 break;
306#endif
307 }
308
309 // Select the default instruction
310 SelectCode(Node);
311}
312
313bool MipsDAGToDAGISel::SelectInlineAsmMemoryOperand(
314 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
315 std::vector<SDValue> &OutOps) {
316 // All memory constraints can at least accept raw pointers.
317 switch(ConstraintID) {
318 default:
319 llvm_unreachable("Unexpected asm memory constraint");
323 OutOps.push_back(Op);
324 return false;
325 }
326 return true;
327}
328
329bool MipsDAGToDAGISel::isUnneededShiftMask(SDNode *N,
330 unsigned ShAmtBits) const {
331 assert(N->getOpcode() == ISD::AND && "Unexpected opcode");
332
333 const APInt &RHS = N->getConstantOperandAPInt(1);
334 if (RHS.countr_one() >= ShAmtBits) {
336 dbgs()
337 << DEBUG_TYPE
338 << " Need optimize 'and & shl/srl/sra' and operand value bits is "
339 << RHS.countr_one() << "\n");
340 return true;
341 }
342
343 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));
344 return (Known.Zero | RHS).countr_one() >= ShAmtBits;
345}
346
348
350 std::unique_ptr<SelectionDAGISel> S)
352
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Addr
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#define DEBUG_TYPE
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
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
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:487
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getRegister(unsigned Reg, EVT VT)
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:1099
@ GLOBAL_OFFSET_TABLE
The address of the GOT.
Definition: ISDOpcodes.h:93
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:708
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:1856
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