1 //==- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp - DAG Address Analysis --==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
10 #include "llvm/CodeGen/ISDOpcodes.h"
11 #include "llvm/CodeGen/MachineFrameInfo.h"
12 #include "llvm/CodeGen/MachineFunction.h"
13 #include "llvm/CodeGen/SelectionDAG.h"
14 #include "llvm/CodeGen/SelectionDAGNodes.h"
15 #include "llvm/CodeGen/TargetLowering.h"
16 #include "llvm/Support/Casting.h"
17 #include <cstdint>
18 
19 using namespace llvm;
20 
21 bool BaseIndexOffset::equalBaseIndex(const BaseIndexOffset &Other,
22                                      const SelectionDAG &DAG,
23                                      int64_t &Off) const {
24   // Conservatively fail if we a match failed..
25   if (!Base.getNode() || !Other.Base.getNode())
26     return false;
27   // Initial Offset difference.
28   Off = Other.Offset - Offset;
29 
30   if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {
31     // Trivial match.
32     if (Other.Base == Base)
33       return true;
34 
35     // Match GlobalAddresses
36     if (auto *A = dyn_cast<GlobalAddressSDNode>(Base))
37       if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))
38         if (A->getGlobal() == B->getGlobal()) {
39           Off += B->getOffset() - A->getOffset();
40           return true;
41         }
42 
43     // Match Constants
44     if (auto *A = dyn_cast<ConstantPoolSDNode>(Base))
45       if (auto *B = dyn_cast<ConstantPoolSDNode>(Other.Base)) {
46         bool IsMatch =
47             A->isMachineConstantPoolEntry() == B->isMachineConstantPoolEntry();
48         if (IsMatch) {
49           if (A->isMachineConstantPoolEntry())
50             IsMatch = A->getMachineCPVal() == B->getMachineCPVal();
51           else
52             IsMatch = A->getConstVal() == B->getConstVal();
53         }
54         if (IsMatch) {
55           Off += B->getOffset() - A->getOffset();
56           return true;
57         }
58       }
59 
60     const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
61 
62     // Match FrameIndexes.
63     if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
64       if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base)) {
65         // Equal FrameIndexes - offsets are directly comparable.
66         if (A->getIndex() == B->getIndex())
67           return true;
68         // Non-equal FrameIndexes - If both frame indices are fixed
69         // we know their relative offsets and can compare them. Otherwise
70         // we must be conservative.
71         if (MFI.isFixedObjectIndex(A->getIndex()) &&
72             MFI.isFixedObjectIndex(B->getIndex())) {
73           Off += MFI.getObjectOffset(B->getIndex()) -
74                  MFI.getObjectOffset(A->getIndex());
75           return true;
76         }
77       }
78   }
79   return false;
80 }
81 
82 /// Parses tree in Ptr for base, index, offset addresses.
83 BaseIndexOffset BaseIndexOffset::match(const LSBaseSDNode *N,
84                                        const SelectionDAG &DAG) {
85   SDValue Ptr = N->getBasePtr();
86 
87   // (((B + I*M) + c)) + c ...
88   SDValue Base = DAG.getTargetLoweringInfo().unwrapAddress(Ptr);
89   SDValue Index = SDValue();
90   int64_t Offset = 0;
91   bool IsIndexSignExt = false;
92 
93   // pre-inc/pre-dec ops are components of EA.
94   if (N->getAddressingMode() == ISD::PRE_INC) {
95     if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
96       Offset += C->getSExtValue();
97     else // If unknown, give up now.
98       return BaseIndexOffset(SDValue(), SDValue(), 0, false);
99   } else if (N->getAddressingMode() == ISD::PRE_DEC) {
100     if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
101       Offset -= C->getSExtValue();
102     else // If unknown, give up now.
103       return BaseIndexOffset(SDValue(), SDValue(), 0, false);
104   }
105 
106   // Consume constant adds & ors with appropriate masking.
107   while (true) {
108     switch (Base->getOpcode()) {
109     case ISD::OR:
110       // Only consider ORs which act as adds.
111       if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1)))
112         if (DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue())) {
113           Offset += C->getSExtValue();
114           Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
115           continue;
116         }
117       break;
118     case ISD::ADD:
119       if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
120         Offset += C->getSExtValue();
121         Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));
122         continue;
123       }
124       break;
125     case ISD::LOAD:
126     case ISD::STORE: {
127       auto *LSBase = cast<LSBaseSDNode>(Base.getNode());
128       unsigned int IndexResNo = (Base->getOpcode() == ISD::LOAD) ? 1 : 0;
129       if (LSBase->isIndexed() && Base.getResNo() == IndexResNo)
130         if (auto *C = dyn_cast<ConstantSDNode>(LSBase->getOffset())) {
131           auto Off = C->getSExtValue();
132           if (LSBase->getAddressingMode() == ISD::PRE_DEC ||
133               LSBase->getAddressingMode() == ISD::POST_DEC)
134             Offset -= Off;
135           else
136             Offset += Off;
137           Base = DAG.getTargetLoweringInfo().unwrapAddress(LSBase->getBasePtr());
138           continue;
139         }
140       break;
141     }
142     }
143     // If we get here break out of the loop.
144     break;
145   }
146 
147   if (Base->getOpcode() == ISD::ADD) {
148     // TODO: The following code appears to be needless as it just
149     //       bails on some Ptrs early, reducing the cases where we
150     //       find equivalence. We should be able to remove this.
151     // Inside a loop the current BASE pointer is calculated using an ADD and a
152     // MUL instruction. In this case Base is the actual BASE pointer.
153     // (i64 add (i64 %array_ptr)
154     //          (i64 mul (i64 %induction_var)
155     //                   (i64 %element_size)))
156     if (Base->getOperand(1)->getOpcode() == ISD::MUL)
157       return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
158 
159     // Look at Base + Index + Offset cases.
160     Index = Base->getOperand(1);
161     SDValue PotentialBase = Base->getOperand(0);
162 
163     // Skip signextends.
164     if (Index->getOpcode() == ISD::SIGN_EXTEND) {
165       Index = Index->getOperand(0);
166       IsIndexSignExt = true;
167     }
168 
169     // Check if Index Offset pattern
170     if (Index->getOpcode() != ISD::ADD ||
171         !isa<ConstantSDNode>(Index->getOperand(1)))
172       return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
173 
174     Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
175     Index = Index->getOperand(0);
176     if (Index->getOpcode() == ISD::SIGN_EXTEND) {
177       Index = Index->getOperand(0);
178       IsIndexSignExt = true;
179     } else
180       IsIndexSignExt = false;
181     Base = PotentialBase;
182   }
183   return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
184 }
185 
186 
187 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
188 
189 LLVM_DUMP_METHOD void BaseIndexOffset::dump() const {
190   print(dbgs());
191 }
192 
193 void BaseIndexOffset::print(raw_ostream& OS) const {
194   OS << "BaseIndexOffset base=[";
195   Base->print(OS);
196   OS << "] index=[";
197   if (Index)
198     Index->print(OS);
199   OS << "] offset=" << Offset;
200 }
201 
202 #endif
203