12cab237bSDimitry Andric //==- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp - DAG Address Analysis --==//
2edd7eaddSDimitry Andric //
3edd7eaddSDimitry Andric // The LLVM Compiler Infrastructure
4edd7eaddSDimitry Andric //
5edd7eaddSDimitry Andric // This file is distributed under the University of Illinois Open Source
6edd7eaddSDimitry Andric // License. See LICENSE.TXT for details.
7edd7eaddSDimitry Andric //
8edd7eaddSDimitry Andric //===----------------------------------------------------------------------===//
9edd7eaddSDimitry Andric
10edd7eaddSDimitry Andric #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
11edd7eaddSDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
12a580b014SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
132cab237bSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
14edd7eaddSDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
15edd7eaddSDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
162cab237bSDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
172cab237bSDimitry Andric #include "llvm/Support/Casting.h"
182cab237bSDimitry Andric #include <cstdint>
19edd7eaddSDimitry Andric
202cab237bSDimitry Andric using namespace llvm;
21edd7eaddSDimitry Andric
equalBaseIndex(const BaseIndexOffset & Other,const SelectionDAG & DAG,int64_t & Off) const22*b5893f02SDimitry Andric bool BaseIndexOffset::equalBaseIndex(const BaseIndexOffset &Other,
23*b5893f02SDimitry Andric const SelectionDAG &DAG,
24*b5893f02SDimitry Andric int64_t &Off) const {
25042b1c2eSDimitry Andric // Conservatively fail if we a match failed..
26042b1c2eSDimitry Andric if (!Base.getNode() || !Other.Base.getNode())
27042b1c2eSDimitry Andric return false;
28a580b014SDimitry Andric // Initial Offset difference.
29edd7eaddSDimitry Andric Off = Other.Offset - Offset;
30a580b014SDimitry Andric
31a580b014SDimitry Andric if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
32a580b014SDimitry Andric // Trivial match.
33a580b014SDimitry Andric if (Other.Base == Base)
34edd7eaddSDimitry Andric return true;
35edd7eaddSDimitry Andric
36edd7eaddSDimitry Andric // Match GlobalAddresses
37a580b014SDimitry Andric if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
38a580b014SDimitry Andric if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
39edd7eaddSDimitry Andric if (A->getGlobal() == B->getGlobal()) {
40edd7eaddSDimitry Andric Off += B->getOffset() - A->getOffset();
41edd7eaddSDimitry Andric return true;
42edd7eaddSDimitry Andric }
43edd7eaddSDimitry Andric
44da09e106SDimitry Andric // Match Constants
45da09e106SDimitry Andric if (auto *A = dyn_cast<ConstantPoolSDNode>(Base))
46da09e106SDimitry Andric if (auto *B = dyn_cast<ConstantPoolSDNode>(Other.Base)) {
47da09e106SDimitry Andric bool IsMatch =
48da09e106SDimitry Andric A->isMachineConstantPoolEntry() == B->isMachineConstantPoolEntry();
49da09e106SDimitry Andric if (IsMatch) {
50da09e106SDimitry Andric if (A->isMachineConstantPoolEntry())
51da09e106SDimitry Andric IsMatch = A->getMachineCPVal() == B->getMachineCPVal();
52da09e106SDimitry Andric else
53da09e106SDimitry Andric IsMatch = A->getConstVal() == B->getConstVal();
54da09e106SDimitry Andric }
55da09e106SDimitry Andric if (IsMatch) {
56da09e106SDimitry Andric Off += B->getOffset() - A->getOffset();
57da09e106SDimitry Andric return true;
58da09e106SDimitry Andric }
59da09e106SDimitry Andric }
60da09e106SDimitry Andric
61a580b014SDimitry Andric const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
62edd7eaddSDimitry Andric
63c4394386SDimitry Andric // Match non-equal FrameIndexes - If both frame indices are fixed
64c4394386SDimitry Andric // we know their relative offsets and can compare them. Otherwise
65c4394386SDimitry Andric // we must be conservative.
66a580b014SDimitry Andric if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
67a580b014SDimitry Andric if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base))
68c4394386SDimitry Andric if (MFI.isFixedObjectIndex(A->getIndex()) &&
69c4394386SDimitry Andric MFI.isFixedObjectIndex(B->getIndex())) {
70a580b014SDimitry Andric Off += MFI.getObjectOffset(B->getIndex()) -
71a580b014SDimitry Andric MFI.getObjectOffset(A->getIndex());
72a580b014SDimitry Andric return true;
73a580b014SDimitry Andric }
74a580b014SDimitry Andric }
75edd7eaddSDimitry Andric return false;
76edd7eaddSDimitry Andric }
77edd7eaddSDimitry Andric
78edd7eaddSDimitry Andric /// Parses tree in Ptr for base, index, offset addresses.
match(const LSBaseSDNode * N,const SelectionDAG & DAG)79*b5893f02SDimitry Andric BaseIndexOffset BaseIndexOffset::match(const LSBaseSDNode *N,
80042b1c2eSDimitry Andric const SelectionDAG &DAG) {
81042b1c2eSDimitry Andric SDValue Ptr = N->getBasePtr();
82042b1c2eSDimitry Andric
83edd7eaddSDimitry Andric // (((B + I*M) + c)) + c ...
842cab237bSDimitry Andric SDValue Base = DAG.getTargetLoweringInfo().unwrapAddress(Ptr);
85edd7eaddSDimitry Andric SDValue Index = SDValue();
86edd7eaddSDimitry Andric int64_t Offset = 0;
87edd7eaddSDimitry Andric bool IsIndexSignExt = false;
88edd7eaddSDimitry Andric
89042b1c2eSDimitry Andric // pre-inc/pre-dec ops are components of EA.
90042b1c2eSDimitry Andric if (N->getAddressingMode() == ISD::PRE_INC) {
91042b1c2eSDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
92042b1c2eSDimitry Andric Offset += C->getSExtValue();
93042b1c2eSDimitry Andric else // If unknown, give up now.
94042b1c2eSDimitry Andric return BaseIndexOffset(SDValue(), SDValue(), 0, false);
95042b1c2eSDimitry Andric } else if (N->getAddressingMode() == ISD::PRE_DEC) {
96042b1c2eSDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
97042b1c2eSDimitry Andric Offset -= C->getSExtValue();
98042b1c2eSDimitry Andric else // If unknown, give up now.
99042b1c2eSDimitry Andric return BaseIndexOffset(SDValue(), SDValue(), 0, false);
100042b1c2eSDimitry Andric }
101042b1c2eSDimitry Andric
102c4394386SDimitry Andric // Consume constant adds & ors with appropriate masking.
1034ba319b5SDimitry Andric while (true) {
1044ba319b5SDimitry Andric switch (Base->getOpcode()) {
1054ba319b5SDimitry Andric case ISD::OR:
106c4394386SDimitry Andric // Only consider ORs which act as adds.
1074ba319b5SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1)))
1084ba319b5SDimitry Andric if (DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue())) {
109c4394386SDimitry Andric Offset += C->getSExtValue();
110*b5893f02SDimitry Andric Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
111c4394386SDimitry Andric continue;
112c4394386SDimitry Andric }
113c4394386SDimitry Andric break;
1144ba319b5SDimitry Andric case ISD::ADD:
1154ba319b5SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
1164ba319b5SDimitry Andric Offset += C->getSExtValue();
117*b5893f02SDimitry Andric Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
1184ba319b5SDimitry Andric continue;
1194ba319b5SDimitry Andric }
1204ba319b5SDimitry Andric break;
1214ba319b5SDimitry Andric case ISD::LOAD:
1224ba319b5SDimitry Andric case ISD::STORE: {
1234ba319b5SDimitry Andric auto *LSBase = cast<LSBaseSDNode>(Base.getNode());
1244ba319b5SDimitry Andric unsigned int IndexResNo = (Base->getOpcode() == ISD::LOAD) ? 1 : 0;
1254ba319b5SDimitry Andric if (LSBase->isIndexed() && Base.getResNo() == IndexResNo)
1264ba319b5SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(LSBase->getOffset())) {
1274ba319b5SDimitry Andric auto Off = C->getSExtValue();
1284ba319b5SDimitry Andric if (LSBase->getAddressingMode() == ISD::PRE_DEC ||
1294ba319b5SDimitry Andric LSBase->getAddressingMode() == ISD::POST_DEC)
1304ba319b5SDimitry Andric Offset -= Off;
1314ba319b5SDimitry Andric else
1324ba319b5SDimitry Andric Offset += Off;
133*b5893f02SDimitry Andric Base = DAG.getTargetLoweringInfo().unwrapAddress(LSBase->getBasePtr());
1344ba319b5SDimitry Andric continue;
1354ba319b5SDimitry Andric }
1364ba319b5SDimitry Andric break;
1374ba319b5SDimitry Andric }
1384ba319b5SDimitry Andric }
1394ba319b5SDimitry Andric // If we get here break out of the loop.
1404ba319b5SDimitry Andric break;
141edd7eaddSDimitry Andric }
142edd7eaddSDimitry Andric
143edd7eaddSDimitry Andric if (Base->getOpcode() == ISD::ADD) {
144edd7eaddSDimitry Andric // TODO: The following code appears to be needless as it just
145edd7eaddSDimitry Andric // bails on some Ptrs early, reducing the cases where we
146edd7eaddSDimitry Andric // find equivalence. We should be able to remove this.
147edd7eaddSDimitry Andric // Inside a loop the current BASE pointer is calculated using an ADD and a
148edd7eaddSDimitry Andric // MUL instruction. In this case Base is the actual BASE pointer.
149edd7eaddSDimitry Andric // (i64 add (i64 %array_ptr)
150edd7eaddSDimitry Andric // (i64 mul (i64 %induction_var)
151edd7eaddSDimitry Andric // (i64 %element_size)))
152edd7eaddSDimitry Andric if (Base->getOperand(1)->getOpcode() == ISD::MUL)
153edd7eaddSDimitry Andric return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
154edd7eaddSDimitry Andric
155edd7eaddSDimitry Andric // Look at Base + Index + Offset cases.
156edd7eaddSDimitry Andric Index = Base->getOperand(1);
157edd7eaddSDimitry Andric SDValue PotentialBase = Base->getOperand(0);
158edd7eaddSDimitry Andric
159edd7eaddSDimitry Andric // Skip signextends.
160edd7eaddSDimitry Andric if (Index->getOpcode() == ISD::SIGN_EXTEND) {
161edd7eaddSDimitry Andric Index = Index->getOperand(0);
162edd7eaddSDimitry Andric IsIndexSignExt = true;
163edd7eaddSDimitry Andric }
164edd7eaddSDimitry Andric
165edd7eaddSDimitry Andric // Check if Index Offset pattern
166edd7eaddSDimitry Andric if (Index->getOpcode() != ISD::ADD ||
167edd7eaddSDimitry Andric !isa<ConstantSDNode>(Index->getOperand(1)))
168edd7eaddSDimitry Andric return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
169edd7eaddSDimitry Andric
170edd7eaddSDimitry Andric Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
171edd7eaddSDimitry Andric Index = Index->getOperand(0);
172edd7eaddSDimitry Andric if (Index->getOpcode() == ISD::SIGN_EXTEND) {
173edd7eaddSDimitry Andric Index = Index->getOperand(0);
174edd7eaddSDimitry Andric IsIndexSignExt = true;
175edd7eaddSDimitry Andric } else
176edd7eaddSDimitry Andric IsIndexSignExt = false;
177edd7eaddSDimitry Andric Base = PotentialBase;
178edd7eaddSDimitry Andric }
179edd7eaddSDimitry Andric return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
180edd7eaddSDimitry Andric }
181