[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
This commit is contained in:
Matteo Favaro 2021-02-23 10:22:53 +00:00 committed by Florian Hahn
parent 53c4c2b9f7
commit 633e090528
No known key found for this signature in database
GPG Key ID: 61D7554B5CECDC0D
2 changed files with 54 additions and 0 deletions

View File

@ -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();

View File

@ -0,0 +1,49 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -dse -S | FileCheck %s
@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
}