<div dir="ltr">Seems nondeteministic behavior. Investigating.<br>See, <a href="http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2935">http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2935</a></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Aug 14, 2015 at 1:18 PM Karthik Bhat via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: karthik<br>
Date: Thu Aug 13 23:17:23 2015<br>
New Revision: 245025<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=245025&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=245025&view=rev</a><br>
Log:<br>
Add support for cross block dse.<br>
This patch enables dead stroe elimination across basicblocks.<br>
<br>
Example:<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>
; <label>:4<br>
store i32 5, i32* @x<br>
br label %7<br>
<br>
; <label>:5<br>
%6 = load i32, i32* @x<br>
store i32 %6, i32* @y<br>
br label %7<br>
<br>
; <label>:7<br>
store i32 15, i32* @x<br>
ret void<br>
}<br>
In the above example dead store "store i32 5, i32* @x" is now eliminated.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D11143" rel="noreferrer" target="_blank">http://reviews.llvm.org/D11143</a><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=245025&r1=245024&r2=245025&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=245025&r1=245024&r2=245025&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Thu Aug 13 23:17:23 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<SmallVector<StoreInst *, 8>, 16> Candidates;<br>
+ SetVector<StoreInst *> DeadStores;<br>
+ SmallVector<std::pair<const BasicBlock *, const BasicBlock *>, 32><br>
+ BackEdges;<br>
+ DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> 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<StoreInst *, 8> getStores(BasicBlock *BB) {<br>
+ SmallVector<StoreInst *, 8> VecStores;<br>
+ for (auto &BI : *BB) {<br>
+ if (StoreInst *SI = dyn_cast<StoreInst>(&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<StoreInst *, 8> 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<MemoryDependenceAnalysis>();<br>
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();<br>
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();<br>
-<br>
+ PDT = &getAnalysis<PostDominatorTree>();<br>
+ if (PDT->getRootNode()) {<br>
+ int Count = PDT->getRootNode()->getDFSNumOut();<br>
+ SmallVector<StoreInst *, 8> 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,23 @@ namespace {<br>
void RemoveAccessedObjects(const MemoryLocation &LoadedLoc,<br>
SmallSetVector<Value *, 16> &DeadStackObjects,<br>
const DataLayout &DL);<br>
-<br>
+ void handleNonLocalStoreDeletion(StoreInst *SI);<br>
+ bool isSafeCandidateForDeletion(BasicBlock *SrcBlock, BasicBlock *SinkBlock,<br>
+ StoreInst *SI);<br>
+ void DeleteDeadInstruction(Instruction *I, MemoryDependenceAnalysis &MD,<br>
+ const TargetLibraryInfo &TLI,<br>
+ SmallSetVector<Value *, 16> *ValueSet = nullptr);<br>
void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
AU.setPreservesCFG();<br>
AU.addRequired<DominatorTreeWrapperPass>();<br>
AU.addRequired<AliasAnalysis>();<br>
AU.addRequired<MemoryDependenceAnalysis>();<br>
+ AU.addRequired<PostDominatorTree>();<br>
AU.addRequired<TargetLibraryInfoWrapperPass>();<br>
AU.addPreserved<AliasAnalysis>();<br>
AU.addPreserved<DominatorTreeWrapperPass>();<br>
AU.addPreserved<MemoryDependenceAnalysis>();<br>
+ AU.addPreserved<PostDominatorTree>();<br>
}<br>
};<br>
}<br>
@@ -102,6 +156,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 +166,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<Value*, 16> *ValueSet = nullptr) {<br>
- SmallVector<Instruction*, 32> 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<Instruction>(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 +538,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<StoreInst>(Inst))<br>
+ handleNonLocalStoreDeletion(SI);<br>
+ continue;<br>
+ }<br>
<br>
// Figure out what location is being stored to.<br>
MemoryLocation Loc = getLocForWrite(Inst, *AA);<br>
@@ -704,6 +720,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<Value *, 16> *ValueSet) {<br>
+ SmallVector<Instruction *, 32> 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<StoreInst>(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<Instruction>(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 +991,116 @@ 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<BasicBlock *, 16> WorkList;<br>
+ SmallPtrSet<BasicBlock *, 8> 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<StoreInst>(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<StoreInst>(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) {<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>
+ }<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=245025&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse.ll?rev=245025&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 Thu Aug 13 23:17:23 2015<br>
@@ -0,0 +1,76 @@<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>
+<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>
+; <label>:4<br>
+ store i32 5, i32* @x<br>
+ br label %5<br>
+<br>
+; <label>: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>
+; <label>:4<br>
+ store i32 5, i32* @x<br>
+ br label %7<br>
+<br>
+; <label>:5<br>
+ %6 = load i32, i32* @x<br>
+ store i32 %6, i32* @y<br>
+ br label %7<br>
+<br>
+; <label>: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>
+; <label>:4 ; preds = %0<br>
+ %5 = load i32, i32* @x<br>
+ store i32 %5, i32* @y<br>
+ br label %6<br>
+<br>
+; <label>: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>
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=245025&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/cross_block_dse_loop.ll?rev=245025&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 Thu Aug 13 23:17:23 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<N;++i)<br>
+; 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>
+; <label>: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>
+; <label>: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>
+; <label>: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>
+; <label>: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<N;++i)<br>
+; 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>
+; <label>: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>
+; <label>: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>
+; <label>: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>
+; <label>: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>
</blockquote></div>