LLVM  9.0.0svn
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 
16 #include "llvm/Support/Casting.h"
17 #include <cstdint>
18 
19 using namespace llvm;
20 
22  const SelectionDAG &DAG,
23  int64_t &Off) const {
24  // Conservatively fail if we a match failed..
25  if (!Base.getNode() || !Other.Base.getNode())
26  return false;
27  if (!hasValidOffset() || !Other.hasValidOffset())
28  return false;
29  // Initial Offset difference.
30  Off = *Other.Offset - *Offset;
31 
32  if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
33  // Trivial match.
34  if (Other.Base == Base)
35  return true;
36 
37  // Match GlobalAddresses
38  if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
39  if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
40  if (A->getGlobal() == B->getGlobal()) {
41  Off += B->getOffset() - A->getOffset();
42  return true;
43  }
44 
45  // Match Constants
46  if (auto *A = dyn_cast<ConstantPoolSDNode>(Base))
47  if (auto *B = dyn_cast<ConstantPoolSDNode>(Other.Base)) {
48  bool IsMatch =
49  A->isMachineConstantPoolEntry() == B->isMachineConstantPoolEntry();
50  if (IsMatch) {
51  if (A->isMachineConstantPoolEntry())
52  IsMatch = A->getMachineCPVal() == B->getMachineCPVal();
53  else
54  IsMatch = A->getConstVal() == B->getConstVal();
55  }
56  if (IsMatch) {
57  Off += B->getOffset() - A->getOffset();
58  return true;
59  }
60  }
61 
63 
64  // Match FrameIndexes.
65  if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
66  if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base)) {
67  // Equal FrameIndexes - offsets are directly comparable.
68  if (A->getIndex() == B->getIndex())
69  return true;
70  // Non-equal FrameIndexes - If both frame indices are fixed
71  // we know their relative offsets and can compare them. Otherwise
72  // we must be conservative.
73  if (MFI.isFixedObjectIndex(A->getIndex()) &&
74  MFI.isFixedObjectIndex(B->getIndex())) {
75  Off += MFI.getObjectOffset(B->getIndex()) -
76  MFI.getObjectOffset(A->getIndex());
77  return true;
78  }
79  }
80  }
81  return false;
82 }
83 
85  const Optional<int64_t> NumBytes0,
86  const SDNode *Op1,
87  const Optional<int64_t> NumBytes1,
88  const SelectionDAG &DAG, bool &IsAlias) {
89 
90  BaseIndexOffset BasePtr0 = match(Op0, DAG);
91  BaseIndexOffset BasePtr1 = match(Op1, DAG);
92 
93  if (!(BasePtr0.getBase().getNode() && BasePtr1.getBase().getNode()))
94  return false;
95  int64_t PtrDiff;
96  if (NumBytes0.hasValue() && NumBytes1.hasValue() &&
97  BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) {
98  // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the
99  // following situations arise:
100  IsAlias = !(
101  // [----BasePtr0----]
102  // [---BasePtr1--]
103  // ========PtrDiff========>
104  (*NumBytes0 <= PtrDiff) ||
105  // [----BasePtr0----]
106  // [---BasePtr1--]
107  // =====(-PtrDiff)====>
108  (PtrDiff + *NumBytes1 <= 0)); // i.e. *NumBytes1 < -PtrDiff.
109  return true;
110  }
111  // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be
112  // able to calculate their relative offset if at least one arises
113  // from an alloca. However, these allocas cannot overlap and we
114  // can infer there is no alias.
115  if (auto *A = dyn_cast<FrameIndexSDNode>(BasePtr0.getBase()))
116  if (auto *B = dyn_cast<FrameIndexSDNode>(BasePtr1.getBase())) {
118  // If the base are the same frame index but the we couldn't find a
119  // constant offset, (indices are different) be conservative.
120  if (A != B && (!MFI.isFixedObjectIndex(A->getIndex()) ||
121  !MFI.isFixedObjectIndex(B->getIndex()))) {
122  IsAlias = false;
123  return true;
124  }
125  }
126 
127  bool IsFI0 = isa<FrameIndexSDNode>(BasePtr0.getBase());
128  bool IsFI1 = isa<FrameIndexSDNode>(BasePtr1.getBase());
129  bool IsGV0 = isa<GlobalAddressSDNode>(BasePtr0.getBase());
130  bool IsGV1 = isa<GlobalAddressSDNode>(BasePtr1.getBase());
131  bool IsCV0 = isa<ConstantPoolSDNode>(BasePtr0.getBase());
132  bool IsCV1 = isa<ConstantPoolSDNode>(BasePtr1.getBase());
133 
134  // If of mismatched base types or checkable indices we can check
135  // they do not alias.
136  if ((BasePtr0.getIndex() == BasePtr1.getIndex() || (IsFI0 != IsFI1) ||
137  (IsGV0 != IsGV1) || (IsCV0 != IsCV1)) &&
138  (IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) {
139  IsAlias = false;
140  return true;
141  }
142  return false; // Cannot determine whether the pointers alias.
143 }
144 
145 bool BaseIndexOffset::contains(const SelectionDAG &DAG, int64_t BitSize,
146  const BaseIndexOffset &Other,
147  int64_t OtherBitSize, int64_t &BitOffset) const {
148  int64_t Offset;
149  if (!equalBaseIndex(Other, DAG, Offset))
150  return false;
151  if (Offset >= 0) {
152  // Other is after *this:
153  // [-------*this---------]
154  // [---Other--]
155  // ==Offset==>
156  BitOffset = 8 * Offset;
157  return BitOffset + OtherBitSize <= BitSize;
158  }
159  // Other starts strictly before *this, it cannot be fully contained.
160  // [-------*this---------]
161  // [--Other--]
162  return false;
163 }
164 
165 /// Parses tree in Ptr for base, index, offset addresses.
167  const SelectionDAG &DAG) {
168  SDValue Ptr = N->getBasePtr();
169 
170  // (((B + I*M) + c)) + c ...
172  SDValue Index = SDValue();
173  int64_t Offset = 0;
174  bool IsIndexSignExt = false;
175 
176  // pre-inc/pre-dec ops are components of EA.
177  if (N->getAddressingMode() == ISD::PRE_INC) {
178  if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
179  Offset += C->getSExtValue();
180  else // If unknown, give up now.
181  return BaseIndexOffset(SDValue(), SDValue(), 0, false);
182  } else if (N->getAddressingMode() == ISD::PRE_DEC) {
183  if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
184  Offset -= C->getSExtValue();
185  else // If unknown, give up now.
186  return BaseIndexOffset(SDValue(), SDValue(), 0, false);
187  }
188 
189  // Consume constant adds & ors with appropriate masking.
190  while (true) {
191  switch (Base->getOpcode()) {
192  case ISD::OR:
193  // Only consider ORs which act as adds.
194  if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1)))
195  if (DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue())) {
196  Offset += C->getSExtValue();
197  Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
198  continue;
199  }
200  break;
201  case ISD::ADD:
202  if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
203  Offset += C->getSExtValue();
204  Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
205  continue;
206  }
207  break;
208  case ISD::LOAD:
209  case ISD::STORE: {
210  auto *LSBase = cast<LSBaseSDNode>(Base.getNode());
211  unsigned int IndexResNo = (Base->getOpcode() == ISD::LOAD) ? 1 : 0;
212  if (LSBase->isIndexed() && Base.getResNo() == IndexResNo)
213  if (auto *C = dyn_cast<ConstantSDNode>(LSBase->getOffset())) {
214  auto Off = C->getSExtValue();
215  if (LSBase->getAddressingMode() == ISD::PRE_DEC ||
216  LSBase->getAddressingMode() == ISD::POST_DEC)
217  Offset -= Off;
218  else
219  Offset += Off;
220  Base = DAG.getTargetLoweringInfo().unwrapAddress(LSBase->getBasePtr());
221  continue;
222  }
223  break;
224  }
225  }
226  // If we get here break out of the loop.
227  break;
228  }
229 
230  if (Base->getOpcode() == ISD::ADD) {
231  // TODO: The following code appears to be needless as it just
232  // bails on some Ptrs early, reducing the cases where we
233  // find equivalence. We should be able to remove this.
234  // Inside a loop the current BASE pointer is calculated using an ADD and a
235  // MUL instruction. In this case Base is the actual BASE pointer.
236  // (i64 add (i64 %array_ptr)
237  // (i64 mul (i64 %induction_var)
238  // (i64 %element_size)))
239  if (Base->getOperand(1)->getOpcode() == ISD::MUL)
240  return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
241 
242  // Look at Base + Index + Offset cases.
243  Index = Base->getOperand(1);
244  SDValue PotentialBase = Base->getOperand(0);
245 
246  // Skip signextends.
247  if (Index->getOpcode() == ISD::SIGN_EXTEND) {
248  Index = Index->getOperand(0);
249  IsIndexSignExt = true;
250  }
251 
252  // Check if Index Offset pattern
253  if (Index->getOpcode() != ISD::ADD ||
254  !isa<ConstantSDNode>(Index->getOperand(1)))
255  return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
256 
257  Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
258  Index = Index->getOperand(0);
259  if (Index->getOpcode() == ISD::SIGN_EXTEND) {
260  Index = Index->getOperand(0);
261  IsIndexSignExt = true;
262  } else
263  IsIndexSignExt = false;
264  Base = PotentialBase;
265  }
266  return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
267 }
268 
270  const SelectionDAG &DAG) {
271  if (const auto *LS0 = dyn_cast<LSBaseSDNode>(N))
272  return matchLSNode(LS0, DAG);
273  if (const auto *LN = dyn_cast<LifetimeSDNode>(N)) {
274  if (LN->hasOffset())
275  return BaseIndexOffset(LN->getOperand(1), SDValue(), LN->getOffset(),
276  false);
277  return BaseIndexOffset(LN->getOperand(1), SDValue(), false);
278  }
279  return BaseIndexOffset();
280 }
281 
282 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
283 
285  print(dbgs());
286 }
287 
289  OS << "BaseIndexOffset base=[";
290  Base->print(OS);
291  OS << "] index=[";
292  if (Index)
293  Index->print(OS);
294  OS << "] offset=" << Offset;
295 }
296 
297 #endif
uint64_t CallInst * C
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds...
Definition: Compiler.h:473
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc, or post-dec.
SDNode * getNode() const
get the SDNode which holds the desired result
Base class for LoadSDNode and StoreSDNode.
bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, int64_t &Off) const
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:400
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:200
bool contains(const SelectionDAG &DAG, int64_t BitSize, const BaseIndexOffset &Other, int64_t OtherBitSize, int64_t &BitOffset) const
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const SDValue & getOperand(unsigned Num) const
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
virtual SDValue unwrapAddress(SDValue N) const
static BaseIndexOffset matchLSNode(const LSBaseSDNode *N, const SelectionDAG &DAG)
Parses tree in Ptr for base, index, offset addresses.
static bool computeAliasing(const SDNode *Op0, const Optional< int64_t > NumBytes0, const SDNode *Op1, const Optional< int64_t > NumBytes1, const SelectionDAG &DAG, bool &IsAlias)
const TargetLowering & getTargetLoweringInfo() const
Definition: SelectionDAG.h:406
Helper struct to parse and store a memory address as base + index + offset.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:221
const SDValue & getOffset() const
void print(raw_ostream &OS) const
Represents one node in the SelectionDAG.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
bool hasValue() const
Definition: Optional.h:259
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:642
#define N
static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if &#39;Op & Mask&#39; is known to be zero.
void print(raw_ostream &OS, const SelectionDAG *G=nullptr) const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
Conversion operators.
Definition: ISDOpcodes.h:489
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
const SDValue & getBasePtr() const
This file describes how to lower LLVM code to machine code.