blob: 0d69441ebb7f7f35e4c1d75c18b76defb3c42209 [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 Davea2810e62017-07-04 02:20:17 +000040 // Match non-equal FrameIndexes - If both frame indices are fixed
41 // we know their relative offsets and can compare them. Otherwise
42 // we must be conservative.
Nirav Dave168c5a62017-06-29 15:48:11 +000043 if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
44 if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base))
Nirav Davea2810e62017-07-04 02:20:17 +000045 if (MFI.isFixedObjectIndex(A->getIndex()) &&
46 MFI.isFixedObjectIndex(B->getIndex())) {
Nirav Dave168c5a62017-06-29 15:48:11 +000047 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 Daveb320ef92017-07-05 01:21:23 +000063 // Consume constant adds & ors with appropriate masking.
64 while (Base->getOpcode() == ISD::ADD || Base->getOpcode() == ISD::OR) {
65 if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
66 // Only consider ORs which act as adds.
67 if (Base->getOpcode() == ISD::OR &&
68 !DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue()))
69 break;
70 Offset += C->getSExtValue();
71 Base = Base->getOperand(0);
72 continue;
73 }
74 break;
Nirav Davec1b6aa72017-06-21 15:40:43 +000075 }
76
77 if (Base->getOpcode() == ISD::ADD) {
78 // TODO: The following code appears to be needless as it just
79 // bails on some Ptrs early, reducing the cases where we
80 // find equivalence. We should be able to remove this.
81 // Inside a loop the current BASE pointer is calculated using an ADD and a
82 // MUL instruction. In this case Base is the actual BASE pointer.
83 // (i64 add (i64 %array_ptr)
84 // (i64 mul (i64 %induction_var)
85 // (i64 %element_size)))
86 if (Base->getOperand(1)->getOpcode() == ISD::MUL)
87 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
88
89 // Look at Base + Index + Offset cases.
90 Index = Base->getOperand(1);
91 SDValue PotentialBase = Base->getOperand(0);
92
93 // Skip signextends.
94 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
95 Index = Index->getOperand(0);
96 IsIndexSignExt = true;
97 }
98
99 // Check if Index Offset pattern
100 if (Index->getOpcode() != ISD::ADD ||
101 !isa<ConstantSDNode>(Index->getOperand(1)))
102 return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
103
104 Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
105 Index = Index->getOperand(0);
106 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
107 Index = Index->getOperand(0);
108 IsIndexSignExt = true;
109 } else
110 IsIndexSignExt = false;
111 Base = PotentialBase;
112 }
113 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
114}
115} // end namespace llvm