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  // Initial Offset difference.
28  Off = Other.Offset - Offset;
29 
30  if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
31  // Trivial match.
32  if (Other.Base == Base)
33  return true;
34 
35  // Match GlobalAddresses
36  if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
37  if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
38  if (A->getGlobal() == B->getGlobal()) {
39  Off += B->getOffset() - A->getOffset();
40  return true;
41  }
42 
43  // Match Constants
44  if (auto *A = dyn_cast<ConstantPoolSDNode>(Base))
45  if (auto *B = dyn_cast<ConstantPoolSDNode>(Other.Base)) {
46  bool IsMatch =
47  A->isMachineConstantPoolEntry() == B->isMachineConstantPoolEntry();
48  if (IsMatch) {
49  if (A->isMachineConstantPoolEntry())
50  IsMatch = A->getMachineCPVal() == B->getMachineCPVal();
51  else
52  IsMatch = A->getConstVal() == B->getConstVal();
53  }
54  if (IsMatch) {
55  Off += B->getOffset() - A->getOffset();
56  return true;
57  }
58  }
59 
61 
62  // Match FrameIndexes.
63  if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
64  if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base)) {
65  // Equal FrameIndexes - offsets are directly comparable.
66  if (A->getIndex() == B->getIndex())
67  return true;
68  // Non-equal FrameIndexes - If both frame indices are fixed
69  // we know their relative offsets and can compare them. Otherwise
70  // we must be conservative.
71  if (MFI.isFixedObjectIndex(A->getIndex()) &&
72  MFI.isFixedObjectIndex(B->getIndex())) {
73  Off += MFI.getObjectOffset(B->getIndex()) -
74  MFI.getObjectOffset(A->getIndex());
75  return true;
76  }
77  }
78  }
79  return false;
80 }
81 
83  const int64_t NumBytes0,
84  const BaseIndexOffset &BasePtr1,
85  const int64_t NumBytes1,
86  const SelectionDAG &DAG, bool &IsAlias) {
87  if (!(BasePtr0.getBase().getNode() && BasePtr1.getBase().getNode()))
88  return false;
89  int64_t PtrDiff;
90  if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) {
91  // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the
92  // following situations arise:
93  IsAlias = !(
94  // [----BasePtr0----]
95  // [---BasePtr1--]
96  // ========PtrDiff========>
97  (NumBytes0 <= PtrDiff) ||
98  // [----BasePtr0----]
99  // [---BasePtr1--]
100  // =====(-PtrDiff)====>
101  (PtrDiff + NumBytes1 <= 0)); // i.e. NumBytes1 < -PtrDiff.
102  return true;
103  }
104  // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be
105  // able to calculate their relative offset if at least one arises
106  // from an alloca. However, these allocas cannot overlap and we
107  // can infer there is no alias.
108  if (auto *A = dyn_cast<FrameIndexSDNode>(BasePtr0.getBase()))
109  if (auto *B = dyn_cast<FrameIndexSDNode>(BasePtr1.getBase())) {
111  // If the base are the same frame index but the we couldn't find a
112  // constant offset, (indices are different) be conservative.
113  if (A != B && (!MFI.isFixedObjectIndex(A->getIndex()) ||
114  !MFI.isFixedObjectIndex(B->getIndex()))) {
115  IsAlias = false;
116  return true;
117  }
118  }
119 
120  bool IsFI0 = isa<FrameIndexSDNode>(BasePtr0.getBase());
121  bool IsFI1 = isa<FrameIndexSDNode>(BasePtr1.getBase());
122  bool IsGV0 = isa<GlobalAddressSDNode>(BasePtr0.getBase());
123  bool IsGV1 = isa<GlobalAddressSDNode>(BasePtr1.getBase());
124  bool IsCV0 = isa<ConstantPoolSDNode>(BasePtr0.getBase());
125  bool IsCV1 = isa<ConstantPoolSDNode>(BasePtr1.getBase());
126 
127  // If of mismatched base types or checkable indices we can check
128  // they do not alias.
129  if ((BasePtr0.getIndex() == BasePtr1.getIndex() || (IsFI0 != IsFI1) ||
130  (IsGV0 != IsGV1) || (IsCV0 != IsCV1)) &&
131  (IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) {
132  IsAlias = false;
133  return true;
134  }
135  return false; // Cannot determine whether the pointers alias.
136 }
137 
138 bool BaseIndexOffset::contains(const SelectionDAG &DAG, int64_t BitSize,
139  const BaseIndexOffset &Other,
140  int64_t OtherBitSize, int64_t &BitOffset) const {
141  int64_t Offset;
142  if (!equalBaseIndex(Other, DAG, Offset))
143  return false;
144  if (Offset >= 0) {
145  // Other is after *this:
146  // [-------*this---------]
147  // [---Other--]
148  // ==Offset==>
149  BitOffset = 8 * Offset;
150  return BitOffset + OtherBitSize <= BitSize;
151  }
152  // Other starts strictly before *this, it cannot be fully contained.
153  // [-------*this---------]
154  // [--Other--]
155  return false;
156 }
157 
158 /// Parses tree in Ptr for base, index, offset addresses.
160  const SelectionDAG &DAG) {
161  SDValue Ptr = N->getBasePtr();
162 
163  // (((B + I*M) + c)) + c ...
165  SDValue Index = SDValue();
166  int64_t Offset = 0;
167  bool IsIndexSignExt = false;
168 
169  // pre-inc/pre-dec ops are components of EA.
170  if (N->getAddressingMode() == ISD::PRE_INC) {
171  if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
172  Offset += C->getSExtValue();
173  else // If unknown, give up now.
174  return BaseIndexOffset(SDValue(), SDValue(), 0, false);
175  } else if (N->getAddressingMode() == ISD::PRE_DEC) {
176  if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
177  Offset -= C->getSExtValue();
178  else // If unknown, give up now.
179  return BaseIndexOffset(SDValue(), SDValue(), 0, false);
180  }
181 
182  // Consume constant adds & ors with appropriate masking.
183  while (true) {
184  switch (Base->getOpcode()) {
185  case ISD::OR:
186  // Only consider ORs which act as adds.
187  if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1)))
188  if (DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue())) {
189  Offset += C->getSExtValue();
190  Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
191  continue;
192  }
193  break;
194  case ISD::ADD:
195  if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
196  Offset += C->getSExtValue();
197  Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
198  continue;
199  }
200  break;
201  case ISD::LOAD:
202  case ISD::STORE: {
203  auto *LSBase = cast<LSBaseSDNode>(Base.getNode());
204  unsigned int IndexResNo = (Base->getOpcode() == ISD::LOAD) ? 1 : 0;
205  if (LSBase->isIndexed() && Base.getResNo() == IndexResNo)
206  if (auto *C = dyn_cast<ConstantSDNode>(LSBase->getOffset())) {
207  auto Off = C->getSExtValue();
208  if (LSBase->getAddressingMode() == ISD::PRE_DEC ||
209  LSBase->getAddressingMode() == ISD::POST_DEC)
210  Offset -= Off;
211  else
212  Offset += Off;
213  Base = DAG.getTargetLoweringInfo().unwrapAddress(LSBase->getBasePtr());
214  continue;
215  }
216  break;
217  }
218  }
219  // If we get here break out of the loop.
220  break;
221  }
222 
223  if (Base->getOpcode() == ISD::ADD) {
224  // TODO: The following code appears to be needless as it just
225  // bails on some Ptrs early, reducing the cases where we
226  // find equivalence. We should be able to remove this.
227  // Inside a loop the current BASE pointer is calculated using an ADD and a
228  // MUL instruction. In this case Base is the actual BASE pointer.
229  // (i64 add (i64 %array_ptr)
230  // (i64 mul (i64 %induction_var)
231  // (i64 %element_size)))
232  if (Base->getOperand(1)->getOpcode() == ISD::MUL)
233  return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
234 
235  // Look at Base + Index + Offset cases.
236  Index = Base->getOperand(1);
237  SDValue PotentialBase = Base->getOperand(0);
238 
239  // Skip signextends.
240  if (Index->getOpcode() == ISD::SIGN_EXTEND) {
241  Index = Index->getOperand(0);
242  IsIndexSignExt = true;
243  }
244 
245  // Check if Index Offset pattern
246  if (Index->getOpcode() != ISD::ADD ||
247  !isa<ConstantSDNode>(Index->getOperand(1)))
248  return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
249 
250  Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
251  Index = Index->getOperand(0);
252  if (Index->getOpcode() == ISD::SIGN_EXTEND) {
253  Index = Index->getOperand(0);
254  IsIndexSignExt = true;
255  } else
256  IsIndexSignExt = false;
257  Base = PotentialBase;
258  }
259  return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
260 }
261 
262 
263 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
264 
266  print(dbgs());
267 }
268 
270  OS << "BaseIndexOffset base=[";
271  Base->print(OS);
272  OS << "] index=[";
273  if (Index)
274  Index->print(OS);
275  OS << "] offset=" << Offset;
276 }
277 
278 #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:464
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:397
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")
static bool computeAliasing(const BaseIndexOffset &BasePtr0, const int64_t NumBytes0, const BaseIndexOffset &BasePtr1, const int64_t NumBytes1, const SelectionDAG &DAG, bool &IsAlias)
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
const TargetLowering & getTargetLoweringInfo() const
Definition: SelectionDAG.h:403
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
static BaseIndexOffset match(const LSBaseSDNode *N, const SelectionDAG &DAG)
Parses tree in Ptr for base, index, offset addresses.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:615
#define N
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:464
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.