diff options
author | Clement Courbet <courbet@google.com> | 2019-03-13 13:56:23 +0000 |
---|---|---|
committer | Clement Courbet <courbet@google.com> | 2019-03-13 13:56:23 +0000 |
commit | 3bb5d0bb9b312f4460ad9741bea434527fe63b87 (patch) | |
tree | 7f83afa96dea695aa812143313da94685f175b4a /llvm/lib/CodeGen | |
parent | d703305e404d3bb7f506e6f8ab0772d415263c48 (diff) | |
download | bcm5719-llvm-3bb5d0bb9b312f4460ad9741bea434527fe63b87.tar.gz bcm5719-llvm-3bb5d0bb9b312f4460ad9741bea434527fe63b87.zip |
Re-land r354244 "[DAGCombiner] Eliminate dead stores to stack."
Always check candidates for hasOtherUses(), not only stores.
llvm-svn: 356050
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index fc1c97b8e9a..9ff62ad7fec 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<LifetimeSDNode>(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<SDValue, 8> 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<LifetimeSDNode>(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<StoreSDNode>(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<LoadSDNode>(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<LifetimeSDNode>(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); |