LLVM 22.0.0git
SelectionDAGAddressAnalysis.cpp
Go to the documentation of this file.
1//==- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp - DAG Address Analysis --==//
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
17#include "llvm/IR/GlobalAlias.h"
19#include "llvm/Support/Debug.h"
20#include <cstdint>
21
22using namespace llvm;
23
25 const SelectionDAG &DAG,
26 int64_t &Off) const {
27 // Conservatively fail if we a match failed..
28 if (!Base.getNode() || !Other.Base.getNode())
29 return false;
30 if (!hasValidOffset() || !Other.hasValidOffset())
31 return false;
32 // Initial Offset difference.
33 Off = *Other.Offset - *Offset;
34
35 if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
36 // Trivial match.
37 if (Other.Base == Base)
38 return true;
39
40 // Match GlobalAddresses
41 if (auto *A = dyn_cast<GlobalAddressSDNode>(Base)) {
42 if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
43 if (A->getGlobal() == B->getGlobal()) {
44 Off += B->getOffset() - A->getOffset();
45 return true;
46 }
47
48 return false;
49 }
50
51 // Match Constants
52 if (auto *A = dyn_cast<ConstantPoolSDNode>(Base)) {
53 if (auto *B = dyn_cast<ConstantPoolSDNode>(Other.Base)) {
54 bool IsMatch =
55 A->isMachineConstantPoolEntry() == B->isMachineConstantPoolEntry();
56 if (IsMatch) {
57 if (A->isMachineConstantPoolEntry())
58 IsMatch = A->getMachineCPVal() == B->getMachineCPVal();
59 else
60 IsMatch = A->getConstVal() == B->getConstVal();
61 }
62 if (IsMatch) {
63 Off += B->getOffset() - A->getOffset();
64 return true;
65 }
66 }
67
68 return false;
69 }
70
71 // Match FrameIndexes.
72 if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
73 if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base)) {
74 // Equal FrameIndexes - offsets are directly comparable.
75 if (A->getIndex() == B->getIndex())
76 return true;
77 // Non-equal FrameIndexes - If both frame indices are fixed
78 // we know their relative offsets and can compare them. Otherwise
79 // we must be conservative.
81 if (MFI.isFixedObjectIndex(A->getIndex()) &&
82 MFI.isFixedObjectIndex(B->getIndex())) {
83 Off += MFI.getObjectOffset(B->getIndex()) -
84 MFI.getObjectOffset(A->getIndex());
85 return true;
86 }
87 }
88 }
89
90 return false;
91}
92
94 const LocationSize NumBytes0,
95 const SDNode *Op1,
96 const LocationSize NumBytes1,
97 const SelectionDAG &DAG, bool &IsAlias) {
98 BaseIndexOffset BasePtr0 = match(Op0, DAG);
99 if (!BasePtr0.getBase().getNode())
100 return false;
101
102 BaseIndexOffset BasePtr1 = match(Op1, DAG);
103 if (!BasePtr1.getBase().getNode())
104 return false;
105
106 int64_t PtrDiff;
107 if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) {
108 // If the size of memory access is unknown, do not use it to analysis.
109 // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the
110 // following situations arise:
111 if (PtrDiff >= 0 && NumBytes0.hasValue() && !NumBytes0.isScalable()) {
112 // [----BasePtr0----]
113 // [---BasePtr1--]
114 // ========PtrDiff========>
115 IsAlias = !(static_cast<int64_t>(NumBytes0.getValue().getFixedValue()) <=
116 PtrDiff);
117 return true;
118 }
119 if (PtrDiff < 0 && NumBytes1.hasValue() && !NumBytes1.isScalable()) {
120 // [----BasePtr0----]
121 // [---BasePtr1--]
122 // =====(-PtrDiff)====>
123 IsAlias = !((PtrDiff + static_cast<int64_t>(
124 NumBytes1.getValue().getFixedValue())) <= 0);
125 return true;
126 }
127 return false;
128 }
129 // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be
130 // able to calculate their relative offset if at least one arises
131 // from an alloca. However, these allocas cannot overlap and we
132 // can infer there is no alias.
133 if (auto *A = dyn_cast<FrameIndexSDNode>(BasePtr0.getBase()))
134 if (auto *B = dyn_cast<FrameIndexSDNode>(BasePtr1.getBase())) {
136 // If the base are the same frame index but the we couldn't find a
137 // constant offset, (indices are different) be conservative.
138 if (A->getIndex() != B->getIndex() && (!MFI.isFixedObjectIndex(A->getIndex()) ||
139 !MFI.isFixedObjectIndex(B->getIndex()))) {
140 IsAlias = false;
141 return true;
142 }
143 }
144
145 bool IsFI0 = isa<FrameIndexSDNode>(BasePtr0.getBase());
146 bool IsFI1 = isa<FrameIndexSDNode>(BasePtr1.getBase());
147 bool IsGV0 = isa<GlobalAddressSDNode>(BasePtr0.getBase());
148 bool IsGV1 = isa<GlobalAddressSDNode>(BasePtr1.getBase());
149 bool IsCV0 = isa<ConstantPoolSDNode>(BasePtr0.getBase());
150 bool IsCV1 = isa<ConstantPoolSDNode>(BasePtr1.getBase());
151
152 if ((IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) {
153 // We can derive NoAlias In case of mismatched base types.
154 if (IsFI0 != IsFI1 || IsGV0 != IsGV1 || IsCV0 != IsCV1) {
155 IsAlias = false;
156 return true;
157 }
158 if (IsGV0 && IsGV1) {
159 auto *GV0 = cast<GlobalAddressSDNode>(BasePtr0.getBase())->getGlobal();
160 auto *GV1 = cast<GlobalAddressSDNode>(BasePtr1.getBase())->getGlobal();
161 // It doesn't make sense to access one global value using another globals
162 // values address, so we can assume that there is no aliasing in case of
163 // two different globals (unless we have symbols that may indirectly point
164 // to each other).
165 // FIXME: This is perhaps a bit too defensive. We could try to follow the
166 // chain with aliasee information for GlobalAlias variables to find out if
167 // we indirect symbols may alias or not.
168 if (GV0 != GV1 && !isa<GlobalAlias>(GV0) && !isa<GlobalAlias>(GV1)) {
169 IsAlias = false;
170 return true;
171 }
172 }
173 }
174 return false; // Cannot determine whether the pointers alias.
175}
176
177bool BaseIndexOffset::contains(const SelectionDAG &DAG, int64_t BitSize,
178 const BaseIndexOffset &Other,
179 int64_t OtherBitSize, int64_t &BitOffset) const {
180 int64_t Offset;
181 if (!equalBaseIndex(Other, DAG, Offset))
182 return false;
183 if (Offset >= 0) {
184 // Other is after *this:
185 // [-------*this---------]
186 // [---Other--]
187 // ==Offset==>
188 BitOffset = 8 * Offset;
189 return BitOffset + OtherBitSize <= BitSize;
190 }
191 // Other starts strictly before *this, it cannot be fully contained.
192 // [-------*this---------]
193 // [--Other--]
194 return false;
195}
196
197/// Parses tree in Ptr for base, index, offset addresses.
199 const SelectionDAG &DAG) {
200 SDValue Ptr = N->getBasePtr();
201
202 // (((B + I*M) + c)) + c ...
204 SDValue Index = SDValue();
205 int64_t Offset = 0;
206 bool IsIndexSignExt = false;
207
208 // pre-inc/pre-dec ops are components of EA.
209 if (N->getAddressingMode() == ISD::PRE_INC) {
210 if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
211 Offset += C->getSExtValue();
212 else // If unknown, give up now.
213 return BaseIndexOffset(SDValue(), SDValue(), 0, false);
214 } else if (N->getAddressingMode() == ISD::PRE_DEC) {
215 if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
216 Offset -= C->getSExtValue();
217 else // If unknown, give up now.
218 return BaseIndexOffset(SDValue(), SDValue(), 0, false);
219 }
220
221 // Consume constant adds & ors with appropriate masking.
222 while (true) {
223 switch (Base->getOpcode()) {
224 case ISD::OR:
225 // Only consider ORs which act as adds.
226 if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1)))
227 if (DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue())) {
228 Offset += C->getSExtValue();
229 Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
230 continue;
231 }
232 break;
233 case ISD::ADD:
234 case ISD::PTRADD:
235 if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
236 Offset += C->getSExtValue();
237 Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
238 continue;
239 }
240 break;
241 case ISD::LOAD:
242 case ISD::STORE: {
243 auto *LSBase = cast<LSBaseSDNode>(Base.getNode());
244 unsigned int IndexResNo = (Base->getOpcode() == ISD::LOAD) ? 1 : 0;
245 if (LSBase->isIndexed() && Base.getResNo() == IndexResNo)
246 if (auto *C = dyn_cast<ConstantSDNode>(LSBase->getOffset())) {
247 auto Off = C->getSExtValue();
248 if (LSBase->getAddressingMode() == ISD::PRE_DEC ||
249 LSBase->getAddressingMode() == ISD::POST_DEC)
250 Offset -= Off;
251 else
252 Offset += Off;
253 Base = DAG.getTargetLoweringInfo().unwrapAddress(LSBase->getBasePtr());
254 continue;
255 }
256 break;
257 }
258 }
259 // If we get here break out of the loop.
260 break;
261 }
262
263 if (Base->isAnyAdd()) {
264 // TODO: The following code appears to be needless as it just
265 // bails on some Ptrs early, reducing the cases where we
266 // find equivalence. We should be able to remove this.
267 // Inside a loop the current BASE pointer is calculated using an ADD and a
268 // MUL instruction. In this case Base is the actual BASE pointer.
269 // (i64 add (i64 %array_ptr)
270 // (i64 mul (i64 %induction_var)
271 // (i64 %element_size)))
272 if (Base->getOperand(1)->getOpcode() == ISD::MUL)
273 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
274
275 // Look at Base + Index + Offset cases.
276 Index = Base->getOperand(1);
277 SDValue PotentialBase = Base->getOperand(0);
278
279 // Skip signextends.
280 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
281 Index = Index->getOperand(0);
282 IsIndexSignExt = true;
283 }
284
285 // Check if Index Offset pattern
286 if (!Index->isAnyAdd() || !isa<ConstantSDNode>(Index->getOperand(1)))
287 return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
288
289 Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
290 Index = Index->getOperand(0);
291 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
292 Index = Index->getOperand(0);
293 IsIndexSignExt = true;
294 } else
295 IsIndexSignExt = false;
296 Base = PotentialBase;
297 }
298 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
299}
300
302 const SelectionDAG &DAG) {
303 if (const auto *LS0 = dyn_cast<LSBaseSDNode>(N))
304 return matchLSNode(LS0, DAG);
305 if (const auto *LN = dyn_cast<LifetimeSDNode>(N)) {
306 return BaseIndexOffset(LN->getOperand(1), SDValue(), 0, false);
307 }
308 return BaseIndexOffset();
309}
310
311#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
312
316
318 OS << "BaseIndexOffset base=[";
319 Base->print(OS);
320 OS << "] index=[";
321 if (Index)
322 Index->print(OS);
323 OS << "] offset=" << Offset;
324}
325
326#endif
return SDValue()
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:638
This file provides utility analysis objects describing memory locations.
static BaseIndexOffset matchLSNode(const LSBaseSDNode *N, const SelectionDAG &DAG)
Parses tree in Ptr for base, index, offset addresses.
This file describes how to lower LLVM code to machine code.
LLVM_ABI bool contains(const SelectionDAG &DAG, int64_t BitSize, const BaseIndexOffset &Other, int64_t OtherBitSize, int64_t &BitOffset) const
LLVM_ABI void print(raw_ostream &OS) const
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
static LLVM_ABI bool computeAliasing(const SDNode *Op0, const LocationSize NumBytes0, const SDNode *Op1, const LocationSize NumBytes1, const SelectionDAG &DAG, bool &IsAlias)
LLVM_ABI bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, int64_t &Off) const
Helper struct to store a base, index and offset that forms an address.
Base class for LoadSDNode and StoreSDNode.
bool hasValue() const
bool isScalable() const
TypeSize getValue() const
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetLowering & getTargetLoweringInfo() const
MachineFunction & getMachineFunction() const
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
virtual SDValue unwrapAddress(SDValue N) const
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:259
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:826
bool match(Val *V, const Pattern &P)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
@ Other
Any other memory.
Definition ModRef.h:68
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
#define N