brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.8 KiB · 8f08046 Raw
327 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"10#include "llvm/Analysis/MemoryLocation.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/IR/GlobalAlias.h"18#include "llvm/Support/Casting.h"19#include "llvm/Support/Debug.h"20#include <cstdint>21 22using namespace llvm;23 24bool BaseIndexOffset::equalBaseIndex(const BaseIndexOffset &Other,25                                     const SelectionDAG &DAG,26                                     int64_t &Off) const {27  // Conservatively fail if we a match failed..28  if (!Base.getNode() || !Other.Base.getNode())29    return false;30  if (!hasValidOffset() || !Other.hasValidOffset())31    return false;32  // Initial Offset difference.33  Off = *Other.Offset - *Offset;34 35  if ((Other.Index == Index) && (Other.IsIndexSignExt == IsIndexSignExt)) {36    // Trivial match.37    if (Other.Base == Base)38      return true;39 40    // Match GlobalAddresses41    if (auto *A = dyn_cast<GlobalAddressSDNode>(Base)) {42      if (auto *B = dyn_cast<GlobalAddressSDNode>(Other.Base))43        if (A->getGlobal() == B->getGlobal()) {44          Off += B->getOffset() - A->getOffset();45          return true;46        }47 48      return false;49    }50 51    // Match Constants52    if (auto *A = dyn_cast<ConstantPoolSDNode>(Base)) {53      if (auto *B = dyn_cast<ConstantPoolSDNode>(Other.Base)) {54        bool IsMatch =55            A->isMachineConstantPoolEntry() == B->isMachineConstantPoolEntry();56        if (IsMatch) {57          if (A->isMachineConstantPoolEntry())58            IsMatch = A->getMachineCPVal() == B->getMachineCPVal();59          else60            IsMatch = A->getConstVal() == B->getConstVal();61        }62        if (IsMatch) {63          Off += B->getOffset() - A->getOffset();64          return true;65        }66      }67 68      return false;69    }70 71    // Match FrameIndexes.72    if (auto *A = dyn_cast<FrameIndexSDNode>(Base))73      if (auto *B = dyn_cast<FrameIndexSDNode>(Other.Base)) {74        // Equal FrameIndexes - offsets are directly comparable.75        if (A->getIndex() == B->getIndex())76          return true;77        // Non-equal FrameIndexes - If both frame indices are fixed78        // we know their relative offsets and can compare them. Otherwise79        // we must be conservative.80        const MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();81        if (MFI.isFixedObjectIndex(A->getIndex()) &&82            MFI.isFixedObjectIndex(B->getIndex())) {83          Off += MFI.getObjectOffset(B->getIndex()) -84                 MFI.getObjectOffset(A->getIndex());85          return true;86        }87      }88  }89 90  return false;91}92 93bool BaseIndexOffset::computeAliasing(const SDNode *Op0,94                                      const LocationSize NumBytes0,95                                      const SDNode *Op1,96                                      const LocationSize NumBytes1,97                                      const SelectionDAG &DAG, bool &IsAlias) {98  BaseIndexOffset BasePtr0 = match(Op0, DAG);99  if (!BasePtr0.getBase().getNode())100    return false;101 102  BaseIndexOffset BasePtr1 = match(Op1, DAG);103  if (!BasePtr1.getBase().getNode())104    return false;105 106  int64_t PtrDiff;107  if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) {108    // If the size of memory access is unknown, do not use it to analysis.109    // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the110    // following situations arise:111    if (PtrDiff >= 0 && NumBytes0.hasValue() && !NumBytes0.isScalable()) {112      // [----BasePtr0----]113      //                         [---BasePtr1--]114      // ========PtrDiff========>115      IsAlias = !(static_cast<int64_t>(NumBytes0.getValue().getFixedValue()) <=116                  PtrDiff);117      return true;118    }119    if (PtrDiff < 0 && NumBytes1.hasValue() && !NumBytes1.isScalable()) {120      //                     [----BasePtr0----]121      // [---BasePtr1--]122      // =====(-PtrDiff)====>123      IsAlias = !((PtrDiff + static_cast<int64_t>(124                                 NumBytes1.getValue().getFixedValue())) <= 0);125      return true;126    }127    return false;128  }129  // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be130  // able to calculate their relative offset if at least one arises131  // from an alloca. However, these allocas cannot overlap and we132  // can infer there is no alias.133  if (auto *A = dyn_cast<FrameIndexSDNode>(BasePtr0.getBase()))134    if (auto *B = dyn_cast<FrameIndexSDNode>(BasePtr1.getBase())) {135      MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();136      // If the base are the same frame index but the we couldn't find a137      // constant offset, (indices are different) be conservative.138      if (A->getIndex() != B->getIndex() && (!MFI.isFixedObjectIndex(A->getIndex()) ||139                     !MFI.isFixedObjectIndex(B->getIndex()))) {140        IsAlias = false;141        return true;142      }143    }144 145  bool IsFI0 = isa<FrameIndexSDNode>(BasePtr0.getBase());146  bool IsFI1 = isa<FrameIndexSDNode>(BasePtr1.getBase());147  bool IsGV0 = isa<GlobalAddressSDNode>(BasePtr0.getBase());148  bool IsGV1 = isa<GlobalAddressSDNode>(BasePtr1.getBase());149  bool IsCV0 = isa<ConstantPoolSDNode>(BasePtr0.getBase());150  bool IsCV1 = isa<ConstantPoolSDNode>(BasePtr1.getBase());151 152  if ((IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) {153    // We can derive NoAlias In case of mismatched base types.154    if (IsFI0 != IsFI1 || IsGV0 != IsGV1 || IsCV0 != IsCV1) {155      IsAlias = false;156      return true;157    }158    if (IsGV0 && IsGV1) {159      auto *GV0 = cast<GlobalAddressSDNode>(BasePtr0.getBase())->getGlobal();160      auto *GV1 = cast<GlobalAddressSDNode>(BasePtr1.getBase())->getGlobal();161      // It doesn't make sense to access one global value using another globals162      // values address, so we can assume that there is no aliasing in case of163      // two different globals (unless we have symbols that may indirectly point164      // to each other).165      // FIXME: This is perhaps a bit too defensive. We could try to follow the166      // chain with aliasee information for GlobalAlias variables to find out if167      // we indirect symbols may alias or not.168      if (GV0 != GV1 && !isa<GlobalAlias>(GV0) && !isa<GlobalAlias>(GV1)) {169        IsAlias = false;170        return true;171      }172    }173  }174  return false; // Cannot determine whether the pointers alias.175}176 177bool BaseIndexOffset::contains(const SelectionDAG &DAG, int64_t BitSize,178                               const BaseIndexOffset &Other,179                               int64_t OtherBitSize, int64_t &BitOffset) const {180  int64_t Offset;181  if (!equalBaseIndex(Other, DAG, Offset))182    return false;183  if (Offset >= 0) {184    // Other is after *this:185    // [-------*this---------]186    //            [---Other--]187    // ==Offset==>188    BitOffset = 8 * Offset;189    return BitOffset + OtherBitSize <= BitSize;190  }191  // Other starts strictly before *this, it cannot be fully contained.192  //    [-------*this---------]193  // [--Other--]194  return false;195}196 197/// Parses tree in Ptr for base, index, offset addresses.198static BaseIndexOffset matchLSNode(const LSBaseSDNode *N,199                                   const SelectionDAG &DAG) {200  SDValue Ptr = N->getBasePtr();201 202  // (((B + I*M) + c)) + c ...203  SDValue Base = DAG.getTargetLoweringInfo().unwrapAddress(Ptr);204  SDValue Index = SDValue();205  int64_t Offset = 0;206  bool IsIndexSignExt = false;207 208  // pre-inc/pre-dec ops are components of EA.209  if (N->getAddressingMode() == ISD::PRE_INC) {210    if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))211      Offset += C->getSExtValue();212    else // If unknown, give up now.213      return BaseIndexOffset(SDValue(), SDValue(), 0, false);214  } else if (N->getAddressingMode() == ISD::PRE_DEC) {215    if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))216      Offset -= C->getSExtValue();217    else // If unknown, give up now.218      return BaseIndexOffset(SDValue(), SDValue(), 0, false);219  }220 221  // Consume constant adds & ors with appropriate masking.222  while (true) {223    switch (Base->getOpcode()) {224    case ISD::OR:225      // Only consider ORs which act as adds.226      if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1)))227        if (DAG.MaskedValueIsZero(Base->getOperand(0), C->getAPIntValue())) {228          Offset += C->getSExtValue();229          Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));230          continue;231        }232      break;233    case ISD::ADD:234    case ISD::PTRADD:235      if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {236        Offset += C->getSExtValue();237        Base = DAG.getTargetLoweringInfo().unwrapAddress(Base->getOperand(0));238        continue;239      }240      break;241    case ISD::LOAD:242    case ISD::STORE: {243      auto *LSBase = cast<LSBaseSDNode>(Base.getNode());244      unsigned int IndexResNo = (Base->getOpcode() == ISD::LOAD) ? 1 : 0;245      if (LSBase->isIndexed() && Base.getResNo() == IndexResNo)246        if (auto *C = dyn_cast<ConstantSDNode>(LSBase->getOffset())) {247          auto Off = C->getSExtValue();248          if (LSBase->getAddressingMode() == ISD::PRE_DEC ||249              LSBase->getAddressingMode() == ISD::POST_DEC)250            Offset -= Off;251          else252            Offset += Off;253          Base = DAG.getTargetLoweringInfo().unwrapAddress(LSBase->getBasePtr());254          continue;255        }256      break;257    }258    }259    // If we get here break out of the loop.260    break;261  }262 263  if (Base->isAnyAdd()) {264    // TODO: The following code appears to be needless as it just265    //       bails on some Ptrs early, reducing the cases where we266    //       find equivalence. We should be able to remove this.267    // Inside a loop the current BASE pointer is calculated using an ADD and a268    // MUL instruction. In this case Base is the actual BASE pointer.269    // (i64 add (i64 %array_ptr)270    //          (i64 mul (i64 %induction_var)271    //                   (i64 %element_size)))272    if (Base->getOperand(1)->getOpcode() == ISD::MUL)273      return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);274 275    // Look at Base + Index + Offset cases.276    Index = Base->getOperand(1);277    SDValue PotentialBase = Base->getOperand(0);278 279    // Skip signextends.280    if (Index->getOpcode() == ISD::SIGN_EXTEND) {281      Index = Index->getOperand(0);282      IsIndexSignExt = true;283    }284 285    // Check if Index Offset pattern286    if (!Index->isAnyAdd() || !isa<ConstantSDNode>(Index->getOperand(1)))287      return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);288 289    Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue();290    Index = Index->getOperand(0);291    if (Index->getOpcode() == ISD::SIGN_EXTEND) {292      Index = Index->getOperand(0);293      IsIndexSignExt = true;294    } else295      IsIndexSignExt = false;296    Base = PotentialBase;297  }298  return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt);299}300 301BaseIndexOffset BaseIndexOffset::match(const SDNode *N,302                                       const SelectionDAG &DAG) {303  if (const auto *LS0 = dyn_cast<LSBaseSDNode>(N))304    return matchLSNode(LS0, DAG);305  if (const auto *LN = dyn_cast<LifetimeSDNode>(N)) {306    return BaseIndexOffset(LN->getOperand(1), SDValue(), 0, false);307  }308  return BaseIndexOffset();309}310 311#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)312 313LLVM_DUMP_METHOD void BaseIndexOffset::dump() const {314  print(dbgs());315}316 317void BaseIndexOffset::print(raw_ostream& OS) const {318  OS << "BaseIndexOffset base=[";319  Base->print(OS);320  OS << "] index=[";321  if (Index)322    Index->print(OS);323  OS << "] offset=" << Offset;324}325 326#endif327