[PATCH] D21007: DSE: Don't remove stores made live by a call which unwinds.

Eli Friedman via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 5 15:54:38 PDT 2016


eli.friedman created this revision.
eli.friedman added reviewers: hfinkel, mcrosier, reames, majnemer.
eli.friedman added a subscriber: llvm-commits.

Issue exposed by noalias or more aggressive alias analysis.

Fixes http://llvm.org/PR25422.

http://reviews.llvm.org/D21007

Files:
  lib/Transforms/Scalar/DeadStoreElimination.cpp
  test/Transforms/DeadStoreElimination/simple.ll

Index: test/Transforms/DeadStoreElimination/simple.ll
===================================================================
--- test/Transforms/DeadStoreElimination/simple.ll
+++ test/Transforms/DeadStoreElimination/simple.ll
@@ -498,3 +498,14 @@
   ret i32 0
 }
 
+; Don't remove redundant store: unknown_func could unwind
+; CHECK-LABEL: @test34(
+; CHECK: store i32 1
+; CHECK: store i32 0
+; CHECK: ret
+define void @test34(i32* noalias %p) {
+  store i32 1, i32* %p
+  call void @unknown_func()
+  store i32 0, i32* %p
+  ret void
+}
Index: lib/Transforms/Scalar/DeadStoreElimination.cpp
===================================================================
--- lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -750,11 +750,15 @@
                                 const TargetLibraryInfo *TLI) {
   const DataLayout &DL = BB.getModule()->getDataLayout();
   bool MadeChange = false;
+  bool MayThrow = false;
 
   // Do a top-down walk on the BB.
   for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) {
     Instruction *Inst = &*BBI++;
 
+    if (Inst->mayThrow())
+      MayThrow = true;
+
     // Handle 'free' calls specially.
     if (CallInst *F = isFreeCall(Inst, TLI)) {
       MadeChange |= handleFree(F, AA, MD, DT, TLI);
@@ -845,6 +849,27 @@
       if (!DepLoc.Ptr)
         break;
 
+      // Make sure we don't look past a call which might throw. This is an
+      // issue because MemoryDependenceAnalysis works in the wrong direction:
+      // it finds instructions which dominate the current instruction, rather than
+      // instructions which are post-dominated by the current instruction.
+      //
+      // If the underlying object is a non-escaping memory allocation, any store
+      // to it is dead along the unwind edge. Otherwise, we need to preserve
+      // the store.
+      // FIXME: Check whether a throwing call is actually between the stores, instead
+      // of just in the same block.  Maybe using OrderedBasicBlock?
+      if (MayThrow) {
+        const Value* Underlying = GetUnderlyingObject(DepLoc.Ptr, DL);
+        bool IsStoreDeadOnUnwind = isa<AllocaInst>(Underlying);
+        if (!IsStoreDeadOnUnwind) {
+          IsStoreDeadOnUnwind = isAllocLikeFn(Underlying, TLI) &&
+              !PointerMayBeCapturedBefore(Underlying, true, true, Inst, DT, false);
+        }
+        if (!IsStoreDeadOnUnwind)
+          break;
+      }
+
       // If we find a write that is a) removable (i.e., non-volatile), b) is
       // completely obliterated by the store to 'Loc', and c) which we know that
       // 'Inst' doesn't load from, then we can remove it.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21007.59680.patch
Type: text/x-patch
Size: 2675 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160605/9f843f06/attachment.bin>


More information about the llvm-commits mailing list