blob: 4e899ae6668e76201da00890fa4e0d39edb736e2 [file] [log] [blame]
Nirav Davec1b6aa72017-06-21 15:40:43 +00001//===-- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp ------- DAG Address
2//Analysis ---*- C++ -*-===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10//
11
12#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
13#include "llvm/CodeGen/ISDOpcodes.h"
Nirav Dave168c5a62017-06-29 15:48:11 +000014#include "llvm/CodeGen/MachineFrameInfo.h"
Nirav Davec1b6aa72017-06-21 15:40:43 +000015#include "llvm/CodeGen/SelectionDAG.h"
16#include "llvm/CodeGen/SelectionDAGNodes.h"
17
18namespace llvm {
19
20bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other,
21 const SelectionDAG &DAG, int64_t &Off) {
Nirav Dave168c5a62017-06-29 15:48:11 +000022 // Initial Offset difference.
Nirav Davec1b6aa72017-06-21 15:40:43 +000023 Off = Other.Offset - Offset;
Nirav Davec1b6aa72017-06-21 15:40:43 +000024
Nirav Dave168c5a62017-06-29 15:48:11 +000025 if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
26 // Trivial match.
27 if (Other.Base == Base)
28 return true;
29
30 // Match GlobalAddresses
31 if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
32 if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
Nirav Davec1b6aa72017-06-21 15:40:43 +000033 if (A->getGlobal() == B->getGlobal()) {
34 Off += B->getOffset() - A->getOffset();
35 return true;
36 }
37
Nirav Dave168c5a62017-06-29 15:48:11 +000038 const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
Nirav Davec1b6aa72017-06-21 15:40:43 +000039
Nirav Dave168c5a62017-06-29 15:48:11 +000040 // Match non-equal FrameIndexes - a FrameIndex stemming from an
41 // alloca will not have it's ObjectOffset set until post-DAG and
42 // as such we must assume the two framesIndices are incomparable.
43 if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
44 if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base))
45 if (!MFI.getObjectAllocation(A->getIndex()) &&
46 !MFI.getObjectAllocation(B->getIndex())) {
47 Off += MFI.getObjectOffset(B->getIndex()) -
48 MFI.getObjectOffset(A->getIndex());
49 return true;
50 }
51 }
Nirav Davec1b6aa72017-06-21 15:40:43 +000052 return false;
53}
54
55/// Parses tree in Ptr for base, index, offset addresses.
Nirav Dave168c5a62017-06-29 15:48:11 +000056BaseIndexOffset BaseIndexOffset::match(SDValue Ptr, const SelectionDAG &DAG) {
Nirav Davec1b6aa72017-06-21 15:40:43 +000057 // (((B + I*M) + c)) + c ...
58 SDValue Base = Ptr;
59 SDValue Index = SDValue();
60 int64_t Offset = 0;
61 bool IsIndexSignExt = false;
62
Nirav Davea35938d2017-06-30 12:56:02 +000063 // Consume constant adds
64 while (Base->getOpcode() == ISD::ADD &&
65 isa<ConstantSDNode>(Base->getOperand(1))) {
66 int64_t POffset = cast<ConstantSDNode>(Base->getOperand(1))->getSExtValue();
67 Offset += POffset;
68 Base = Base->getOperand(0);
Nirav Davec1b6aa72017-06-21 15:40:43 +000069 }
70
71 if (Base->getOpcode() == ISD::ADD) {
72 // TODO: The following code appears to be needless as it just
73 // bails on some Ptrs early, reducing the cases where we
74 // find equivalence. We should be able to remove this.
75 // Inside a loop the current BASE pointer is calculated using an ADD and a
76 // MUL instruction. In this case Base is the actual BASE pointer.
77 // (i64 add (i64 %array_ptr)
78 // (i64 mul (i64 %induction_var)
79 // (i64 %element_size)))
80 if (Base->getOperand(1)->getOpcode() == ISD::MUL)
81 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
82
83 // Look at Base + Index + Offset cases.
84 Index = Base->getOperand(1);
85 SDValue PotentialBase = Base->getOperand(0);
86
87 // Skip signextends.
88 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
89 Index = Index->getOperand(0);
90 IsIndexSignExt = true;
91 }
92
93 // Check if Index Offset pattern
94 if (Index->getOpcode() != ISD::ADD ||
95 !isa<ConstantSDNode>(Index->getOperand(1)))
96 return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
97
98 Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
99 Index = Index->getOperand(0);
100 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
101 Index = Index->getOperand(0);
102 IsIndexSignExt = true;
103 } else
104 IsIndexSignExt = false;
105 Base = PotentialBase;
106 }
107 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
108}
109} // end namespace llvm