[llvm] r245195 - Fix PR24469 resulting from r245025 and re-enable dead store elimination across basicblocks.

NAKAMURA Takumi via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 17 02:53:29 PDT 2015


Seems it has nondeterministic behavior. See;
http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2960

2015-08-17 14:51 GMT+09:00 Karthik Bhat via llvm-commits
<llvm-commits at lists.llvm.org>:
> Author: karthik
> Date: Mon Aug 17 00:51:39 2015
> New Revision: 245195
>
> URL: http://llvm.org/viewvc/llvm-project?rev=245195&view=rev
> Log:
> Fix PR24469 resulting from r245025 and re-enable dead store elimination across basicblocks.
> PR24469 resulted because DeleteDeadInstruction in handleNonLocalStoreDeletion was
> deleting the next basic block iterator. Fixed the same by resetting the basic block iterator
> post call to DeleteDeadInstruction.
>
>
> Added:
>     llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll
>     llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll
> Modified:
>     llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
>
> Modified: llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=245195&r1=245194&r2=245195&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Mon Aug 17 00:51:39 2015
> @@ -16,13 +16,16 @@
>  //===----------------------------------------------------------------------===//
>
>  #include "llvm/Transforms/Scalar.h"
> +#include "llvm/ADT/DenseSet.h"
>  #include "llvm/ADT/STLExtras.h"
>  #include "llvm/ADT/SetVector.h"
>  #include "llvm/ADT/Statistic.h"
>  #include "llvm/Analysis/AliasAnalysis.h"
>  #include "llvm/Analysis/CaptureTracking.h"
> +#include "llvm/Analysis/CFG.h"
>  #include "llvm/Analysis/MemoryBuiltins.h"
>  #include "llvm/Analysis/MemoryDependenceAnalysis.h"
> +#include "llvm/Analysis/PostDominators.h"
>  #include "llvm/Analysis/TargetLibraryInfo.h"
>  #include "llvm/Analysis/ValueTracking.h"
>  #include "llvm/IR/Constants.h"
> @@ -42,6 +45,7 @@ using namespace llvm;
>
>  STATISTIC(NumRedundantStores, "Number of redundant stores deleted");
>  STATISTIC(NumFastStores, "Number of stores deleted");
> +STATISTIC(NumCrossBlockStores, "Number of cross block stores deleted");
>  STATISTIC(NumFastOther , "Number of other instrs removed");
>
>  namespace {
> @@ -49,12 +53,41 @@ namespace {
>      AliasAnalysis *AA;
>      MemoryDependenceAnalysis *MD;
>      DominatorTree *DT;
> +    PostDominatorTree *PDT;
>      const TargetLibraryInfo *TLI;
> -
> +    SmallVector<SmallVector<StoreInst *, 8>, 16> Candidates;
> +    SetVector<StoreInst *> DeadStores;
> +    SmallVector<std::pair<const BasicBlock *, const BasicBlock *>, 32>
> +        BackEdges;
> +    DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> BackEdgesMap;
>      static char ID; // Pass identification, replacement for typeid
> -    DSE() : FunctionPass(ID), AA(nullptr), MD(nullptr), DT(nullptr) {
> +    DSE()
> +        : FunctionPass(ID), AA(nullptr), MD(nullptr), DT(nullptr),
> +          PDT(nullptr) {
>        initializeDSEPass(*PassRegistry::getPassRegistry());
>      }
> +    // Return all stores in a given BasicBlock.
> +    SmallVector<StoreInst *, 8> getStores(BasicBlock *BB) {
> +      SmallVector<StoreInst *, 8> VecStores;
> +      for (auto &BI : *BB) {
> +        if (StoreInst *SI = dyn_cast<StoreInst>(&BI))
> +          VecStores.push_back(SI);
> +      }
> +      return VecStores;
> +    }
> +
> +    // Get dfs in/out on the PDT and populate Candidates store list which
> +    // is used to find potential dead stores for a given block
> +    void populateCandidateStores(Function &F) {
> +      for (auto &I : F) {
> +        DomTreeNode *DTNode = PDT->getNode(&I);
> +        if (!DTNode)
> +          continue;
> +        int DFSIn = DTNode->getDFSNumIn();
> +        SmallVector<StoreInst *, 8> VecStores = getStores(&I);
> +        Candidates[DFSIn] = VecStores;
> +      }
> +    }
>
>      bool runOnFunction(Function &F) override {
>        if (skipOptnoneFunction(F))
> @@ -64,7 +97,21 @@ namespace {
>        MD = &getAnalysis<MemoryDependenceAnalysis>();
>        DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
>        TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
> -
> +      PDT = &getAnalysis<PostDominatorTree>();
> +      if (PDT->getRootNode()) {
> +        int Count = PDT->getRootNode()->getDFSNumOut();
> +        SmallVector<StoreInst *, 8> VecStores;
> +        Candidates.resize(Count + 1);
> +        Candidates.assign(Count + 1, VecStores);
> +
> +        // If we have more than 1 block try to populate candidate store.
> +        if (Count > 1) {
> +          populateCandidateStores(F);
> +          FindFunctionBackedges(F, BackEdges);
> +          for (auto I : BackEdges)
> +            BackEdgesMap.insert(I);
> +        }
> +      }
>        bool Changed = false;
>        for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
>          // Only check non-dead blocks.  Dead blocks may have strange pointer
> @@ -83,16 +130,24 @@ namespace {
>      void RemoveAccessedObjects(const MemoryLocation &LoadedLoc,
>                                 SmallSetVector<Value *, 16> &DeadStackObjects,
>                                 const DataLayout &DL);
> -
> +    void handleNonLocalStoreDeletion(StoreInst *SI, BasicBlock::iterator &BBI,
> +                                     BasicBlock &CurBlock);
> +    bool isSafeCandidateForDeletion(BasicBlock *SrcBlock, BasicBlock *SinkBlock,
> +                                    StoreInst *SI);
> +    void DeleteDeadInstruction(Instruction *I, MemoryDependenceAnalysis &MD,
> +                               const TargetLibraryInfo &TLI,
> +                               SmallSetVector<Value *, 16> *ValueSet = nullptr);
>      void getAnalysisUsage(AnalysisUsage &AU) const override {
>        AU.setPreservesCFG();
>        AU.addRequired<DominatorTreeWrapperPass>();
>        AU.addRequired<AliasAnalysis>();
>        AU.addRequired<MemoryDependenceAnalysis>();
> +      AU.addRequired<PostDominatorTree>();
>        AU.addRequired<TargetLibraryInfoWrapperPass>();
>        AU.addPreserved<AliasAnalysis>();
>        AU.addPreserved<DominatorTreeWrapperPass>();
>        AU.addPreserved<MemoryDependenceAnalysis>();
> +      AU.addPreserved<PostDominatorTree>();
>      }
>    };
>  }
> @@ -102,6 +157,7 @@ INITIALIZE_PASS_BEGIN(DSE, "dse", "Dead
>  INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
>  INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
>  INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis)
> +INITIALIZE_PASS_DEPENDENCY(PostDominatorTree)
>  INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
>  INITIALIZE_PASS_END(DSE, "dse", "Dead Store Elimination", false, false)
>
> @@ -111,50 +167,6 @@ FunctionPass *llvm::createDeadStoreElimi
>  // Helper functions
>  //===----------------------------------------------------------------------===//
>
> -/// DeleteDeadInstruction - Delete this instruction.  Before we do, go through
> -/// and zero out all the operands of this instruction.  If any of them become
> -/// dead, delete them and the computation tree that feeds them.
> -///
> -/// If ValueSet is non-null, remove any deleted instructions from it as well.
> -///
> -static void DeleteDeadInstruction(Instruction *I,
> -                               MemoryDependenceAnalysis &MD,
> -                               const TargetLibraryInfo &TLI,
> -                               SmallSetVector<Value*, 16> *ValueSet = nullptr) {
> -  SmallVector<Instruction*, 32> NowDeadInsts;
> -
> -  NowDeadInsts.push_back(I);
> -  --NumFastOther;
> -
> -  // Before we touch this instruction, remove it from memdep!
> -  do {
> -    Instruction *DeadInst = NowDeadInsts.pop_back_val();
> -    ++NumFastOther;
> -
> -    // This instruction is dead, zap it, in stages.  Start by removing it from
> -    // MemDep, which needs to know the operands and needs it to be in the
> -    // function.
> -    MD.removeInstruction(DeadInst);
> -
> -    for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) {
> -      Value *Op = DeadInst->getOperand(op);
> -      DeadInst->setOperand(op, nullptr);
> -
> -      // If this operand just became dead, add it to the NowDeadInsts list.
> -      if (!Op->use_empty()) continue;
> -
> -      if (Instruction *OpI = dyn_cast<Instruction>(Op))
> -        if (isInstructionTriviallyDead(OpI, &TLI))
> -          NowDeadInsts.push_back(OpI);
> -    }
> -
> -    DeadInst->eraseFromParent();
> -
> -    if (ValueSet) ValueSet->remove(DeadInst);
> -  } while (!NowDeadInsts.empty());
> -}
> -
> -
>  /// hasMemoryWrite - Does this instruction write some memory?  This only returns
>  /// true for things that we can analyze with other helpers below.
>  static bool hasMemoryWrite(Instruction *I, const TargetLibraryInfo &TLI) {
> @@ -527,10 +539,15 @@ bool DSE::runOnBasicBlock(BasicBlock &BB
>
>      MemDepResult InstDep = MD->getDependency(Inst);
>
> -    // Ignore any store where we can't find a local dependence.
> -    // FIXME: cross-block DSE would be fun. :)
> -    if (!InstDep.isDef() && !InstDep.isClobber())
> +    if (!InstDep.isDef() && !InstDep.isClobber() && !InstDep.isNonLocal())
>        continue;
> +    if (InstDep.isNonLocal()) {
> +      if (!PDT->getRootNode())
> +        continue;
> +      if (StoreInst *SI = dyn_cast<StoreInst>(Inst))
> +        handleNonLocalStoreDeletion(SI, BBI, BB);
> +      continue;
> +    }
>
>      // Figure out what location is being stored to.
>      MemoryLocation Loc = getLocForWrite(Inst, *AA);
> @@ -704,6 +721,50 @@ static void FindUnconditionalPreds(Small
>    }
>  }
>
> +/// DeleteDeadInstruction - Delete this instruction.  Before we do, go through
> +/// and zero out all the operands of this instruction.  If any of them become
> +/// dead, delete them and the computation tree that feeds them.
> +/// If ValueSet is non-null, remove any deleted instructions from it as well.
> +void DSE::DeleteDeadInstruction(Instruction *I, MemoryDependenceAnalysis &MD,
> +                                const TargetLibraryInfo &TLI,
> +                                SmallSetVector<Value *, 16> *ValueSet) {
> +  SmallVector<Instruction *, 32> NowDeadInsts;
> +
> +  NowDeadInsts.push_back(I);
> +  --NumFastOther;
> +
> +  // Before we touch this instruction, remove it from memdep!
> +  do {
> +    Instruction *DeadInst = NowDeadInsts.pop_back_val();
> +    ++NumFastOther;
> +    if (StoreInst *SI = dyn_cast<StoreInst>(DeadInst))
> +      DeadStores.insert(SI);
> +
> +    // This instruction is dead, zap it, in stages.  Start by removing it from
> +    // MemDep, which needs to know the operands and needs it to be in the
> +    // function.
> +    MD.removeInstruction(DeadInst);
> +
> +    for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) {
> +      Value *Op = DeadInst->getOperand(op);
> +      DeadInst->setOperand(op, nullptr);
> +
> +      // If this operand just became dead, add it to the NowDeadInsts list.
> +      if (!Op->use_empty())
> +        continue;
> +
> +      if (Instruction *OpI = dyn_cast<Instruction>(Op))
> +        if (isInstructionTriviallyDead(OpI, &TLI))
> +          NowDeadInsts.push_back(OpI);
> +    }
> +
> +    DeadInst->eraseFromParent();
> +
> +    if (ValueSet)
> +      ValueSet->remove(DeadInst);
> +  } while (!NowDeadInsts.empty());
> +}
> +
>  /// HandleFree - Handle frees of entire structures whose dependency is a store
>  /// to a field of that structure.
>  bool DSE::HandleFree(CallInst *F) {
> @@ -931,3 +992,122 @@ void DSE::RemoveAccessedObjects(const Me
>      return !AA->isNoAlias(StackLoc, LoadedLoc);
>    });
>  }
> +
> +/// isSafeCandidateForDeletion- Check all paths from the SrcBlock till
> +/// SinkBlock to see if Store 'SI' is safe to be remove.
> +/// Returns true if the candidate store SI is safe to delete
> +/// else returns false.
> +bool DSE::isSafeCandidateForDeletion(BasicBlock *SrcBlock,
> +                                     BasicBlock *SinkBlock, StoreInst *SI) {
> +  SmallVector<BasicBlock *, 16> WorkList;
> +  SmallPtrSet<BasicBlock *, 8> Visited;
> +  BasicBlock::iterator BBI(SI);
> +
> +  // Check from the store till end of block and make sure we have no references
> +  // to memory stored by this Store Instruction.
> +  for (auto BI = ++BBI, BE = SrcBlock->end(); BI != BE; ++BI) {
> +    Instruction *I = BI;
> +    StoreInst *CSI = dyn_cast<StoreInst>(I);
> +    if (CSI) {
> +      AliasResult R =
> +          AA->alias(MemoryLocation::get(SI), MemoryLocation::get(CSI));
> +      if (R == MustAlias)
> +        return true;
> +    } else {
> +      ModRefInfo Res = AA->getModRefInfo(I, MemoryLocation::get(SI));
> +      if (Res != MRI_NoModRef)
> +        return false;
> +    }
> +  }
> +
> +  // Add successors of the block to stack and start DFS.
> +  for (succ_iterator I = succ_begin(SrcBlock), E = succ_end(SrcBlock); I != E;
> +       ++I) {
> +    if (!Visited.insert(*I).second)
> +      continue;
> +    // A path with backedge may not be safe. Conservatively mark
> +    // this store unsafe.
> +    if (BackEdgesMap.count(std::make_pair(SrcBlock, *I)))
> +      return false;
> +    WorkList.push_back(*I);
> +  }
> +
> +  while (!WorkList.empty()) {
> +    BasicBlock *B = WorkList.pop_back_val();
> +    auto BI = B->begin();
> +    auto BE = B->end();
> +    for (; BI != BE; ++BI) {
> +      Instruction *I = BI;
> +      StoreInst *CSI = dyn_cast<StoreInst>(I);
> +      if (CSI) {
> +        AliasResult R =
> +            AA->alias(MemoryLocation::get(SI), MemoryLocation::get(CSI));
> +        if (R == MustAlias)
> +          break;
> +      } else {
> +        ModRefInfo Res = AA->getModRefInfo(I, MemoryLocation::get(SI));
> +        if (Res != MRI_NoModRef)
> +          return false;
> +      }
> +    }
> +
> +    // If we reached the sink node or we found a block which has a stores that
> +    // overwrites the candidate block we need not look at their successors.
> +    if (B == SinkBlock || BI != BE)
> +      continue;
> +
> +    for (succ_iterator I = succ_begin(B), E = succ_end(B); I != E; ++I) {
> +      if (!Visited.insert(*I).second)
> +        continue;
> +      // A path with backedge may not be safe.Conservatively mark
> +      // this store unsafe.
> +      if (BackEdgesMap.count(std::make_pair(B, *I)))
> +        return false;
> +      WorkList.push_back(*I);
> +    }
> +  }
> +
> +  return true;
> +}
> +
> +/// handleNonLocalStoreDeletion - Handle non local dead store elimination.
> +/// This works by finding candidate stores using PDT and then running DFS
> +/// from candidate store block checking all paths to make sure the store is
> +/// safe to delete.
> +void DSE::handleNonLocalStoreDeletion(StoreInst *SI, BasicBlock::iterator &BBI,
> +                                      BasicBlock &CurBlock) {
> +  BasicBlock *BB = SI->getParent();
> +  Value *Pointer = SI->getPointerOperand();
> +  DomTreeNode *DTNode = PDT->getNode(BB);
> +  if (!DTNode)
> +    return;
> +
> +  int DFSNumIn = DTNode->getDFSNumIn();
> +  int DFSNumOut = DTNode->getDFSNumOut();
> +  for (int i = DFSNumIn + 1; i < DFSNumOut; ++i) {
> +    for (auto &I : Candidates[i]) {
> +      StoreInst *CandidateSI = I;
> +      if (DeadStores.count(CandidateSI))
> +        continue;
> +      Value *MemPtr = CandidateSI->getPointerOperand();
> +      if (!MemPtr)
> +        continue;
> +      if (Pointer->getType() != MemPtr->getType())
> +        continue;
> +      AliasResult R =
> +          AA->alias(MemoryLocation::get(SI), MemoryLocation::get(CandidateSI));
> +      if (R != MustAlias)
> +        continue;
> +      if (isSafeCandidateForDeletion(CandidateSI->getParent(), BB,
> +                                     CandidateSI)) {
> +        DeleteDeadInstruction(CandidateSI, *MD, *TLI);
> +        ++NumCrossBlockStores;
> +        // DeleteDeadInstruction can delete the current instruction in loop
> +        // cases, reset BBI.
> +        BBI = SI;
> +        if (BBI != CurBlock.begin())
> +          --BBI;
> +      }
> +    }
> +  }
> +}
>
> Added: llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll?rev=245195&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll (added)
> +++ llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll Mon Aug 17 00:51:39 2015
> @@ -0,0 +1,104 @@
> +; RUN: opt < %s -basicaa -dse -S | FileCheck %s
> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> +
> + at x = common global i32 0
> + at y = common global i32 0
> + at a = external global i32
> + at b = external global i32
> +
> +define void @test_01(i32 %N) {
> +  %1 = alloca i32
> +  store i32 %N, i32* %1
> +  store i32 10, i32* @x
> +  %2 = load i32, i32* %1
> +  %3 = icmp ne i32 %2, 0
> +  br i1 %3, label %4, label %5
> +
> +; <label>:4
> +  store i32 5, i32* @x
> +  br label %5
> +
> +; <label>:5
> +  store i32 15, i32* @x
> +  ret void
> +}
> +; CHECK-LABEL: @test_01(
> +; CHECK-NOT: store i32 10, i32* @x
> +; CHECK-NOT: store i32 5, i32* @x
> +; CHECK: store i32 15, i32* @x
> +
> +
> +define void @test_02(i32 %N) {
> +  %1 = alloca i32
> +  store i32 %N, i32* %1
> +  store i32 10, i32* @x
> +  %2 = load i32, i32* %1
> +  %3 = icmp ne i32 %2, 0
> +  br i1 %3, label %4, label %5
> +
> +; <label>:4
> +  store i32 5, i32* @x
> +  br label %7
> +
> +; <label>:5
> +  %6 = load i32, i32* @x
> +  store i32 %6, i32* @y
> +  br label %7
> +
> +; <label>:7
> +  store i32 15, i32* @x
> +  ret void
> +}
> +; CHECK-LABEL: @test_02(
> +; CHECK: store i32 10, i32* @x
> +; CHECK-NOT: store i32 5, i32* @x
> +; CHECK: store i32 %6, i32* @y
> +
> +
> +define void @test_03(i32 %N) #0 {
> +  %1 = alloca i32
> +  store i32 %N, i32* %1
> +  store i32 10, i32* @x
> +  %2 = load i32, i32* %1
> +  %3 = icmp ne i32 %2, 0
> +  br i1 %3, label %4, label %6
> +
> +; <label>:4                                       ; preds = %0
> +  %5 = load i32, i32* @x
> +  store i32 %5, i32* @y
> +  br label %6
> +
> +; <label>:6                                       ; preds = %4, %0
> +  store i32 15, i32* @x
> +  ret void
> +}
> +; CHECK-LABEL: @test_03(
> +; CHECK: store i32 10, i32* @x
> +; CHECK: store i32 %5, i32* @y
> +; CHECK: store i32 15, i32* @x
> +
> +
> +
> +; Check we safely delete store i32 %g.02, i32* @b below.(PR24469)
> +define void @test_04() {
> +entry:
> +  br i1 false, label %for.body, label %for.end.9
> +
> +for.cond.1.loopexit:                              ; preds = %for.body
> +  store i32 0, i32* @b
> +  %0 = load i32, i32* @a
> +  br i1 false, label %for.body, label %for.end.9
> +
> +for.body:                                         ; preds = %for.cond.1.loopexit, %entry
> +  %g.02 = phi i32 [ undef, %entry ], [ %0, %for.cond.1.loopexit ]
> +  store i32 %g.02, i32* @b
> +  br label %for.cond.1.loopexit
> +
> +for.end.9:                                        ; preds = %for.cond.1.loopexit, %entry
> +  ret void
> +}
> +
> +; CHECK-LABEL: @test_04(
> +; CHECK-NOT: store i32 %g.02, i32* @b
> +; CHECK-NOT: %g.02 = phi i32 [ undef, %entry ], [ %0, %for.cond.1.loopexit ]
> +; CHECK-NOT: %0 = load i32, i32* @a
>
> Added: llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll?rev=245195&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll (added)
> +++ llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll Mon Aug 17 00:51:39 2015
> @@ -0,0 +1,104 @@
> +; RUN: opt < %s -basicaa -dse -S | FileCheck %s
> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> +
> + at A = common global [100 x i32] zeroinitializer, align 16
> + at x = common global i32 0
> +
> +; Negative Test case-
> +;void foo(int N) {
> +;  A[0] = N;
> +;  for(int i=0;i<N;++i)
> +;    A[i]+=i;
> +;  A[0] = 10;
> +;}
> +;; Stores should not be optimized away.
> +
> +define void @test_01(i32 %N) #0 {
> +  %1 = alloca i32
> +  %i = alloca i32
> +  store i32 %N, i32* %1
> +  %2 = load i32, i32* %1
> +  store i32 %2, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)
> +  store i32 0, i32* %i
> +  br label %3
> +
> +; <label>:3                                       ; preds = %14, %0
> +  %4 = load i32, i32* %i
> +  %5 = load i32, i32* %1
> +  %6 = icmp slt i32 %4, %5
> +  br i1 %6, label %7, label %17
> +
> +; <label>:7                                       ; preds = %3
> +  %8 = load i32, i32* %i
> +  %9 = load i32, i32* %i
> +  %10 = sext i32 %9 to i64
> +  %11 = getelementptr inbounds [100 x i32], [100 x i32]* @A, i32 0, i64 %10
> +  %12 = load i32, i32* %11
> +  %13 = add nsw i32 %12, %8
> +  store i32 %13, i32* %11
> +  br label %14
> +
> +; <label>:14                                      ; preds = %7
> +  %15 = load i32, i32* %i
> +  %16 = add nsw i32 %15, 1
> +  store i32 %16, i32* %i
> +  br label %3
> +
> +; <label>:17                                      ; preds = %3
> +  store i32 10, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)
> +  ret void
> +}
> +; CHECK-LABEL: @test_01(
> +; CHECK: store i32 %2, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)
> +; CHECK: store i32 %13, i32* %11
> +; CHECK: store i32 10, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)
> +
> +
> +; Postive Test case-
> +;void foo(int N) {
> +;  A[0] = N;
> +;  for(int i=0;i<N;++i)
> +;    A[i]=i;
> +;  A[0] = 10;
> +;}
> +;; Stores should not be optimized away.
> +define void @test_02(i32 %N) #0 {
> +  %1 = alloca i32
> +  %i = alloca i32
> +  store i32 %N, i32* %1
> +  %2 = load i32, i32* %1
> +  store i32 %2, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)
> +  store i32 0, i32* %i
> +  br label %3
> +
> +; <label>:3                                       ; preds = %12, %0
> +  %4 = load i32, i32* %i
> +  %5 = load i32, i32* %1
> +  %6 = icmp slt i32 %4, %5
> +  br i1 %6, label %7, label %15
> +
> +; <label>:7                                       ; preds = %3
> +  %8 = load i32, i32* %i
> +  %9 = load i32, i32* %i
> +  %10 = sext i32 %9 to i64
> +  %11 = getelementptr inbounds [100 x i32], [100 x i32]* @A, i32 0, i64 %10
> +  store i32 %8, i32* %11
> +  br label %12
> +
> +; <label>:12                                      ; preds = %7
> +  %13 = load i32, i32* %i
> +  %14 = add nsw i32 %13, 1
> +  store i32 %14, i32* %i
> +  br label %3
> +
> +; <label>:15                                      ; preds = %3
> +  store i32 10, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)
> +  ret void
> +}
> +
> +; CHECK-LABEL: @test_02(
> +; CHECK-NOT: store i32 %2, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)
> +; CHECK: store i32 %7, i32* %10
> +; CHECK: store i32 10, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @A, i32 0, i64 0)
> +
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list