From: Clement Courbet Date: Wed, 13 Mar 2019 13:56:23 +0000 (+0000) Subject: Re-land r354244 "[DAGCombiner] Eliminate dead stores to stack." X-Git-Tag: llvmorg-10-init~10083 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3bb5d0bb9b312f4460ad9741bea434527fe63b87;p=platform%2Fupstream%2Fllvm.git Re-land r354244 "[DAGCombiner] Eliminate dead stores to stack." Always check candidates for hasOtherUses(), not only stores. llvm-svn: 356050 --- diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index fc1c97b..9ff62ad 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -384,6 +384,7 @@ namespace { SDValue replaceStoreOfFPConstant(StoreSDNode *ST); SDValue visitSTORE(SDNode *N); + SDValue visitLIFETIME_END(SDNode *N); SDValue visitINSERT_VECTOR_ELT(SDNode *N); SDValue visitEXTRACT_VECTOR_ELT(SDNode *N); SDValue visitBUILD_VECTOR(SDNode *N); @@ -1591,6 +1592,7 @@ SDValue DAGCombiner::visit(SDNode *N) { case ISD::MLOAD: return visitMLOAD(N); case ISD::MSCATTER: return visitMSCATTER(N); case ISD::MSTORE: return visitMSTORE(N); + case ISD::LIFETIME_END: return visitLIFETIME_END(N); case ISD::FP_TO_FP16: return visitFP_TO_FP16(N); case ISD::FP16_TO_FP: return visitFP16_TO_FP(N); case ISD::VECREDUCE_FADD: @@ -15561,6 +15563,66 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return ReduceLoadOpStoreWidth(N); } +SDValue DAGCombiner::visitLIFETIME_END(SDNode *N) { + const auto *LifetimeEnd = cast(N); + if (!LifetimeEnd->hasOffset()) + return SDValue(); + + const BaseIndexOffset LifetimeEndBase(N->getOperand(1), SDValue(), + LifetimeEnd->getOffset(), false); + + // We walk up the chains to find stores. + SmallVector Chains = {N->getOperand(0)}; + while (!Chains.empty()) { + SDValue Chain = Chains.back(); + Chains.pop_back(); + if (!Chain.hasOneUse()) + continue; + switch (Chain.getOpcode()) { + case ISD::TokenFactor: + for (unsigned Nops = Chain.getNumOperands(); Nops;) + Chains.push_back(Chain.getOperand(--Nops)); + break; + case ISD::LIFETIME_START: + case ISD::LIFETIME_END: { + // We can forward past any lifetime start/end that can be proven not to + // alias the node. + const auto *Lifetime = cast(Chain); + if (!Lifetime->hasOffset()) + break; // Be conservative if we don't know the extents of the object. + + const BaseIndexOffset LifetimeBase(Lifetime->getOperand(1), SDValue(), + Lifetime->getOffset(), false); + bool IsAlias; + if (BaseIndexOffset::computeAliasing(LifetimeEndBase, + LifetimeEnd->getSize(), LifetimeBase, + Lifetime->getSize(), DAG, IsAlias) && + !IsAlias) { + Chains.push_back(Chain.getOperand(0)); + } + break; + } + case ISD::STORE: { + StoreSDNode *ST = dyn_cast(Chain); + if (ST->isVolatile() || ST->isIndexed()) + continue; + const BaseIndexOffset StoreBase = BaseIndexOffset::match(ST, DAG); + // If we store purely within object bounds just before its lifetime ends, + // we can remove the store. + if (LifetimeEndBase.contains(DAG, LifetimeEnd->getSize() * 8, StoreBase, + ST->getMemoryVT().getStoreSizeInBits())) { + LLVM_DEBUG(dbgs() << "\nRemoving store:"; StoreBase.dump(); + dbgs() << "\nwithin LIFETIME_END of : "; + LifetimeEndBase.dump(); dbgs() << "\n"); + CombineTo(ST, ST->getChain()); + return SDValue(N, 0); + } + } + } + } + return SDValue(); +} + /// For the instruction sequence of store below, F and I values /// are bundled together as an i64 value before being stored into memory. /// Sometimes it is more efficent to generate separate stores for F and I, @@ -19394,6 +19456,8 @@ void DAGCombiner::GatherAllAliases(LSBaseSDNode *N, SDValue OriginalChain, // Get alias information for node. bool IsLoad = isa(N) && !N->isVolatile(); + const BaseIndexOffset LSBasePtr = BaseIndexOffset::match(N, DAG); + const unsigned LSNumBytes = N->getMemoryVT().getStoreSize(); // Starting off. Chains.push_back(OriginalChain); @@ -19464,6 +19528,31 @@ void DAGCombiner::GatherAllAliases(LSBaseSDNode *N, SDValue OriginalChain, ++Depth; break; + case ISD::LIFETIME_START: + case ISD::LIFETIME_END: { + // We can forward past any lifetime start/end that can be proven not to + // alias the memory access. + const auto *Lifetime = cast(Chain); + if (!Lifetime->hasOffset()) { + Aliases.push_back(Chain); + break; // Be conservative if we don't know the extents of the object. + } + + const BaseIndexOffset LifetimePtr(Lifetime->getOperand(1), SDValue(), + Lifetime->getOffset(), false); + bool IsAlias; + if (BaseIndexOffset::computeAliasing(LifetimePtr, Lifetime->getSize(), + LSBasePtr, LSNumBytes, DAG, + IsAlias) && + !IsAlias) { + Chains.push_back(Chain.getOperand(0)); + ++Depth; + } else { + Aliases.push_back(Chain); + } + break; + } + default: // For all other instructions we will just have to take what we can get. Aliases.push_back(Chain); diff --git a/llvm/test/CodeGen/X86/swap.ll b/llvm/test/CodeGen/X86/swap.ll index e74ed24..32599b6 100644 --- a/llvm/test/CodeGen/X86/swap.ll +++ b/llvm/test/CodeGen/X86/swap.ll @@ -22,7 +22,6 @@ define dso_local void @_Z4SwapP1SS0_(%struct.S* nocapture %a, %struct.S* nocaptu ; AA-LABEL: _Z4SwapP1SS0_: ; AA: # %bb.0: # %entry ; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: vmovups (%rsi), %xmm1 ; AA-NEXT: vmovups %xmm1, (%rdi) ; AA-NEXT: vmovups %xmm0, (%rsi) @@ -43,18 +42,10 @@ entry: define dso_local void @onealloc_noreadback(i8* nocapture %a, i8* nocapture %b) local_unnamed_addr { ; NOAA-LABEL: onealloc_noreadback: ; NOAA: # %bb.0: # %entry -; NOAA-NEXT: vmovups (%rdi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; NOAA-NEXT: vmovups (%rsi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; NOAA-NEXT: retq ; ; AA-LABEL: onealloc_noreadback: ; AA: # %bb.0: # %entry -; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovups (%rsi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: retq entry: %alloc = alloca [16 x i8], i8 2, align 1 @@ -73,18 +64,10 @@ entry: define dso_local void @twoallocs_trivial(i8* nocapture %a, i8* nocapture %b) local_unnamed_addr { ; NOAA-LABEL: twoallocs_trivial: ; NOAA: # %bb.0: # %entry -; NOAA-NEXT: vmovups (%rdi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; NOAA-NEXT: vmovups (%rsi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; NOAA-NEXT: retq ; ; AA-LABEL: twoallocs_trivial: ; AA: # %bb.0: # %entry -; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovups (%rsi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: retq entry: %alloc1 = alloca [16 x i8], align 1 @@ -105,7 +88,6 @@ define dso_local void @twoallocs(i8* nocapture %a, i8* nocapture %b) local_unnam ; NOAA: # %bb.0: # %entry ; NOAA-NEXT: vmovups (%rdi), %xmm0 ; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; NOAA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; NOAA-NEXT: vmovups %xmm0, (%rsi) ; NOAA-NEXT: retq ; @@ -113,7 +95,6 @@ define dso_local void @twoallocs(i8* nocapture %a, i8* nocapture %b) local_unnam ; AA: # %bb.0: # %entry ; AA-NEXT: vmovups (%rdi), %xmm0 ; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; AA-NEXT: vmovups %xmm0, (%rsi) ; AA-NEXT: retq entry: @@ -148,7 +129,6 @@ define dso_local void @onealloc_readback_1(i8* nocapture %a, i8* nocapture %b) l ; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: vmovups (%rsi), %xmm0 ; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; AA-NEXT: vmovups %xmm0, (%rdi) ; AA-NEXT: retq entry: @@ -182,7 +162,6 @@ define dso_local void @onealloc_readback_2(i8* nocapture %a, i8* nocapture %b) l ; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: vmovups (%rsi), %xmm0 ; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; AA-NEXT: vmovups %xmm0, (%rdi) ; AA-NEXT: retq entry: diff --git a/llvm/test/DebugInfo/COFF/lexicalblock.ll b/llvm/test/DebugInfo/COFF/lexicalblock.ll index 39fcd99..970aae2 100644 --- a/llvm/test/DebugInfo/COFF/lexicalblock.ll +++ b/llvm/test/DebugInfo/COFF/lexicalblock.ll @@ -70,9 +70,6 @@ ; CHECK: Kind: S_BLOCK32 {{.*}} ; CHECK: BlockName: ; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localC -; CHECK: } ; CHECK: ScopeEndSym { ; CHECK: Kind: S_END {{.*}} ; CHECK: } @@ -80,9 +77,6 @@ ; CHECK: Kind: S_BLOCK32 {{.*}} ; CHECK: BlockName: ; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localD -; CHECK: } ; CHECK: ScopeEndSym { ; CHECK: Kind: S_END {{.*}} ; CHECK: } @@ -90,38 +84,12 @@ ; CHECK: Kind: S_BLOCK32 {{.*}} ; CHECK: BlockName: ; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localE -; CHECK: } -; CHECK: ScopeEndSym { -; CHECK: } -; CHECK: BlockSym { -; CHECK: Kind: S_BLOCK32 {{.*}} -; CHECK: BlockName: -; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localF -; CHECK: } -; CHECK: BlockSym { -; CHECK: Kind: S_BLOCK32 {{.*}} -; CHECK: BlockName: -; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localG -; CHECK: } ; CHECK: ScopeEndSym { -; CHECK: Kind: S_END {{.*}} -; CHECK: } -; CHECK: ScopeEndSym { -; CHECK: Kind: S_END {{.*}} ; CHECK: } ; CHECK: BlockSym { ; CHECK: Kind: S_BLOCK32 {{.*}} ; CHECK: BlockName: ; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localH -; CHECK: } ; CHECK: ScopeEndSym { ; CHECK: Kind: S_END {{.*}} ; CHECK: }