LLVM 24.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
50 Subtarget = &MF.getSubtarget<MipsSubtarget>();
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.
61 Register GlobalBaseReg = MF->getInfo<MipsFunctionInfo>()->getGlobalBaseReg(*MF);
62 return CurDAG->getRegister(GlobalBaseReg, getTargetLowering()->getPointerTy(
63 CurDAG->getDataLayout()))
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
217 SDValue NegC = CurDAG->FoldConstantArithmetic(
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
228 // The generic DAG combiner folds
229 //
230 // select C, (add $gp, %gp_rel(A)), (add $gp, %gp_rel(B))
231 //
232 // into
233 //
234 // add $gp, (select C, %gp_rel(A), %gp_rel(B)).
235 //
236 // A GP-relative relocation is only selectable as an operand of the add.
237 // Restore the original form before instruction selection so the relocation
238 // is never selected on its own.
239 bool MadeChange = false;
240 for (SDNode &Node : llvm::make_early_inc_range(CurDAG->allnodes())) {
241 if (Node.getOpcode() != ISD::ADD)
242 continue;
243
244 SDValue Base = Node.getOperand(0);
245 SDValue Sel = Node.getOperand(1);
246 if (Base.getOpcode() == ISD::SELECT)
247 std::swap(Base, Sel);
248
250 if (!BaseReg ||
251 (BaseReg->getReg() != Mips::GP && BaseReg->getReg() != Mips::GP_64) ||
252 Sel.getOpcode() != ISD::SELECT)
253 continue;
254
255 SDValue TrueValue = Sel.getOperand(1);
256 SDValue FalseValue = Sel.getOperand(2);
257 if (TrueValue.getOpcode() != MipsISD::GPRel &&
258 FalseValue.getOpcode() != MipsISD::GPRel)
259 continue;
260
261 SDLoc DL(&Node);
262 EVT VT = Node.getValueType(0);
263 SDNodeFlags Flags = Node.getFlags();
264 TrueValue = CurDAG->getNode(ISD::ADD, DL, VT, Base, TrueValue, Flags);
265 FalseValue = CurDAG->getNode(ISD::ADD, DL, VT, Base, FalseValue, Flags);
266 SDValue NewSel =
267 CurDAG->getSelect(DL, VT, Sel.getOperand(0), TrueValue, FalseValue);
268 CurDAG->ReplaceAllUsesOfValueWith(SDValue(&Node, 0), NewSel);
269 MadeChange = true;
270 }
271
272 if (MadeChange)
273 CurDAG->RemoveDeadNodes();
274}
275
276/// Select instructions not customized! Used for
277/// expanded, promoted and normal instructions
278void MipsDAGToDAGISel::Select(SDNode *Node) {
279 unsigned Opcode = Node->getOpcode();
280
281 // If we have a custom node, we already have selected!
282 if (Node->isMachineOpcode()) {
283 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
284 Node->setNodeId(-1);
285 return;
286 }
287
288 // See if subclasses can handle this node.
289 if (trySelect(Node))
290 return;
291
292 switch(Opcode) {
293 default: break;
294
295 case ISD::ADD:
296 if (Node->getSimpleValueType(0).isVector() &&
297 selectVecAddAsVecSubIfProfitable(Node))
298 return;
299 break;
300
301 // Get target GOT address.
304 return;
305
306#ifndef NDEBUG
307 case ISD::LOAD:
308 case ISD::STORE:
309 assert((Subtarget->systemSupportsUnalignedAccess() ||
310 cast<MemSDNode>(Node)->getAlign() >=
311 cast<MemSDNode>(Node)->getMemoryVT().getStoreSize()) &&
312 "Unexpected unaligned loads/stores.");
313 break;
314#endif
315 }
316
317 // Select the default instruction
318 SelectCode(Node);
319}
320
321bool MipsDAGToDAGISel::SelectInlineAsmMemoryOperand(
322 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
323 std::vector<SDValue> &OutOps) {
324 // All memory constraints can at least accept raw pointers.
325 switch(ConstraintID) {
326 default:
327 llvm_unreachable("Unexpected asm memory constraint");
331 OutOps.push_back(Op);
332 return false;
333 }
334 return true;
335}
336
337bool MipsDAGToDAGISel::isUnneededShiftMask(SDNode *N,
338 unsigned ShAmtBits) const {
339 assert(N->getOpcode() == ISD::AND && "Unexpected opcode");
340
341 const APInt &RHS = N->getConstantOperandAPInt(1);
342 if (RHS.countr_one() >= ShAmtBits) {
344 dbgs()
345 << DEBUG_TYPE
346 << " Need optimize 'and & shl/srl/sra' and operand value bits is "
347 << RHS.countr_one() << "\n");
348 return true;
349 }
350
351 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));
352 return (Known.Zero | RHS).countr_one() >= ShAmtBits;
353}
354
356
358 std::unique_ptr<SelectionDAGISel> S)
360
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#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:56
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define PASS_NAME
Value * RHS
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.
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...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
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
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
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
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ GLOBAL_OFFSET_TABLE
The address of the GOT.
Definition ISDOpcodes.h:103
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
@ Known
Known to have no common set bits.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
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:1917
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176