1*0b57cec5SDimitry Andric //==- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp - DAG Address Analysis --==// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" 10*0b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h" 11*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 12*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 13*0b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h" 14*0b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h" 15*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 16*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 17*0b57cec5SDimitry Andric #include <cstdint> 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric using namespace llvm; 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric bool BaseIndexOffset::equalBaseIndex(const BaseIndexOffset &Other, 22*0b57cec5SDimitry Andric const SelectionDAG &DAG, 23*0b57cec5SDimitry Andric int64_t &Off) const { 24*0b57cec5SDimitry Andric // Conservatively fail if we a match failed.. 25*0b57cec5SDimitry Andric if (!Base.getNode() || !Other.Base.getNode()) 26*0b57cec5SDimitry Andric return false; 27*0b57cec5SDimitry Andric if (!hasValidOffset() || !Other.hasValidOffset()) 28*0b57cec5SDimitry Andric return false; 29*0b57cec5SDimitry Andric // Initial Offset difference. 30*0b57cec5SDimitry Andric Off = *Other.Offset - *Offset; 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) { 33*0b57cec5SDimitry Andric // Trivial match. 34*0b57cec5SDimitry Andric if (Other.Base == Base) 35*0b57cec5SDimitry Andric return true; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric // Match GlobalAddresses 38*0b57cec5SDimitry Andric if (auto *A = dyn_cast<GlobalAddressSDNode>(Base)) 39*0b57cec5SDimitry Andric if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base)) 40*0b57cec5SDimitry Andric if (A->getGlobal() == B->getGlobal()) { 41*0b57cec5SDimitry Andric Off += B->getOffset() - A->getOffset(); 42*0b57cec5SDimitry Andric return true; 43*0b57cec5SDimitry Andric } 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric // Match Constants 46*0b57cec5SDimitry Andric if (auto *A = dyn_cast<ConstantPoolSDNode>(Base)) 47*0b57cec5SDimitry Andric if (auto *B = dyn_cast<ConstantPoolSDNode>(Other.Base)) { 48*0b57cec5SDimitry Andric bool IsMatch = 49*0b57cec5SDimitry Andric A->isMachineConstantPoolEntry() == B->isMachineConstantPoolEntry(); 50*0b57cec5SDimitry Andric if (IsMatch) { 51*0b57cec5SDimitry Andric if (A->isMachineConstantPoolEntry()) 52*0b57cec5SDimitry Andric IsMatch = A->getMachineCPVal() == B->getMachineCPVal(); 53*0b57cec5SDimitry Andric else 54*0b57cec5SDimitry Andric IsMatch = A->getConstVal() == B->getConstVal(); 55*0b57cec5SDimitry Andric } 56*0b57cec5SDimitry Andric if (IsMatch) { 57*0b57cec5SDimitry Andric Off += B->getOffset() - A->getOffset(); 58*0b57cec5SDimitry Andric return true; 59*0b57cec5SDimitry Andric } 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric // Match FrameIndexes. 65*0b57cec5SDimitry Andric if (auto *A = dyn_cast<FrameIndexSDNode>(Base)) 66*0b57cec5SDimitry Andric if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base)) { 67*0b57cec5SDimitry Andric // Equal FrameIndexes - offsets are directly comparable. 68*0b57cec5SDimitry Andric if (A->getIndex() == B->getIndex()) 69*0b57cec5SDimitry Andric return true; 70*0b57cec5SDimitry Andric // Non-equal FrameIndexes - If both frame indices are fixed 71*0b57cec5SDimitry Andric // we know their relative offsets and can compare them. Otherwise 72*0b57cec5SDimitry Andric // we must be conservative. 73*0b57cec5SDimitry Andric if (MFI.isFixedObjectIndex(A->getIndex()) && 74*0b57cec5SDimitry Andric MFI.isFixedObjectIndex(B->getIndex())) { 75*0b57cec5SDimitry Andric Off += MFI.getObjectOffset(B->getIndex()) - 76*0b57cec5SDimitry Andric MFI.getObjectOffset(A->getIndex()); 77*0b57cec5SDimitry Andric return true; 78*0b57cec5SDimitry Andric } 79*0b57cec5SDimitry Andric } 80*0b57cec5SDimitry Andric } 81*0b57cec5SDimitry Andric return false; 82*0b57cec5SDimitry Andric } 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric bool BaseIndexOffset::computeAliasing(const SDNode *Op0, 85*0b57cec5SDimitry Andric const Optional<int64_t> NumBytes0, 86*0b57cec5SDimitry Andric const SDNode *Op1, 87*0b57cec5SDimitry Andric const Optional<int64_t> NumBytes1, 88*0b57cec5SDimitry Andric const SelectionDAG &DAG, bool &IsAlias) { 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric BaseIndexOffset BasePtr0 = match(Op0, DAG); 91*0b57cec5SDimitry Andric BaseIndexOffset BasePtr1 = match(Op1, DAG); 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric if (!(BasePtr0.getBase().getNode() && BasePtr1.getBase().getNode())) 94*0b57cec5SDimitry Andric return false; 95*0b57cec5SDimitry Andric int64_t PtrDiff; 96*0b57cec5SDimitry Andric if (NumBytes0.hasValue() && NumBytes1.hasValue() && 97*0b57cec5SDimitry Andric BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) { 98*0b57cec5SDimitry Andric // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the 99*0b57cec5SDimitry Andric // following situations arise: 100*0b57cec5SDimitry Andric IsAlias = !( 101*0b57cec5SDimitry Andric // [----BasePtr0----] 102*0b57cec5SDimitry Andric // [---BasePtr1--] 103*0b57cec5SDimitry Andric // ========PtrDiff========> 104*0b57cec5SDimitry Andric (*NumBytes0 <= PtrDiff) || 105*0b57cec5SDimitry Andric // [----BasePtr0----] 106*0b57cec5SDimitry Andric // [---BasePtr1--] 107*0b57cec5SDimitry Andric // =====(-PtrDiff)====> 108*0b57cec5SDimitry Andric (PtrDiff + *NumBytes1 <= 0)); // i.e. *NumBytes1 < -PtrDiff. 109*0b57cec5SDimitry Andric return true; 110*0b57cec5SDimitry Andric } 111*0b57cec5SDimitry Andric // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be 112*0b57cec5SDimitry Andric // able to calculate their relative offset if at least one arises 113*0b57cec5SDimitry Andric // from an alloca. However, these allocas cannot overlap and we 114*0b57cec5SDimitry Andric // can infer there is no alias. 115*0b57cec5SDimitry Andric if (auto *A = dyn_cast<FrameIndexSDNode>(BasePtr0.getBase())) 116*0b57cec5SDimitry Andric if (auto *B = dyn_cast<FrameIndexSDNode>(BasePtr1.getBase())) { 117*0b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 118*0b57cec5SDimitry Andric // If the base are the same frame index but the we couldn't find a 119*0b57cec5SDimitry Andric // constant offset, (indices are different) be conservative. 120*0b57cec5SDimitry Andric if (A != B && (!MFI.isFixedObjectIndex(A->getIndex()) || 121*0b57cec5SDimitry Andric !MFI.isFixedObjectIndex(B->getIndex()))) { 122*0b57cec5SDimitry Andric IsAlias = false; 123*0b57cec5SDimitry Andric return true; 124*0b57cec5SDimitry Andric } 125*0b57cec5SDimitry Andric } 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric bool IsFI0 = isa<FrameIndexSDNode>(BasePtr0.getBase()); 128*0b57cec5SDimitry Andric bool IsFI1 = isa<FrameIndexSDNode>(BasePtr1.getBase()); 129*0b57cec5SDimitry Andric bool IsGV0 = isa<GlobalAddressSDNode>(BasePtr0.getBase()); 130*0b57cec5SDimitry Andric bool IsGV1 = isa<GlobalAddressSDNode>(BasePtr1.getBase()); 131*0b57cec5SDimitry Andric bool IsCV0 = isa<ConstantPoolSDNode>(BasePtr0.getBase()); 132*0b57cec5SDimitry Andric bool IsCV1 = isa<ConstantPoolSDNode>(BasePtr1.getBase()); 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric // If of mismatched base types or checkable indices we can check 135*0b57cec5SDimitry Andric // they do not alias. 136*0b57cec5SDimitry Andric if ((BasePtr0.getIndex() == BasePtr1.getIndex() || (IsFI0 != IsFI1) || 137*0b57cec5SDimitry Andric (IsGV0 != IsGV1) || (IsCV0 != IsCV1)) && 138*0b57cec5SDimitry Andric (IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) { 139*0b57cec5SDimitry Andric IsAlias = false; 140*0b57cec5SDimitry Andric return true; 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric return false; // Cannot determine whether the pointers alias. 143*0b57cec5SDimitry Andric } 144*0b57cec5SDimitry Andric 145*0b57cec5SDimitry Andric bool BaseIndexOffset::contains(const SelectionDAG &DAG, int64_t BitSize, 146*0b57cec5SDimitry Andric const BaseIndexOffset &Other, 147*0b57cec5SDimitry Andric int64_t OtherBitSize, int64_t &BitOffset) const { 148*0b57cec5SDimitry Andric int64_t Offset; 149*0b57cec5SDimitry Andric if (!equalBaseIndex(Other, DAG, Offset)) 150*0b57cec5SDimitry Andric return false; 151*0b57cec5SDimitry Andric if (Offset >= 0) { 152*0b57cec5SDimitry Andric // Other is after *this: 153*0b57cec5SDimitry Andric // [-------*this---------] 154*0b57cec5SDimitry Andric // [---Other--] 155*0b57cec5SDimitry Andric // ==Offset==> 156*0b57cec5SDimitry Andric BitOffset = 8 * Offset; 157*0b57cec5SDimitry Andric return BitOffset + OtherBitSize <= BitSize; 158*0b57cec5SDimitry Andric } 159*0b57cec5SDimitry Andric // Other starts strictly before *this, it cannot be fully contained. 160*0b57cec5SDimitry Andric // [-------*this---------] 161*0b57cec5SDimitry Andric // [--Other--] 162*0b57cec5SDimitry Andric return false; 163*0b57cec5SDimitry Andric } 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric /// Parses tree in Ptr for base, index, offset addresses. 166*0b57cec5SDimitry Andric static BaseIndexOffset matchLSNode(const LSBaseSDNode *N, 167*0b57cec5SDimitry Andric const SelectionDAG &DAG) { 168*0b57cec5SDimitry Andric SDValue Ptr = N->getBasePtr(); 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric // (((B + I*M) + c)) + c ... 171*0b57cec5SDimitry Andric SDValue Base = DAG.getTargetLoweringInfo().unwrapAddress(Ptr); 172*0b57cec5SDimitry Andric SDValue Index = SDValue(); 173*0b57cec5SDimitry Andric int64_t Offset = 0; 174*0b57cec5SDimitry Andric bool IsIndexSignExt = false; 175*0b57cec5SDimitry Andric 176*0b57cec5SDimitry Andric // pre-inc/pre-dec ops are components of EA. 177*0b57cec5SDimitry Andric if (N->getAddressingMode() == ISD::PRE_INC) { 178*0b57cec5SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset())) 179*0b57cec5SDimitry Andric Offset += C->getSExtValue(); 180*0b57cec5SDimitry Andric else // If unknown, give up now. 181*0b57cec5SDimitry Andric return BaseIndexOffset(SDValue(), SDValue(), 0, false); 182*0b57cec5SDimitry Andric } else if (N->getAddressingMode() == ISD::PRE_DEC) { 183*0b57cec5SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset())) 184*0b57cec5SDimitry Andric Offset -= C->getSExtValue(); 185*0b57cec5SDimitry Andric else // If unknown, give up now. 186*0b57cec5SDimitry Andric return BaseIndexOffset(SDValue(), SDValue(), 0, false); 187*0b57cec5SDimitry Andric } 188*0b57cec5SDimitry Andric 189*0b57cec5SDimitry Andric // Consume constant adds & ors with appropriate masking. 190*0b57cec5SDimitry Andric while (true) { 191*0b57cec5SDimitry Andric switch (Base->getOpcode()) { 192*0b57cec5SDimitry Andric case ISD::OR: 193*0b57cec5SDimitry Andric // Only consider ORs which act as adds. 194*0b57cec5SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) 195*0b57cec5SDimitry Andric if (DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue())) { 196*0b57cec5SDimitry Andric Offset += C->getSExtValue(); 197*0b57cec5SDimitry Andric Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0)); 198*0b57cec5SDimitry Andric continue; 199*0b57cec5SDimitry Andric } 200*0b57cec5SDimitry Andric break; 201*0b57cec5SDimitry Andric case ISD::ADD: 202*0b57cec5SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) { 203*0b57cec5SDimitry Andric Offset += C->getSExtValue(); 204*0b57cec5SDimitry Andric Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0)); 205*0b57cec5SDimitry Andric continue; 206*0b57cec5SDimitry Andric } 207*0b57cec5SDimitry Andric break; 208*0b57cec5SDimitry Andric case ISD::LOAD: 209*0b57cec5SDimitry Andric case ISD::STORE: { 210*0b57cec5SDimitry Andric auto *LSBase = cast<LSBaseSDNode>(Base.getNode()); 211*0b57cec5SDimitry Andric unsigned int IndexResNo = (Base->getOpcode() == ISD::LOAD) ? 1 : 0; 212*0b57cec5SDimitry Andric if (LSBase->isIndexed() && Base.getResNo() == IndexResNo) 213*0b57cec5SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(LSBase->getOffset())) { 214*0b57cec5SDimitry Andric auto Off = C->getSExtValue(); 215*0b57cec5SDimitry Andric if (LSBase->getAddressingMode() == ISD::PRE_DEC || 216*0b57cec5SDimitry Andric LSBase->getAddressingMode() == ISD::POST_DEC) 217*0b57cec5SDimitry Andric Offset -= Off; 218*0b57cec5SDimitry Andric else 219*0b57cec5SDimitry Andric Offset += Off; 220*0b57cec5SDimitry Andric Base = DAG.getTargetLoweringInfo().unwrapAddress(LSBase->getBasePtr()); 221*0b57cec5SDimitry Andric continue; 222*0b57cec5SDimitry Andric } 223*0b57cec5SDimitry Andric break; 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric } 226*0b57cec5SDimitry Andric // If we get here break out of the loop. 227*0b57cec5SDimitry Andric break; 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric if (Base->getOpcode() == ISD::ADD) { 231*0b57cec5SDimitry Andric // TODO: The following code appears to be needless as it just 232*0b57cec5SDimitry Andric // bails on some Ptrs early, reducing the cases where we 233*0b57cec5SDimitry Andric // find equivalence. We should be able to remove this. 234*0b57cec5SDimitry Andric // Inside a loop the current BASE pointer is calculated using an ADD and a 235*0b57cec5SDimitry Andric // MUL instruction. In this case Base is the actual BASE pointer. 236*0b57cec5SDimitry Andric // (i64 add (i64 %array_ptr) 237*0b57cec5SDimitry Andric // (i64 mul (i64 %induction_var) 238*0b57cec5SDimitry Andric // (i64 %element_size))) 239*0b57cec5SDimitry Andric if (Base->getOperand(1)->getOpcode() == ISD::MUL) 240*0b57cec5SDimitry Andric return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt); 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric // Look at Base + Index + Offset cases. 243*0b57cec5SDimitry Andric Index = Base->getOperand(1); 244*0b57cec5SDimitry Andric SDValue PotentialBase = Base->getOperand(0); 245*0b57cec5SDimitry Andric 246*0b57cec5SDimitry Andric // Skip signextends. 247*0b57cec5SDimitry Andric if (Index->getOpcode() == ISD::SIGN_EXTEND) { 248*0b57cec5SDimitry Andric Index = Index->getOperand(0); 249*0b57cec5SDimitry Andric IsIndexSignExt = true; 250*0b57cec5SDimitry Andric } 251*0b57cec5SDimitry Andric 252*0b57cec5SDimitry Andric // Check if Index Offset pattern 253*0b57cec5SDimitry Andric if (Index->getOpcode() != ISD::ADD || 254*0b57cec5SDimitry Andric !isa<ConstantSDNode>(Index->getOperand(1))) 255*0b57cec5SDimitry Andric return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt); 256*0b57cec5SDimitry Andric 257*0b57cec5SDimitry Andric Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue(); 258*0b57cec5SDimitry Andric Index = Index->getOperand(0); 259*0b57cec5SDimitry Andric if (Index->getOpcode() == ISD::SIGN_EXTEND) { 260*0b57cec5SDimitry Andric Index = Index->getOperand(0); 261*0b57cec5SDimitry Andric IsIndexSignExt = true; 262*0b57cec5SDimitry Andric } else 263*0b57cec5SDimitry Andric IsIndexSignExt = false; 264*0b57cec5SDimitry Andric Base = PotentialBase; 265*0b57cec5SDimitry Andric } 266*0b57cec5SDimitry Andric return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt); 267*0b57cec5SDimitry Andric } 268*0b57cec5SDimitry Andric 269*0b57cec5SDimitry Andric BaseIndexOffset BaseIndexOffset::match(const SDNode *N, 270*0b57cec5SDimitry Andric const SelectionDAG &DAG) { 271*0b57cec5SDimitry Andric if (const auto *LS0 = dyn_cast<LSBaseSDNode>(N)) 272*0b57cec5SDimitry Andric return matchLSNode(LS0, DAG); 273*0b57cec5SDimitry Andric if (const auto *LN = dyn_cast<LifetimeSDNode>(N)) { 274*0b57cec5SDimitry Andric if (LN->hasOffset()) 275*0b57cec5SDimitry Andric return BaseIndexOffset(LN->getOperand(1), SDValue(), LN->getOffset(), 276*0b57cec5SDimitry Andric false); 277*0b57cec5SDimitry Andric return BaseIndexOffset(LN->getOperand(1), SDValue(), false); 278*0b57cec5SDimitry Andric } 279*0b57cec5SDimitry Andric return BaseIndexOffset(); 280*0b57cec5SDimitry Andric } 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric LLVM_DUMP_METHOD void BaseIndexOffset::dump() const { 285*0b57cec5SDimitry Andric print(dbgs()); 286*0b57cec5SDimitry Andric } 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric void BaseIndexOffset::print(raw_ostream& OS) const { 289*0b57cec5SDimitry Andric OS << "BaseIndexOffset base=["; 290*0b57cec5SDimitry Andric Base->print(OS); 291*0b57cec5SDimitry Andric OS << "] index=["; 292*0b57cec5SDimitry Andric if (Index) 293*0b57cec5SDimitry Andric Index->print(OS); 294*0b57cec5SDimitry Andric OS << "] offset=" << Offset; 295*0b57cec5SDimitry Andric } 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric #endif 298