[llvm] 633e090 - [DSE] Allow ptrs defined in the entry block in IsGuaranteedLoopInvariant.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 23 04:01:05 PST 2021


Author: Matteo Favaro
Date: 2021-02-23T12:00:44Z
New Revision: 633e090528dbc9b6dd380771046af8463bbb5fe1

URL: https://github.com/llvm/llvm-project/commit/633e090528dbc9b6dd380771046af8463bbb5fe1
DIFF: https://github.com/llvm/llvm-project/commit/633e090528dbc9b6dd380771046af8463bbb5fe1.diff

LOG: [DSE] Allow ptrs defined in the entry block in IsGuaranteedLoopInvariant.

The **IsGuaranteedLoopInvariant** function is making sure to check if the
incoming pointer is guaranteed to be loop invariant, therefore I think
the case where the pointer is defined in the entry block of a function
automatically guarantees the pointer to be loop invariant, as the entry
block of a function cannot have predecessors or be part of a loop.

I implemented this small patch and tested it using
**ninja check-llvm-unit** and **ninja check-llvm**. I added a contained test
file that shows the problem and used **opt -O3 -debug** on it to make sure
the case is not currently handled (in fact the debug log is showing that
the DSE pass is bailing out when testing if the killer store is able to
clobber the dead store).

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D96979

Added: 
    llvm/test/Transforms/DeadStoreElimination/MSSA/loop-invariant-entry-block.ll

Modified: 
    llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 9fcfdbee5e53..7d58292da0a3 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1911,6 +1911,11 @@ struct DSEState {
     };
 
     Ptr = Ptr->stripPointerCasts();
+    if (auto *I = dyn_cast<Instruction>(Ptr)) {
+      if (I->getParent() == &I->getFunction()->getEntryBlock()) {
+        return true;
+      }
+    }
     if (auto *GEP = dyn_cast<GEPOperator>(Ptr)) {
       return IsGuaranteedLoopInvariantBase(GEP->getPointerOperand()) &&
              GEP->hasAllConstantIndices();

diff  --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/loop-invariant-entry-block.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/loop-invariant-entry-block.ll
new file mode 100644
index 000000000000..cd639e25bed0
--- /dev/null
+++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/loop-invariant-entry-block.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -dse -S | FileCheck %s
+
+ at BUFFER = external dso_local local_unnamed_addr global [0 x i8], align 1
+
+define void @MissedDSEOpportunity(i64 %idx, i1* noalias %cc) {
+;
+; The DSE pass will try to kill the store in the loop exit block using the
+; store in the function exit block. The loop invariant check on the pointer
+; used by the stores should trivially return true because a pointer defined
+; in the entry block of a function is loop invariant by definition. In fact
+; the entry block of a function cannot have predecessors or be part of a loop.
+;
+; CHECK-LABEL: @MissedDSEOpportunity(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [0 x i8], [0 x i8]* @BUFFER, i64 0, i64 [[IDX:%.*]]
+; CHECK-NEXT:    [[BC:%.*]] = bitcast i8* [[GEP]] to i64*
+; CHECK-NEXT:    [[CC0:%.*]] = load volatile i1, i1* [[CC:%.*]], align 1
+; CHECK-NEXT:    br i1 [[CC0]], label [[HEAD:%.*]], label [[EXIT:%.*]]
+; CHECK:       head:
+; CHECK-NEXT:    [[CC1:%.*]] = load volatile i1, i1* [[CC]], align 1
+; CHECK-NEXT:    br i1 [[CC1]], label [[HEAD]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    store i64 0, i64* [[BC]], align 4
+; CHECK-NEXT:    ret void
+;
+entry:
+  ; The entry block cannot have predecessors or be part of a loop
+  %gep = getelementptr inbounds [0 x i8], [0 x i8]* @BUFFER, i64 0, i64 %idx
+  %bc = bitcast i8* %gep to i64*
+  %cc0 = load volatile i1, i1* %cc, align 1
+  br i1 %cc0, label %head, label %exit
+
+head:                                             ; preds = %entry, %head
+  %cc1 = load volatile i1, i1* %cc, align 1
+  br i1 %cc1, label %head, label %exit.loopexit
+
+exit.loopexit:                                    ; preds = %head
+  ; Dead store
+  store i64 2, i64* %bc, align 4
+  br label %exit
+
+exit:                                             ; preds = %exit.loopexit, %entry
+  ; Killer store
+  store i64 0, i64* %bc, align 4
+  ret void
+}
\ No newline at end of file


        


More information about the llvm-commits mailing list