Commit 134a2c12 authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r322003:

------------------------------------------------------------------------
r322003 | niravd | 2018-01-08 08:21:35 -0800 (Mon, 08 Jan 2018) | 11 lines

[DAG] Teach BaseIndexOffset to correctly handle with indexed operations

BaseIndexOffset address analysis incorrectly ignores offsets folded
into indexed memory operations causing potential errors in alias
analysis of pre-indexed operations.

Reviewers: efriedma, RKSimon, hfinkel, jyknight

Subscribers: hiraditya, javed.absar, llvm-commits

Differential Revision: https://reviews.llvm.org/D41701
------------------------------------------------------------------------

llvm-svn: 322693
parent d68c17bc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ public:
                      int64_t &Off);

  /// Parses tree in Ptr for base, index, offset addresses.
  static BaseIndexOffset match(SDValue Ptr, const SelectionDAG &DAG);
  static BaseIndexOffset match(LSBaseSDNode *N, const SelectionDAG &DAG);
};

} // end namespace llvm
+47 −45
Original line number Diff line number Diff line
@@ -5225,7 +5225,7 @@ SDValue DAGCombiner::MatchLoadCombine(SDNode *N) {
      return SDValue();
    // Loads must share the same base address
    BaseIndexOffset Ptr = BaseIndexOffset::match(L->getBasePtr(), DAG);
    BaseIndexOffset Ptr = BaseIndexOffset::match(L, DAG);
    int64_t ByteOffsetFromBase = 0;
    if (!Base)
      Base = Ptr;
@@ -12944,7 +12944,7 @@ void DAGCombiner::getStoreMergeCandidates(
    StoreSDNode *St, SmallVectorImpl<MemOpLink> &StoreNodes) {
  // This holds the base pointer, index, and the offset in bytes from the base
  // pointer.
  BaseIndexOffset BasePtr = BaseIndexOffset::match(St->getBasePtr(), DAG);
  BaseIndexOffset BasePtr = BaseIndexOffset::match(St, DAG);
  EVT MemVT = St->getMemoryVT();
  SDValue Val = peekThroughBitcast(St->getValue());
@@ -12965,7 +12965,7 @@ void DAGCombiner::getStoreMergeCandidates(
  EVT LoadVT;
  if (IsLoadSrc) {
    auto *Ld = cast<LoadSDNode>(Val);
    LBasePtr = BaseIndexOffset::match(Ld->getBasePtr(), DAG);
    LBasePtr = BaseIndexOffset::match(Ld, DAG);
    LoadVT = Ld->getMemoryVT();
    // Load and store should be the same type.
    if (MemVT != LoadVT)
@@ -12984,7 +12984,7 @@ void DAGCombiner::getStoreMergeCandidates(
        return false;
      // The Load's Base Ptr must also match
      if (LoadSDNode *OtherLd = dyn_cast<LoadSDNode>(Val)) {
        auto LPtr = BaseIndexOffset::match(OtherLd->getBasePtr(), DAG);
        auto LPtr = BaseIndexOffset::match(OtherLd, DAG);
        if (LoadVT != OtherLd->getMemoryVT())
          return false;
        if (!(LBasePtr.equalBaseIndex(LPtr, DAG)))
@@ -13008,7 +13008,7 @@ void DAGCombiner::getStoreMergeCandidates(
          Val.getOpcode() != ISD::EXTRACT_SUBVECTOR)
        return false;
    }
    Ptr = BaseIndexOffset::match(Other->getBasePtr(), DAG);
    Ptr = BaseIndexOffset::match(Other, DAG);
    return (BasePtr.equalBaseIndex(Ptr, DAG, Offset));
  };
@@ -13381,7 +13381,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
      if (Ld->getMemoryVT() != MemVT)
        break;
      BaseIndexOffset LdPtr = BaseIndexOffset::match(Ld->getBasePtr(), DAG);
      BaseIndexOffset LdPtr = BaseIndexOffset::match(Ld, DAG);
      // If this is not the first ptr that we check.
      int64_t LdOffset = 0;
      if (LdBasePtr.getBase().getNode()) {
@@ -17448,9 +17448,10 @@ bool DAGCombiner::isAlias(LSBaseSDNode *Op0, LSBaseSDNode *Op1) const {
  unsigned NumBytes1 = Op1->getMemoryVT().getStoreSize();
  // Check for BaseIndexOffset matching.
  BaseIndexOffset BasePtr0 = BaseIndexOffset::match(Op0->getBasePtr(), DAG);
  BaseIndexOffset BasePtr1 = BaseIndexOffset::match(Op1->getBasePtr(), DAG);
  BaseIndexOffset BasePtr0 = BaseIndexOffset::match(Op0, DAG);
  BaseIndexOffset BasePtr1 = BaseIndexOffset::match(Op1, DAG);
  int64_t PtrDiff;
  if (BasePtr0.getBase().getNode() && BasePtr1.getBase().getNode()) {
    if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff))
      return !((NumBytes0 <= PtrDiff) || (PtrDiff + NumBytes1 <= 0));
@@ -17481,11 +17482,12 @@ bool DAGCombiner::isAlias(LSBaseSDNode *Op0, LSBaseSDNode *Op1) const {
         (IsGV0 != IsGV1) || (IsCV0 != IsCV1)) &&
        (IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1))
      return false;
  }
  // If we know required SrcValue1 and SrcValue2 have relatively large alignment
  // compared to the size and offset of the access, we may be able to prove they
  // do not alias. This check is conservative for now to catch cases created by
  // splitting vector types.
  // If we know required SrcValue1 and SrcValue2 have relatively large
  // alignment compared to the size and offset of the access, we may be able
  // to prove they do not alias. This check is conservative for now to catch
  // cases created by splitting vector types.
  int64_t SrcValOffset0 = Op0->getSrcValueOffset();
  int64_t SrcValOffset1 = Op1->getSrcValueOffset();
  unsigned OrigAlignment0 = Op0->getOriginalAlignment();
@@ -17495,8 +17497,8 @@ bool DAGCombiner::isAlias(LSBaseSDNode *Op0, LSBaseSDNode *Op1) const {
    int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0;
    int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1;
    // There is no overlap between these relatively aligned accesses of similar
    // size. Return no alias.
    // There is no overlap between these relatively aligned accesses of
    // similar size. Return no alias.
    if ((OffAlign0 + NumBytes0) <= OffAlign1 ||
        (OffAlign1 + NumBytes1) <= OffAlign0)
      return false;
@@ -17659,7 +17661,7 @@ bool DAGCombiner::findBetterNeighborChains(StoreSDNode *St) {
  // This holds the base pointer, index, and the offset in bytes from the base
  // pointer.
  BaseIndexOffset BasePtr = BaseIndexOffset::match(St->getBasePtr(), DAG);
  BaseIndexOffset BasePtr = BaseIndexOffset::match(St, DAG);
  // We must have a base and an offset.
  if (!BasePtr.getBase().getNode())
@@ -17685,7 +17687,7 @@ bool DAGCombiner::findBetterNeighborChains(StoreSDNode *St) {
      break;
    // Find the base pointer and offset for this memory node.
    BaseIndexOffset Ptr = BaseIndexOffset::match(Index->getBasePtr(), DAG);
    BaseIndexOffset Ptr = BaseIndexOffset::match(Index, DAG);
    // Check that the base pointer is the same as the original one.
    if (!BasePtr.equalBaseIndex(Ptr, DAG))
+2 −5
Original line number Diff line number Diff line
@@ -7947,11 +7947,8 @@ bool SelectionDAG::areNonVolatileConsecutiveLoads(LoadSDNode *LD,
  if (VT.getSizeInBits() / 8 != Bytes)
    return false;

  SDValue Loc = LD->getOperand(1);
  SDValue BaseLoc = Base->getOperand(1);

  auto BaseLocDecomp = BaseIndexOffset::match(BaseLoc, *this);
  auto LocDecomp = BaseIndexOffset::match(Loc, *this);
  auto BaseLocDecomp = BaseIndexOffset::match(Base, *this);
  auto LocDecomp = BaseIndexOffset::match(LD, *this);

  int64_t Offset = 0;
  if (BaseLocDecomp.equalBaseIndex(LocDecomp, *this, Offset))
+20 −1
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@ using namespace llvm;

bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other,
                                     const SelectionDAG &DAG, int64_t &Off) {
  // Conservatively fail if we a match failed..
  if (!Base.getNode() || !Other.Base.getNode())
    return false;
  // Initial Offset difference.
  Off = Other.Offset - Offset;

@@ -72,13 +75,29 @@ bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other,
}

/// Parses tree in Ptr for base, index, offset addresses.
BaseIndexOffset BaseIndexOffset::match(SDValue Ptr, const SelectionDAG &DAG) {
BaseIndexOffset BaseIndexOffset::match(LSBaseSDNode *N,
                                       const SelectionDAG &DAG) {
  SDValue Ptr = N->getBasePtr();

  // (((B + I*M) + c)) + c ...
  SDValue Base = DAG.getTargetLoweringInfo().unwrapAddress(Ptr);
  SDValue Index = SDValue();
  int64_t Offset = 0;
  bool IsIndexSignExt = false;

  // pre-inc/pre-dec ops are components of EA.
  if (N->getAddressingMode() == ISD::PRE_INC) {
    if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
      Offset += C->getSExtValue();
    else // If unknown, give up now.
      return BaseIndexOffset(SDValue(), SDValue(), 0, false);
  } else if (N->getAddressingMode() == ISD::PRE_DEC) {
    if (auto *C = dyn_cast<ConstantSDNode>(N->getOffset()))
      Offset -= C->getSExtValue();
    else // If unknown, give up now.
      return BaseIndexOffset(SDValue(), SDValue(), 0, false);
  }

  // Consume constant adds & ors with appropriate masking.
  while (Base->getOpcode() == ISD::ADD || Base->getOpcode() == ISD::OR) {
    if (auto *C = dyn_cast<ConstantSDNode>(Base->getOperand(1))) {