From: Clement Courbet Date: Wed, 20 Feb 2019 15:45:58 +0000 (+0000) Subject: Re-land the refactoring part of r354244 "[DAGCombiner] Eliminate dead stores to stack." X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1da2d4699dd5d780be323d5959e0ad94a21e5ee8;p=llvm Re-land the refactoring part of r354244 "[DAGCombiner] Eliminate dead stores to stack." This is an NFC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354476 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h b/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h index f168b846fda..4173cbe635b 100644 --- a/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h +++ b/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h @@ -48,14 +48,30 @@ public: SDValue getIndex() { return Index; } SDValue getIndex() const { return Index; } + // Returns true if `Other` and `*this` are both some offset from the same base + // pointer. In that case, `Off` is set to the offset between `*this` and + // `Other` (negative if `Other` is before `*this`). + bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, + int64_t &Off) const; + bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG) const { int64_t Off; return equalBaseIndex(Other, DAG, Off); } - bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, - int64_t &Off) const; + // Returns true if `Other` (with size `OtherSize`) can be proven to be fully + // contained in `*this` (with size `Size`). + bool contains(int64_t Size, const BaseIndexOffset &Other, int64_t OtherSize, + const SelectionDAG &DAG) const; + + // Returns true `BasePtr0` and `BasePtr1` can be proven to alias/not alias, in + // which case `IsAlias` is set to true/false. + static bool computeAliasing(const BaseIndexOffset &BasePtr0, + const int64_t NumBytes0, + const BaseIndexOffset &BasePtr1, + const int64_t NumBytes1, const SelectionDAG &DAG, + bool &IsAlias); /// Parses tree in Ptr for base, index, offset addresses. static BaseIndexOffset match(const LSBaseSDNode *N, const SelectionDAG &DAG); diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index c2404f963ce..993ab4ae551 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -19235,41 +19235,11 @@ bool DAGCombiner::isAlias(LSBaseSDNode *Op0, LSBaseSDNode *Op1) const { unsigned NumBytes1 = Op1->getMemoryVT().getStoreSize(); // Check for BaseIndexOffset matching. - 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)); - - // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be - // able to calculate their relative offset if at least one arises - // from an alloca. However, these allocas cannot overlap and we - // can infer there is no alias. - if (auto *A = dyn_cast(BasePtr0.getBase())) - if (auto *B = dyn_cast(BasePtr1.getBase())) { - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - // If the base are the same frame index but the we couldn't find a - // constant offset, (indices are different) be conservative. - if (A != B && (!MFI.isFixedObjectIndex(A->getIndex()) || - !MFI.isFixedObjectIndex(B->getIndex()))) - return false; - } - - bool IsFI0 = isa(BasePtr0.getBase()); - bool IsFI1 = isa(BasePtr1.getBase()); - bool IsGV0 = isa(BasePtr0.getBase()); - bool IsGV1 = isa(BasePtr1.getBase()); - bool IsCV0 = isa(BasePtr0.getBase()); - bool IsCV1 = isa(BasePtr1.getBase()); - - // If of mismatched base types or checkable indices we can check - // they do not alias. - if ((BasePtr0.getIndex() == BasePtr1.getIndex() || (IsFI0 != IsFI1) || - (IsGV0 != IsGV1) || (IsCV0 != IsCV1)) && - (IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) - return false; - } + bool IsAlias; + if (BaseIndexOffset::computeAliasing( + BaseIndexOffset::match(Op0, DAG), NumBytes0, + BaseIndexOffset::match(Op1, DAG), NumBytes1, DAG, IsAlias)) + return IsAlias; // If we know required SrcValue1 and SrcValue2 have relatively large // alignment compared to the size and offset of the access, we may be able diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp index 5666c1293e9..c21ecfca13a 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp @@ -79,6 +79,81 @@ bool BaseIndexOffset::equalBaseIndex(const BaseIndexOffset &Other, return false; } +bool BaseIndexOffset::computeAliasing(const BaseIndexOffset &BasePtr0, + const int64_t NumBytes0, + const BaseIndexOffset &BasePtr1, + const int64_t NumBytes1, + const SelectionDAG &DAG, bool &IsAlias) { + if (!(BasePtr0.getBase().getNode() && BasePtr1.getBase().getNode())) + return false; + int64_t PtrDiff; + if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) { + // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the + // following situations arise: + IsAlias = !( + // [----BasePtr0----] + // [---BasePtr1--] + // ========PtrDiff========> + (NumBytes0 <= PtrDiff) || + // [----BasePtr0----] + // [---BasePtr1--] + // =====(-PtrDiff)====> + (PtrDiff + NumBytes1 <= 0)); // i.e. NumBytes1 < -PtrDiff. + return true; + } + // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be + // able to calculate their relative offset if at least one arises + // from an alloca. However, these allocas cannot overlap and we + // can infer there is no alias. + if (auto *A = dyn_cast(BasePtr0.getBase())) + if (auto *B = dyn_cast(BasePtr1.getBase())) { + MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); + // If the base are the same frame index but the we couldn't find a + // constant offset, (indices are different) be conservative. + if (A != B && (!MFI.isFixedObjectIndex(A->getIndex()) || + !MFI.isFixedObjectIndex(B->getIndex()))) { + IsAlias = false; + return true; + } + } + + bool IsFI0 = isa(BasePtr0.getBase()); + bool IsFI1 = isa(BasePtr1.getBase()); + bool IsGV0 = isa(BasePtr0.getBase()); + bool IsGV1 = isa(BasePtr1.getBase()); + bool IsCV0 = isa(BasePtr0.getBase()); + bool IsCV1 = isa(BasePtr1.getBase()); + + // If of mismatched base types or checkable indices we can check + // they do not alias. + if ((BasePtr0.getIndex() == BasePtr1.getIndex() || (IsFI0 != IsFI1) || + (IsGV0 != IsGV1) || (IsCV0 != IsCV1)) && + (IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) { + IsAlias = false; + return true; + } + return false; // Cannot determine whether the pointers alias. +} + +bool BaseIndexOffset::contains(int64_t Size, const BaseIndexOffset &Other, + int64_t OtherSize, + const SelectionDAG &DAG) const { + int64_t Offset; + if (!equalBaseIndex(Other, DAG, Offset)) + return false; + if (Offset >= 0) { + // Other is after *this: + // [-------*this---------] + // [---Other--] + // ==Offset==> + return Offset + OtherSize <= Size; + } + // Other starts strictly before *this, it cannot be fully contained. + // [-------*this---------] + // [--Other--] + return false; +} + /// Parses tree in Ptr for base, index, offset addresses. BaseIndexOffset BaseIndexOffset::match(const LSBaseSDNode *N, const SelectionDAG &DAG) {