blob: 544da362be698a6d4e48ee0ad28dce49ca6f4970 [file] [log] [blame]
Eugene Zelenko618c5552017-09-13 21:15:20 +00001//==- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp - DAG Address Analysis --==//
Nirav Davec1b6aa72017-06-21 15:40:43 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Nirav Davec1b6aa72017-06-21 15:40:43 +00009
10#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
11#include "llvm/CodeGen/ISDOpcodes.h"
Nirav Dave168c5a62017-06-29 15:48:11 +000012#include "llvm/CodeGen/MachineFrameInfo.h"
Eugene Zelenko618c5552017-09-13 21:15:20 +000013#include "llvm/CodeGen/MachineFunction.h"
Nirav Davec1b6aa72017-06-21 15:40:43 +000014#include "llvm/CodeGen/SelectionDAG.h"
15#include "llvm/CodeGen/SelectionDAGNodes.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000016#include "llvm/CodeGen/TargetLowering.h"
Eugene Zelenko618c5552017-09-13 21:15:20 +000017#include "llvm/Support/Casting.h"
Eugene Zelenko618c5552017-09-13 21:15:20 +000018#include <cstdint>
Nirav Davec1b6aa72017-06-21 15:40:43 +000019
Eugene Zelenko618c5552017-09-13 21:15:20 +000020using namespace llvm;
Nirav Davec1b6aa72017-06-21 15:40:43 +000021
22bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other,
23 const SelectionDAG &DAG, int64_t &Off) {
Nirav Dave168c5a62017-06-29 15:48:11 +000024 // Initial Offset difference.
Nirav Davec1b6aa72017-06-21 15:40:43 +000025 Off = Other.Offset - Offset;
Nirav Davec1b6aa72017-06-21 15:40:43 +000026
Nirav Dave168c5a62017-06-29 15:48:11 +000027 if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
28 // Trivial match.
29 if (Other.Base == Base)
30 return true;
31
32 // Match GlobalAddresses
33 if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
34 if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
Nirav Davec1b6aa72017-06-21 15:40:43 +000035 if (A->getGlobal() == B->getGlobal()) {
36 Off += B->getOffset() - A->getOffset();
37 return true;
38 }
39
Nirav Dave168c5a62017-06-29 15:48:11 +000040 const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
Nirav Davec1b6aa72017-06-21 15:40:43 +000041
Nirav Davea2810e62017-07-04 02:20:17 +000042 // Match non-equal FrameIndexes - If both frame indices are fixed
43 // we know their relative offsets and can compare them. Otherwise
44 // we must be conservative.
Nirav Dave168c5a62017-06-29 15:48:11 +000045 if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
46 if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base))
Nirav Davea2810e62017-07-04 02:20:17 +000047 if (MFI.isFixedObjectIndex(A->getIndex()) &&
48 MFI.isFixedObjectIndex(B->getIndex())) {
Nirav Dave168c5a62017-06-29 15:48:11 +000049 Off += MFI.getObjectOffset(B->getIndex()) -
50 MFI.getObjectOffset(A->getIndex());
51 return true;
52 }
53 }
Nirav Davec1b6aa72017-06-21 15:40:43 +000054 return false;
55}
56
57/// Parses tree in Ptr for base, index, offset addresses.
Nirav Dave168c5a62017-06-29 15:48:11 +000058BaseIndexOffset BaseIndexOffset::match(SDValue Ptr, const SelectionDAG &DAG) {
Nirav Davec1b6aa72017-06-21 15:40:43 +000059 // (((B + I*M) + c)) + c ...
Nirav Daved1b3f092017-08-11 13:21:35 +000060 SDValue Base = DAG.getTargetLoweringInfo().unwrapAddress(Ptr);
Nirav Davec1b6aa72017-06-21 15:40:43 +000061 SDValue Index = SDValue();
62 int64_t Offset = 0;
63 bool IsIndexSignExt = false;
64
Nirav Daveb320ef92017-07-05 01:21:23 +000065 // Consume constant adds & ors with appropriate masking.
66 while (Base->getOpcode() == ISD::ADD || Base->getOpcode() == ISD::OR) {
67 if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
68 // Only consider ORs which act as adds.
69 if (Base->getOpcode() == ISD::OR &&
70 !DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue()))
71 break;
72 Offset += C->getSExtValue();
73 Base = Base->getOperand(0);
74 continue;
75 }
76 break;
Nirav Davec1b6aa72017-06-21 15:40:43 +000077 }
78
79 if (Base->getOpcode() == ISD::ADD) {
80 // TODO: The following code appears to be needless as it just
81 // bails on some Ptrs early, reducing the cases where we
82 // find equivalence. We should be able to remove this.
83 // Inside a loop the current BASE pointer is calculated using an ADD and a
84 // MUL instruction. In this case Base is the actual BASE pointer.
85 // (i64 add (i64 %array_ptr)
86 // (i64 mul (i64 %induction_var)
87 // (i64 %element_size)))
88 if (Base->getOperand(1)->getOpcode() == ISD::MUL)
89 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
90
91 // Look at Base + Index + Offset cases.
92 Index = Base->getOperand(1);
93 SDValue PotentialBase = Base->getOperand(0);
94
95 // Skip signextends.
96 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
97 Index = Index->getOperand(0);
98 IsIndexSignExt = true;
99 }
100
101 // Check if Index Offset pattern
102 if (Index->getOpcode() != ISD::ADD ||
103 !isa<ConstantSDNode>(Index->getOperand(1)))
104 return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
105
106 Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
107 Index = Index->getOperand(0);
108 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
109 Index = Index->getOperand(0);
110 IsIndexSignExt = true;
111 } else
112 IsIndexSignExt = false;
113 Base = PotentialBase;
114 }
115 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
116}