blob: 504ddfacd3298a42705830da7e0dba2f5b5b5c9e [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"
Nirav Daved1b3f092017-08-11 13:21:35 +000017#include "llvm/Target/TargetLowering.h"
Nirav Davec1b6aa72017-06-21 15:40:43 +000018
19namespace llvm {
20
21bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other,
22 const SelectionDAG &DAG, int64_t &Off) {
Nirav Dave168c5a62017-06-29 15:48:11 +000023 // Initial Offset difference.
Nirav Davec1b6aa72017-06-21 15:40:43 +000024 Off = Other.Offset - Offset;
Nirav Davec1b6aa72017-06-21 15:40:43 +000025
Nirav Dave168c5a62017-06-29 15:48:11 +000026 if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
27 // Trivial match.
28 if (Other.Base == Base)
29 return true;
30
31 // Match GlobalAddresses
32 if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
33 if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
Nirav Davec1b6aa72017-06-21 15:40:43 +000034 if (A->getGlobal() == B->getGlobal()) {
35 Off += B->getOffset() - A->getOffset();
36 return true;
37 }
38
Nirav Dave168c5a62017-06-29 15:48:11 +000039 const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
Nirav Davec1b6aa72017-06-21 15:40:43 +000040
Nirav Davea2810e62017-07-04 02:20:17 +000041 // Match non-equal FrameIndexes - If both frame indices are fixed
42 // we know their relative offsets and can compare them. Otherwise
43 // we must be conservative.
Nirav Dave168c5a62017-06-29 15:48:11 +000044 if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
45 if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base))
Nirav Davea2810e62017-07-04 02:20:17 +000046 if (MFI.isFixedObjectIndex(A->getIndex()) &&
47 MFI.isFixedObjectIndex(B->getIndex())) {
Nirav Dave168c5a62017-06-29 15:48:11 +000048 Off += MFI.getObjectOffset(B->getIndex()) -
49 MFI.getObjectOffset(A->getIndex());
50 return true;
51 }
52 }
Nirav Davec1b6aa72017-06-21 15:40:43 +000053 return false;
54}
55
56/// Parses tree in Ptr for base, index, offset addresses.
Nirav Dave168c5a62017-06-29 15:48:11 +000057BaseIndexOffset BaseIndexOffset::match(SDValue Ptr, const SelectionDAG &DAG) {
Nirav Davec1b6aa72017-06-21 15:40:43 +000058 // (((B + I*M) + c)) + c ...
Nirav Daved1b3f092017-08-11 13:21:35 +000059 SDValue Base = DAG.getTargetLoweringInfo().unwrapAddress(Ptr);
Nirav Davec1b6aa72017-06-21 15:40:43 +000060 SDValue Index = SDValue();
61 int64_t Offset = 0;
62 bool IsIndexSignExt = false;
63
Nirav Daveb320ef92017-07-05 01:21:23 +000064 // Consume constant adds & ors with appropriate masking.
65 while (Base->getOpcode() == ISD::ADD || Base->getOpcode() == ISD::OR) {
66 if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
67 // Only consider ORs which act as adds.
68 if (Base->getOpcode() == ISD::OR &&
69 !DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue()))
70 break;
71 Offset += C->getSExtValue();
72 Base = Base->getOperand(0);
73 continue;
74 }
75 break;
Nirav Davec1b6aa72017-06-21 15:40:43 +000076 }
77
78 if (Base->getOpcode() == ISD::ADD) {
79 // TODO: The following code appears to be needless as it just
80 // bails on some Ptrs early, reducing the cases where we
81 // find equivalence. We should be able to remove this.
82 // Inside a loop the current BASE pointer is calculated using an ADD and a
83 // MUL instruction. In this case Base is the actual BASE pointer.
84 // (i64 add (i64 %array_ptr)
85 // (i64 mul (i64 %induction_var)
86 // (i64 %element_size)))
87 if (Base->getOperand(1)->getOpcode() == ISD::MUL)
88 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
89
90 // Look at Base + Index + Offset cases.
91 Index = Base->getOperand(1);
92 SDValue PotentialBase = Base->getOperand(0);
93
94 // Skip signextends.
95 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
96 Index = Index->getOperand(0);
97 IsIndexSignExt = true;
98 }
99
100 // Check if Index Offset pattern
101 if (Index->getOpcode() != ISD::ADD ||
102 !isa<ConstantSDNode>(Index->getOperand(1)))
103 return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
104
105 Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
106 Index = Index->getOperand(0);
107 if (Index->getOpcode() == ISD::SIGN_EXTEND) {
108 Index = Index->getOperand(0);
109 IsIndexSignExt = true;
110 } else
111 IsIndexSignExt = false;
112 Base = PotentialBase;
113 }
114 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
115}
116} // end namespace llvm