<div dir="ltr">Clearing DeadStores in runOnFunction() can stabilize the issue.<div><div><div><br></div><div>In FunctionPass, runOnFunction() may be called frequently in its life.</div></div></div><div>It'd be not a good idea to hold per-function states in a instance of FunctionPass.</div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Aug 19, 2015 at 1:19 PM NAKAMURA Takumi <<a href="mailto:geek4civic@gmail.com">geek4civic@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">FYI, it's not bootstrapping issue.<div>Iterative running (with just-built clang) may reproduce the issue. For me, clang/lib/Basic/Targets.cpp is often unstable.</div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Aug 19, 2015 at 12:26 PM KARTHIK VENKATESH BHAT <<a href="mailto:kv.bhat@samsung.com" target="_blank">kv.bhat@samsung.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Thanks Eric for explaining the 3 stage build process. I will try to figure out the reason for this.<br>
Thanks & Regards<br>
Karthik Bhat<br>
<br>
------- Original Message -------<br>
Sender : Eric Christopher<<a href="mailto:echristo@gmail.com" target="_blank">echristo@gmail.com</a>><br>
Date : Aug 19, 2015 11:16 (GMT+09:00)<br>
Title : Re: Re: [llvm] r245195 - Fix PR24469 resulting from r245025 and re-enable dead store elimination across basicblocks.<br>
<br>
OK, I've reverted this here:<br>
<br>
<br>
dzur:~/sources/llvm> git svn dcommit<br>
Committing to <a href="https://llvm.org/svn/llvm-project/llvm/trunk" rel="noreferrer" target="_blank">https://llvm.org/svn/llvm-project/llvm/trunk</a> ...<br>
D test/Transforms/DeadStoreElimination/cross_block_dse.ll<br>
D test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll<br>
M lib/Transforms/Scalar/DeadStoreElimination.cpp<br>
Committed r245402<br>
<br>
<br>
Thanks.<br>
<br>
<br>
-eric<br>
<br>
<br>
On Tue, Aug 18, 2015 at 2:17 PM Eric Christopher <<a href="mailto:echristo@gmail.com" target="_blank">echristo@gmail.com</a>> wrote:<br>
<br>
Hi Karthik,<br>
<br>
<br>
We're also seeing this as non-deterministic. The basic idea is that in a 3 stage build you build stage1 with your system compiler, then stage 2 is built with that and stage 3 with the output of stage 2. The stage 2 and stage 3 compilers then need to be bit for bit identical to show that there's no instability going on. Both the bot and we are seeing bootstrap failures after this revision - would you mind reverting shortly so we can figure out what's going on? I'll probably revert in an hour or so if you haven't.<br>
<br>
<br>
Thanks!<br>
<br>
<br>
-eric<br>
<br>
<br>
On Mon, Aug 17, 2015 at 4:02 AM KARTHIK VENKATESH BHAT via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br>
<br>
Hi Nakamura,<br>
Thanks for the link. I'm a bit new to this can you please let me know if my understanding of nondeterministic behavior is correct here.<br>
<br>
So build seems to be successful. The warning in stage1_build_clang seems to be from other files. So I assume we are talking about "compare_23" in the link?<br>
>From what I could understand we are building llvm with clang and comparing the .o files generated and checking if there is a difference with and without the current change list. Is my understanding correct?<br>
If that is true the current patch can remove few dead stores if any and create difference in .o files generated.<br>
<br>
Please if you could guide me if my understanding is correct I can investigate more to see if there is actually a problem.<br>
Thanks and Regards<br>
Karthik Bhat<br>
<br>
<br>
------- Original Message -------<br>
Sender : NAKAMURA Takumi<<a href="mailto:geek4civic@gmail.com" target="_blank">geek4civic@gmail.com</a>><br>
Date : Aug 17, 2015 18:53 (GMT+09:00)<br>
Title : Re: [llvm] r245195 - Fix PR24469 resulting from r245025 and re-enable dead store elimination across basicblocks.<br>
<br>
Seems it has nondeterministic behavior. See;<br>
<a href="http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2960" rel="noreferrer" target="_blank">http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2960</a><br>
<br>
2015-08-17 14:51 GMT+09:00 Karthik Bhat via llvm-commits<br>
:<br>
> Author: karthik<br>
> Date: Mon Aug 17 00:51:39 2015<br>
> New Revision: 245195<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=245195&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=245195&view=rev</a><br>
> Log:<br>
> Fix PR24469 resulting from r245025 and re-enable dead store elimination across basicblocks.<br>
> PR24469 resulted because DeleteDeadInstruction in handleNonLocalStoreDeletion was<br>
> deleting the next basic block iterator. Fixed the same by resetting the basic block iterator<br>
> post call to DeleteDeadInstruction.<br>
><br>
><br>
> Added:<br>
>     llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll<br>
>     llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll<br>
> Modified:<br>
>     llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=245195&r1=245194&r2=245195&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=245195&r1=245194&r2=245195&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Mon Aug 17 00:51:39 2015<br>
> @@ -16,13 +16,16 @@<br>
>  //===----------------------------------------------------------------------===//<br>
><br>
>  #include "llvm/Transforms/Scalar.h"<br>
> +#include "llvm/ADT/DenseSet.h"<br>
>  #include "llvm/ADT/STLExtras.h"<br>
>  #include "llvm/ADT/SetVector.h"<br>
>  #include "llvm/ADT/Statistic.h"<br>
>  #include "llvm/Analysis/AliasAnalysis.h"<br>
>  #include "llvm/Analysis/CaptureTracking.h"<br>
> +#include "llvm/Analysis/CFG.h"<br>
>  #include "llvm/Analysis/MemoryBuiltins.h"<br>
>  #include "llvm/Analysis/MemoryDependenceAnalysis.h"<br>
> +#include "llvm/Analysis/PostDominators.h"<br>
>  #include "llvm/Analysis/TargetLibraryInfo.h"<br>
>  #include "llvm/Analysis/ValueTracking.h"<br>
>  #include "llvm/IR/Constants.h"<br>
> @@ -42,6 +45,7 @@ using namespace llvm;<br>
><br>
>  STATISTIC(NumRedundantStores, "Number of redundant stores deleted");<br>
>  STATISTIC(NumFastStores, "Number of stores deleted");<br>
> +STATISTIC(NumCrossBlockStores, "Number of cross block stores deleted");<br>
>  STATISTIC(NumFastOther , "Number of other instrs removed");<br>
><br>
>  namespace {<br>
> @@ -49,12 +53,41 @@ namespace {<br>
>      AliasAnalysis *AA;<br>
>      MemoryDependenceAnalysis *MD;<br>
>      DominatorTree *DT;<br>
> +    PostDominatorTree *PDT;<br>
>      const TargetLibraryInfo *TLI;<br>
> -<br>
> +    SmallVector, 16> Candidates;<br>
> +    SetVector DeadStores;<br>
> +    SmallVector, 32><br>
> +        BackEdges;<br>
> +    DenseSet> BackEdgesMap;<br>
>      static char ID; // Pass identification, replacement for typeid<br>
> -    DSE() : FunctionPass(ID), AA(nullptr), MD(nullptr), DT(nullptr) {<br>
> +    DSE()<br>
> +        : FunctionPass(ID), AA(nullptr), MD(nullptr), DT(nullptr),<br>
> +          PDT(nullptr) {<br>
>        initializeDSEPass(*PassRegistry::getPassRegistry());<br>
>      }<br>
> +    // Return all stores in a given BasicBlock.<br>
> +    SmallVector getStores(BasicBlock *BB) {<br>
> +      SmallVector VecStores;<br>
> +      for (auto &BI : *BB) {<br>
> +        if (StoreInst *SI = dyn_cast(&BI))<br>
> +          VecStores.push_back(SI);<br>
> +      }<br>
> +      return VecStores;<br>
> +    }<br>
> +<br>
> +    // Get dfs in/out on the PDT and populate Candidates store list which<br>
> +    // is used to find potential dead stores for a given block<br>
> +    void populateCandidateStores(Function &F) {<br>
> +      for (auto &I : F) {<br>
> +        DomTreeNode *DTNode = PDT->getNode(&I);<br>
> +        if (!DTNode)<br>
> +          continue;<br>
> +        int DFSIn = DTNode->getDFSNumIn();<br>
> +        SmallVector VecStores = getStores(&I);<br>
> +        Candidates[DFSIn] = VecStores;<br>
> +      }<br>
> +    }<br>
><br>
>      bool runOnFunction(Function &F) override {<br>
>        if (skipOptnoneFunction(F))<br>
> @@ -64,7 +97,21 @@ namespace {<br>
>        MD = &getAnalysis();<br>
>        DT = &getAnalysis().getDomTree();<br>
>        TLI = &getAnalysis().getTLI();<br>
> -<br>
> +      PDT = &getAnalysis();<br>
> +      if (PDT->getRootNode()) {<br>
> +        int Count = PDT->getRootNode()->getDFSNumOut();<br>
> +        SmallVector VecStores;<br>
> +        Candidates.resize(Count + 1);<br>
> +        Candidates.assign(Count + 1, VecStores);<br>
> +<br>
> +        // If we have more than 1 block try to populate candidate store.<br>
> +        if (Count > 1) {<br>
> +          populateCandidateStores(F);<br>
> +          FindFunctionBackedges(F, BackEdges);<br>
> +          for (auto I : BackEdges)<br>
> +            BackEdgesMap.insert(I);<br>
> +        }<br>
> +      }<br>
>        bool Changed = false;<br>
>        for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)<br>
>          // Only check non-dead blocks.  Dead blocks may have strange pointer<br>
> @@ -83,16 +130,24 @@ namespace {<br>
>      void RemoveAccessedObjects(const MemoryLocation &LoadedLoc,<br>
>                                 SmallSetVector &DeadStackObjects,<br>
>                                 const DataLayout &DL);<br>
> -<br>
> +    void handleNonLocalStoreDeletion(StoreInst *SI, BasicBlock::iterator &BBI,<br>
> +                                     BasicBlock &CurBlock);<br>
> +    bool isSafeCandidateForDeletion(BasicBlock *SrcBlock, BasicBlock *SinkBlock,<br>
> +                                    StoreInst *SI);<br>
> +    void DeleteDeadInstruction(Instruction *I, MemoryDependenceAnalysis &MD,<br>
> +                               const TargetLibraryInfo &TLI,<br>
> +                               SmallSetVector *ValueSet = nullptr);<br>
>      void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
>        AU.setPreservesCFG();<br>
>        AU.addRequired();<br>
>        AU.addRequired();<br>
>        AU.addRequired();<br>
> +      AU.addRequired();<br>
>        AU.addRequired();<br>
>        AU.addPreserved();<br>
>        AU.addPreserved();<br>
>        AU.addPreserved();<br>
> +      AU.addPreserved();<br>
>      }<br>
>    };<br>
>  }<br>
> @@ -102,6 +157,7 @@ INITIALIZE_PASS_BEGIN(DSE, "dse", "Dead<br>
>  INITIALIZE_AG_DEPENDENCY(AliasAnalysis)<br>
>  INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)<br>
>  INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis)<br>
> +INITIALIZE_PASS_DEPENDENCY(PostDominatorTree)<br>
>  INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)<br>
>  INITIALIZE_PASS_END(DSE, "dse", "Dead Store Elimination", false, false)<br>
><br>
> @@ -111,50 +167,6 @@ FunctionPass *llvm::createDeadStoreElimi<br>
>  // Helper functions<br>
>  //===----------------------------------------------------------------------===//<br>
><br>
> -/// DeleteDeadInstruction - Delete this instruction.  Before we do, go through<br>
> -/// and zero out all the operands of this instruction.  If any of them become<br>
> -/// dead, delete them and the computation tree that feeds them.<br>
> -///<br>
> -/// If ValueSet is non-null, remove any deleted instructions from it as well.<br>
> -///<br>
> -static void DeleteDeadInstruction(Instruction *I,<br>
> -                               MemoryDependenceAnalysis &MD,<br>
> -                               const TargetLibraryInfo &TLI,<br>
> -                               SmallSetVector *ValueSet = nullptr) {<br>
> -  SmallVector NowDeadInsts;<br>
> -<br>
> -  NowDeadInsts.push_back(I);<br>
> -  --NumFastOther;<br>
> -<br>
> -  // Before we touch this instruction, remove it from memdep!<br>
> -  do {<br>
> -    Instruction *DeadInst = NowDeadInsts.pop_back_val();<br>
> -    ++NumFastOther;<br>
> -<br>
> -    // This instruction is dead, zap it, in stages.  Start by removing it from<br>
> -    // MemDep, which needs to know the operands and needs it to be in the<br>
> -    // function.<br>
> -    MD.removeInstruction(DeadInst);<br>
> -<br>
> -    for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) {<br>
> -      Value *Op = DeadInst->getOperand(op);<br>
> -      DeadInst->setOperand(op, nullptr);<br>
> -<br>
> -      // If this operand just became dead, add it to the NowDeadInsts list.<br>
> -      if (!Op->use_empty()) continue;<br>
> -<br>
> -      if (Instruction *OpI = dyn_cast(Op))<br>
> -        if (isInstructionTriviallyDead(OpI, &TLI))<br>
> -          NowDeadInsts.push_back(OpI);<br>
> -    }<br>
> -<br>
> -    DeadInst->eraseFromParent();<br>
> -<br>
> -    if (ValueSet) ValueSet->remove(DeadInst);<br>
> -  } while (!NowDeadInsts.empty());<br>
> -}<br>
> -<br>
> -<br>
>  /// hasMemoryWrite - Does this instruction write some memory?  This only returns<br>
>  /// true for things that we can analyze with other helpers below.<br>
>  static bool hasMemoryWrite(Instruction *I, const TargetLibraryInfo &TLI) {<br>
> @@ -527,10 +539,15 @@ bool DSE::runOnBasicBlock(BasicBlock &BB<br>
><br>
>      MemDepResult InstDep = MD->getDependency(Inst);<br>
><br>
> -    // Ignore any store where we can't find a local dependence.<br>
> -    // FIXME: cross-block DSE would be fun. :)<br>
> -    if (!InstDep.isDef() && !InstDep.isClobber())<br>
> +    if (!InstDep.isDef() && !InstDep.isClobber() && !InstDep.isNonLocal())<br>
>        continue;<br>
> +    if (InstDep.isNonLocal()) {<br>
> +      if (!PDT->getRootNode())<br>
> +        continue;<br>
> +      if (StoreInst *SI = dyn_cast(Inst))<br>
> +        handleNonLocalStoreDeletion(SI, BBI, BB);<br>
> +      continue;<br>
> +    }<br>
><br>
>      // Figure out what location is being stored to.<br>
>      MemoryLocation Loc = getLocForWrite(Inst, *AA);<br>
> @@ -704,6 +721,50 @@ static void FindUnconditionalPreds(Small<br>
>    }<br>
>  }<br>
><br>
> +/// DeleteDeadInstruction - Delete this instruction.  Before we do, go through<br>
> +/// and zero out all the operands of this instruction.  If any of them become<br>
> +/// dead, delete them and the computation tree that feeds them.<br>
> +/// If ValueSet is non-null, remove any deleted instructions from it as well.<br>
> +void DSE::DeleteDeadInstruction(Instruction *I, MemoryDependenceAnalysis &MD,<br>
> +                                const TargetLibraryInfo &TLI,<br>
> +                                SmallSetVector *ValueSet) {<br>
> +  SmallVector NowDeadInsts;<br>
> +<br>
> +  NowDeadInsts.push_back(I);<br>
> +  --NumFastOther;<br>
> +<br>
> +  // Before we touch this instruction, remove it from memdep!<br>
> +  do {<br>
> +    Instruction *DeadInst = NowDeadInsts.pop_back_val();<br>
> +    ++NumFastOther;<br>
> +    if (StoreInst *SI = dyn_cast(DeadInst))<br>
> +      DeadStores.insert(SI);<br>
> +<br>
> +    // This instruction is dead, zap it, in stages.  Start by removing it from<br>
> +    // MemDep, which needs to know the operands and needs it to be in the<br>
> +    // function.<br>
> +    MD.removeInstruction(DeadInst);<br>
> +<br>
> +    for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) {<br>
> +      Value *Op = DeadInst->getOperand(op);<br>
> +      DeadInst->setOperand(op, nullptr);<br>
> +<br>
> +      // If this operand just became dead, add it to the NowDeadInsts list.<br>
> +      if (!Op->use_empty())<br>
> +        continue;<br>
> +<br>
> +      if (Instruction *OpI = dyn_cast(Op))<br>
> +        if (isInstructionTriviallyDead(OpI, &TLI))<br>
> +          NowDeadInsts.push_back(OpI);<br>
> +    }<br>
> +<br>
> +    DeadInst->eraseFromParent();<br>
> +<br>
> +    if (ValueSet)<br>
> +      ValueSet->remove(DeadInst);<br>
> +  } while (!NowDeadInsts.empty());<br>
> +}<br>
> +<br>
>  /// HandleFree - Handle frees of entire structures whose dependency is a store<br>
>  /// to a field of that structure.<br>
>  bool DSE::HandleFree(CallInst *F) {<br>
> @@ -931,3 +992,122 @@ void DSE::RemoveAccessedObjects(const Me<br>
>      return !AA->isNoAlias(StackLoc, LoadedLoc);<br>
>    });<br>
>  }<br>
> +<br>
> +/// isSafeCandidateForDeletion- Check all paths from the SrcBlock till<br>
> +/// SinkBlock to see if Store 'SI' is safe to be remove.<br>
> +/// Returns true if the candidate store SI is safe to delete<br>
> +/// else returns false.<br>
> +bool DSE::isSafeCandidateForDeletion(BasicBlock *SrcBlock,<br>
> +                                     BasicBlock *SinkBlock, StoreInst *SI) {<br>
> +  SmallVector WorkList;<br>
> +  SmallPtrSet Visited;<br>
> +  BasicBlock::iterator BBI(SI);<br>
> +<br>
> +  // Check from the store till end of block and make sure we have no references<br>
> +  // to memory stored by this Store Instruction.<br>
> +  for (auto BI = ++BBI, BE = SrcBlock->end(); BI != BE; ++BI) {<br>
> +    Instruction *I = BI;<br>
> +    StoreInst *CSI = dyn_cast(I);<br>
> +    if (CSI) {<br>
> +      AliasResult R =<br>
> +          AA->alias(MemoryLocation::get(SI), MemoryLocation::get(CSI));<br>
> +      if (R == MustAlias)<br>
> +        return true;<br>
> +    } else {<br>
> +      ModRefInfo Res = AA->getModRefInfo(I, MemoryLocation::get(SI));<br>
> +      if (Res != MRI_NoModRef)<br>
> +        return false;<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // Add successors of the block to stack and start DFS.<br>
> +  for (succ_iterator I = succ_begin(SrcBlock), E = succ_end(SrcBlock); I != E;<br>
> +       ++I) {<br>
> +    if (!Visited.insert(*I).second)<br>
> +      continue;<br>
> +    // A path with backedge may not be safe. Conservatively mark<br>
> +    // this store unsafe.<br>
> +    if (BackEdgesMap.count(std::make_pair(SrcBlock, *I)))<br>
> +      return false;<br>
> +    WorkList.push_back(*I);<br>
> +  }<br>
> +<br>
> +  while (!WorkList.empty()) {<br>
> +    BasicBlock *B = WorkList.pop_back_val();<br>
> +    auto BI = B->begin();<br>
> +    auto BE = B->end();<br>
> +    for (; BI != BE; ++BI) {<br>
> +      Instruction *I = BI;<br>
> +      StoreInst *CSI = dyn_cast(I);<br>
> +      if (CSI) {<br>
> +        AliasResult R =<br>
> +            AA->alias(MemoryLocation::get(SI), MemoryLocation::get(CSI));<br>
> +        if (R == MustAlias)<br>
> +          break;<br>
> +      } else {<br>
> +        ModRefInfo Res = AA->getModRefInfo(I, MemoryLocation::get(SI));<br>
> +        if (Res != MRI_NoModRef)<br>
> +          return false;<br>
> +      }<br>
> +    }<br>
> +<br>
> +    // If we reached the sink node or we found a block which has a stores that<br>
> +    // overwrites the candidate block we need not look at their successors.<br>
> +    if (B == SinkBlock || BI != BE)<br>
> +      continue;<br>
> +<br>
> +    for (succ_iterator I = succ_begin(B), E = succ_end(B); I != E; ++I) {<br>
> +      if (!Visited.insert(*I).second)<br>
> +        continue;<br>
> +      // A path with backedge may not be safe.Conservatively mark<br>
> +      // this store unsafe.<br>
> +      if (BackEdgesMap.count(std::make_pair(B, *I)))<br>
> +        return false;<br>
> +      WorkList.push_back(*I);<br>
> +    }<br>
> +  }<br>
> +<br>
> +  return true;<br>
> +}<br>
> +<br>
> +/// handleNonLocalStoreDeletion - Handle non local dead store elimination.<br>
> +/// This works by finding candidate stores using PDT and then running DFS<br>
> +/// from candidate store block checking all paths to make sure the store is<br>
> +/// safe to delete.<br>
> +void DSE::handleNonLocalStoreDeletion(StoreInst *SI, BasicBlock::iterator &BBI,<br>
> +                                      BasicBlock &CurBlock) {<br>
> +  BasicBlock *BB = SI->getParent();<br>
> +  Value *Pointer = SI->getPointerOperand();<br>
> +  DomTreeNode *DTNode = PDT->getNode(BB);<br>
> +  if (!DTNode)<br>
> +    return;<br>
> +<br>
> +  int DFSNumIn = DTNode->getDFSNumIn();<br>
> +  int DFSNumOut = DTNode->getDFSNumOut();<br>
> +  for (int i = DFSNumIn + 1; i < DFSNumOut; ++i) {<br>
> +    for (auto &I : Candidates[i]) {<br>
> +      StoreInst *CandidateSI = I;<br>
> +      if (DeadStores.count(CandidateSI))<br>
> +        continue;<br>
> +      Value *MemPtr = CandidateSI->getPointerOperand();<br>
> +      if (!MemPtr)<br>
> +        continue;<br>
> +      if (Pointer->getType() != MemPtr->getType())<br>
> +        continue;<br>
> +      AliasResult R =<br>
> +          AA->alias(MemoryLocation::get(SI), MemoryLocation::get(CandidateSI));<br>
> +      if (R != MustAlias)<br>
> +        continue;<br>
> +      if (isSafeCandidateForDeletion(CandidateSI->getParent(), BB,<br>
> +                                     CandidateSI)) {<br>
> +        DeleteDeadInstruction(CandidateSI, *MD, *TLI);<br>
> +        ++NumCrossBlockStores;<br>
> +        // DeleteDeadInstruction can delete the current instruction in loop<br>
> +        // cases, reset BBI.<br>
> +        BBI = SI;<br>
> +        if (BBI != CurBlock.begin())<br>
> +          --BBI;<br>
> +      }<br>
> +    }<br>
> +  }<br>
> +}<br>
><br>
> Added: llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll?rev=245195&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll?rev=245195&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll (added)<br>
> +++ llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll Mon Aug 17 00:51:39 2015<br>
> @@ -0,0 +1,104 @@<br>
> +; RUN: opt < %s -basicaa -dse -S | FileCheck %s<br>
> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"<br>
> +<br>
> +@x = common global i32 0<br>
> +@y = common global i32 0<br>
> +@a = external global i32<br>
> +@b = external global i32<br>
> +<br>
> +define void @test_01(i32 %N) {<br>
> +  %1 = alloca i32<br>
> +  store i32 %N, i32* %1<br>
> +  store i32 10, i32* @x<br>
> +  %2 = load i32, i32* %1<br>
> +  %3 = icmp ne i32 %2, 0<br>
> +  br i1 %3, label %4, label %5<br>
> +<br>
> +; :4<br>
> +  store i32 5, i32* @x<br>
> +  br label %5<br>
> +<br>
> +; :5<br>
> +  store i32 15, i32* @x<br>
> +  ret void<br>
> +}<br>
> +; CHECK-LABEL: @test_01(<br>
> +; CHECK-NOT: store i32 10, i32* @x<br>
> +; CHECK-NOT: store i32 5, i32* @x<br>
> +; CHECK: store i32 15, i32* @x<br>
> +<br>
> +<br>
> +define void @test_02(i32 %N) {<br>
> +  %1 = alloca i32<br>
> +  store i32 %N, i32* %1<br>
> +  store i32 10, i32* @x<br>
> +  %2 = load i32, i32* %1<br>
> +  %3 = icmp ne i32 %2, 0<br>
> +  br i1 %3, label %4, label %5<br>
> +<br>
> +; :4<br>
> +  store i32 5, i32* @x<br>
> +  br label %7<br>
> +<br>
> +; :5<br>
> +  %6 = load i32, i32* @x<br>
> +  store i32 %6, i32* @y<br>
> +  br label %7<br>
> +<br>
> +; :7<br>
> +  store i32 15, i32* @x<br>
> +  ret void<br>
> +}<br>
> +; CHECK-LABEL: @test_02(<br>
> +; CHECK: store i32 10, i32* @x<br>
> +; CHECK-NOT: store i32 5, i32* @x<br>
> +; CHECK: store i32 %6, i32* @y<br>
> +<br>
> +<br>
> +define void @test_03(i32 %N) #0 {<br>
> +  %1 = alloca i32<br>
> +  store i32 %N, i32* %1<br>
> +  store i32 10, i32* @x<br>
> +  %2 = load i32, i32* %1<br>
> +  %3 = icmp ne i32 %2, 0<br>
> +  br i1 %3, label %4, label %6<br>
> +<br>
> +; :4                                       ; preds = %0<br>
> +  %5 = load i32, i32* @x<br>
> +  store i32 %5, i32* @y<br>
> +  br label %6<br>
> +<br>
> +; :6                                       ; preds = %4, %0<br>
> +  store i32 15, i32* @x<br>
> +  ret void<br>
> +}<br>
> +; CHECK-LABEL: @test_03(<br>
> +; CHECK: store i32 10, i32* @x<br>
> +; CHECK: store i32 %5, i32* @y<br>
> +; CHECK: store i32 15, i32* @x<br>
> +<br>
> +<br>
> +<br>
> +; Check we safely delete store i32 %g.02, i32* @b below.(PR24469)<br>
> +define void @test_04() {<br>
> +entry:<br>
> +  br i1 false, label %for.body, label %for.end.9<br>
> +<br>
> +for.cond.1.loopexit:                              ; preds = %for.body<br>
> +  store i32 0, i32* @b<br>
> +  %0 = load i32, i32* @a<br>
> +  br i1 false, label %for.body, label %for.end.9<br>
> +<br>
> +for.body:                                         ; preds = %for.cond.1.loopexit, %entry<br>
> +  %g.02 = phi i32 [ undef, %entry ], [ %0, %for.cond.1.loopexit ]<br>
> +  store i32 %g.02, i32* @b<br>
> +  br label %for.cond.1.loopexit<br>
> +<br>
> +for.end.9:                                        ; preds = %for.cond.1.loopexit, %entry<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @test_04(<br>
> +; CHECK-NOT: store i32 %g.02, i32* @b<br>
> +; CHECK-NOT: %g.02 = phi i32 [ undef, %entry ], [ %0, %for.cond.1.loopexit ]<br>
> +; CHECK-NOT: %0 = load i32, i32* @a<br>
><br>
> Added: llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll?rev=245195&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll?rev=245195&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll (added)<br>
> +++ llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll Mon Aug 17 00:51:39 2015<br>
> @@ -0,0 +1,104 @@<br>
> +; RUN: opt < %s -basicaa -dse -S | FileCheck %s<br>
> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"<br>
> +<br>
> +@A = common global [100 x i32] zeroinitializer, align 16<br>
> +@x = common global i32 0<br>
> +<br>
> +; Negative Test case-<br>
> +;void foo(int N) {<br>
> +;  A[0] = N;<br>
> +;  for(int i=0;i> +;    A[i]+=i;<br>
> +;  A[0] = 10;<br>
> +;}<br>
> +;; Stores should not be optimized away.<br>
> +<br>
> +define void @test_01(i32 %N) #0 {<br>
> +  %1 = alloca i32<br>
> +  %i = alloca i32<br>
> +  store i32 %N, i32* %1<br>
> +  %2 = load i32, i32* %1<br>
> +  store i32 %2, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)<br>
> +  store i32 0, i32* %i<br>
> +  br label %3<br>
> +<br>
> +; :3                                       ; preds = %14, %0<br>
> +  %4 = load i32, i32* %i<br>
> +  %5 = load i32, i32* %1<br>
> +  %6 = icmp slt i32 %4, %5<br>
> +  br i1 %6, label %7, label %17<br>
> +<br>
> +; :7                                       ; preds = %3<br>
> +  %8 = load i32, i32* %i<br>
> +  %9 = load i32, i32* %i<br>
> +  %10 = sext i32 %9 to i64<br>
> +  %11 = getelementptr inbounds [100 x i32], [100 x i32]* @A, i32 0, i64 %10<br>
> +  %12 = load i32, i32* %11<br>
> +  %13 = add nsw i32 %12, %8<br>
> +  store i32 %13, i32* %11<br>
> +  br label %14<br>
> +<br>
> +; :14                                      ; preds = %7<br>
> +  %15 = load i32, i32* %i<br>
> +  %16 = add nsw i32 %15, 1<br>
> +  store i32 %16, i32* %i<br>
> +  br label %3<br>
> +<br>
> +; :17                                      ; preds = %3<br>
> +  store i32 10, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)<br>
> +  ret void<br>
> +}<br>
> +; CHECK-LABEL: @test_01(<br>
> +; CHECK: store i32 %2, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)<br>
> +; CHECK: store i32 %13, i32* %11<br>
> +; CHECK: store i32 10, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)<br>
> +<br>
> +<br>
> +; Postive Test case-<br>
> +;void foo(int N) {<br>
> +;  A[0] = N;<br>
> +;  for(int i=0;i> +;    A[i]=i;<br>
> +;  A[0] = 10;<br>
> +;}<br>
> +;; Stores should not be optimized away.<br>
> +define void @test_02(i32 %N) #0 {<br>
> +  %1 = alloca i32<br>
> +  %i = alloca i32<br>
> +  store i32 %N, i32* %1<br>
> +  %2 = load i32, i32* %1<br>
> +  store i32 %2, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)<br>
> +  store i32 0, i32* %i<br>
> +  br label %3<br>
> +<br>
> +; :3                                       ; preds = %12, %0<br>
> +  %4 = load i32, i32* %i<br>
> +  %5 = load i32, i32* %1<br>
> +  %6 = icmp slt i32 %4, %5<br>
> +  br i1 %6, label %7, label %15<br>
> +<br>
> +; :7                                       ; preds = %3<br>
> +  %8 = load i32, i32* %i<br>
> +  %9 = load i32, i32* %i<br>
> +  %10 = sext i32 %9 to i64<br>
> +  %11 = getelementptr inbounds [100 x i32], [100 x i32]* @A, i32 0, i64 %10<br>
> +  store i32 %8, i32* %11<br>
> +  br label %12<br>
> +<br>
> +; :12                                      ; preds = %7<br>
> +  %13 = load i32, i32* %i<br>
> +  %14 = add nsw i32 %13, 1<br>
> +  store i32 %14, i32* %i<br>
> +  br label %3<br>
> +<br>
> +; :15                                      ; preds = %3<br>
> +  store i32 10, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @test_02(<br>
> +; CHECK-NOT: store i32 %2, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)<br>
> +; CHECK: store i32 %7, i32* %10<br>
> +; CHECK: store i32 10, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)<br>
> +<br>
> +<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a></blockquote></div></blockquote></div>