<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>