[llvm] [EarlyCSE] Correcting assertion for DSE with invariant loads (PR #141495)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 26 07:10:00 PDT 2025
https://github.com/zGoldthorpe created https://github.com/llvm/llvm-project/pull/141495
This patch corrects an assertion to handle an edge case where there is a dead store into an `!invariant.load`'s pointer, but there is an interleaving store to a different (non-aliasing) address.
The assertion is in place to verify that the putatively dead store is actually dead; in particular, it ensures that at least one of the following conditions hold:
1. There were no previous stores before the putatively dead store.
2. There are no interleaving stores between the `!invariant.load` and the corresponding putatively dead store to the same address.
3. `memssa` is enabled.
However, the assertion seems to have mistakenly inverted the 2nd condition.
This bug was found through the AMD fuzzing project.
>From 1cd811beb2367480157e3a46ea711e853833d62f Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <zgoldtho at ualberta.ca>
Date: Thu, 22 May 2025 17:45:15 -0500
Subject: [PATCH] Correct EarlyCSE assert for DSE with invariant loads
---
llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 2 +-
.../Transforms/EarlyCSE/invariant-loads.ll | 27 +++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index 1e378369166c0..211c2d23387ad 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -1704,7 +1704,7 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
// In that case, LastStore should keep its present value since we're
// removing the current store.
assert((!LastStore ||
- ParseMemoryInst(LastStore, TTI).getPointerOperand() ==
+ ParseMemoryInst(LastStore, TTI).getPointerOperand() !=
MemInst.getPointerOperand() ||
MSSA) &&
"can't have an intervening store if not using MemorySSA!");
diff --git a/llvm/test/Transforms/EarlyCSE/invariant-loads.ll b/llvm/test/Transforms/EarlyCSE/invariant-loads.ll
index 88454660711ed..96a8fc3ddc00a 100644
--- a/llvm/test/Transforms/EarlyCSE/invariant-loads.ll
+++ b/llvm/test/Transforms/EarlyCSE/invariant-loads.ll
@@ -4,6 +4,7 @@
; RUN: opt -S -passes='early-cse<memssa>' --enable-knowledge-retention < %s | FileCheck %s --check-prefixes=CHECK,USE_ASSUME
declare void @clobber_and_use(i32)
+declare void @clobber_and_combine(i32, i32)
define void @f_0(ptr %ptr) {
; NO_ASSUME-LABEL: @f_0(
@@ -164,6 +165,32 @@ define void @test_dse1(ptr %p) {
ret void
}
+; Extending @test_dse1, the call can't change the contents of p.invariant.
+; Moreover, the contents of p.invariant cannot change from the store to p.
+define void @test_dse2(ptr noalias %p, ptr noalias %p.invariant) {
+; NO_ASSUME-LABEL: @test_dse2(
+; NO_ASSUME-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4
+; NO_ASSUME-NEXT: [[V_INVARIANT:%.*]] = load i32, ptr [[P_INVARIANT:%.*]], align 4, !invariant.load !0
+; NO_ASSUME-NEXT: [[V_COMB:%.*]] = call i32 @clobber_and_combine(i32 [[V]], i32 [[V_INVARIANT]])
+; NO_ASSUME-NEXT: store i32 [[V_COMB]], ptr [[P]], align 4
+; NO_ASSUME-NEXT: ret void
+;
+; USE_ASSUME-LABEL: @test_dse2(
+; USE_ASSUME-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4
+; USE_ASSUME-NEXT: [[V_INVARIANT:%.*]] = load i32, ptr [[P_INVARIANT:%.*]], align 4, !invariant.load !0
+; USE_ASSUME-NEXT: [[V_COMB:%.*]] = call i32 @clobber_and_combine(i32 [[V]], i32 [[V_INVARIANT]])
+; USE_ASSUME-NEXT: store i32 [[V_COMB]], ptr [[P]], align 4
+; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P_INVARIANT]], i64 4), "nonnull"(ptr [[P_INVARIANT]]), "align"(ptr [[P_INVARIANT]], i64 4) ]
+; USE_ASSUME-NEXT: ret void
+;
+ %v = load i32, ptr %p
+ %v.invariant = load i32, ptr %p.invariant, !invariant.load !{}
+ %v.comb = call i32 @clobber_and_combine(i32 %v, i32 %v.invariant)
+ store i32 %v.comb, ptr %p
+ store i32 %v.invariant, ptr %p.invariant
+ ret void
+}
+
; By assumption, v1 must equal v2 (TODO)
define void @test_false_negative_dse2(ptr %p, i32 %v2) {
; CHECK-LABEL: @test_false_negative_dse2(
More information about the llvm-commits
mailing list