]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp
MFV: r335802
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / CodeGen / SelectionDAG / SelectionDAGAddressAnalysis.cpp
1 //==- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp - DAG Address Analysis --==//
2 //
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 //===----------------------------------------------------------------------===//
9
10 #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
11 #include "llvm/CodeGen/ISDOpcodes.h"
12 #include "llvm/CodeGen/MachineFrameInfo.h"
13 #include "llvm/CodeGen/MachineFunction.h"
14 #include "llvm/CodeGen/SelectionDAG.h"
15 #include "llvm/CodeGen/SelectionDAGNodes.h"
16 #include "llvm/CodeGen/TargetLowering.h"
17 #include "llvm/Support/Casting.h"
18 #include <cstdint>
19
20 using namespace llvm;
21
22 bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other,
23                                      const SelectionDAG &DAG, int64_t &Off) {
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 non-equal FrameIndexes - If both frame indices are fixed
63     // we know their relative offsets and can compare them. Otherwise
64     // we must be conservative.
65     if (auto *A = dyn_cast<FrameIndexSDNode>(Base))
66       if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base))
67         if (MFI.isFixedObjectIndex(A->getIndex()) &&
68             MFI.isFixedObjectIndex(B->getIndex())) {
69           Off += MFI.getObjectOffset(B->getIndex()) -
70                  MFI.getObjectOffset(A->getIndex());
71           return true;
72         }
73   }
74   return false;
75 }
76
77 /// Parses tree in Ptr for base, index, offset addresses.
78 BaseIndexOffset BaseIndexOffset::match(LSBaseSDNode *N,
79                                        const SelectionDAG &DAG) {
80   SDValue Ptr = N->getBasePtr();
81
82   // (((B + I*M) + c)) + c ...
83   SDValue Base = DAG.getTargetLoweringInfo().unwrapAddress(Ptr);
84   SDValue Index = SDValue();
85   int64_t Offset = 0;
86   bool IsIndexSignExt = false;
87
88   // pre-inc/pre-dec ops are components of EA.
89   if (N->getAddressingMode() == ISD::PRE_INC) {
90     if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
91       Offset += C->getSExtValue();
92     else // If unknown, give up now.
93       return BaseIndexOffset(SDValue(), SDValue(), 0, false);
94   } else if (N->getAddressingMode() == ISD::PRE_DEC) {
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   }
100
101   // Consume constant adds & ors with appropriate masking.
102   while (Base->getOpcode() == ISD::ADD || Base->getOpcode() == ISD::OR) {
103     if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {
104       // Only consider ORs which act as adds.
105       if (Base->getOpcode() == ISD::OR &&
106           !DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue()))
107         break;
108       Offset += C->getSExtValue();
109       Base = Base->getOperand(0);
110       continue;
111     }
112     break;
113   }
114
115   if (Base->getOpcode() == ISD::ADD) {
116     // TODO: The following code appears to be needless as it just
117     //       bails on some Ptrs early, reducing the cases where we
118     //       find equivalence. We should be able to remove this.
119     // Inside a loop the current BASE pointer is calculated using an ADD and a
120     // MUL instruction. In this case Base is the actual BASE pointer.
121     // (i64 add (i64 %array_ptr)
122     //          (i64 mul (i64 %induction_var)
123     //                   (i64 %element_size)))
124     if (Base->getOperand(1)->getOpcode() == ISD::MUL)
125       return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
126
127     // Look at Base + Index + Offset cases.
128     Index = Base->getOperand(1);
129     SDValue PotentialBase = Base->getOperand(0);
130
131     // Skip signextends.
132     if (Index->getOpcode() == ISD::SIGN_EXTEND) {
133       Index = Index->getOperand(0);
134       IsIndexSignExt = true;
135     }
136
137     // Check if Index Offset pattern
138     if (Index->getOpcode() != ISD::ADD ||
139         !isa<ConstantSDNode>(Index->getOperand(1)))
140       return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
141
142     Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();
143     Index = Index->getOperand(0);
144     if (Index->getOpcode() == ISD::SIGN_EXTEND) {
145       Index = Index->getOperand(0);
146       IsIndexSignExt = true;
147     } else
148       IsIndexSignExt = false;
149     Base = PotentialBase;
150   }
151   return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);
152 }