[llvm] 12f00f9 - [GVN] Skip instructions without value numbers in `processNonLocalLoad` (#219851)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 01:08:33 PDT 2026
Author: Nikhil Ludder
Date: 2026-09-11T10:08:27+02:00
New Revision: 12f00f9cd311a910a84f3e8a05b5b0c96e2bdf78
URL: https://github.com/llvm/llvm-project/commit/12f00f9cd311a910a84f3e8a05b5b0c96e2bdf78
DIFF: https://github.com/llvm/llvm-project/commit/12f00f9cd311a910a84f3e8a05b5b0c96e2bdf78.diff
LOG: [GVN] Skip instructions without value numbers in `processNonLocalLoad` (#219851)
GVN may insert coercion instructions (MaterializeAdjustedValue) without
assigning them value numbers. If one becomes a GEP index of a PRE'd load
in the same processBlock sweep, the GEP-index scalar PRE in
processNonLocalLoad reaches it before the next re-numbering iteration
and the verifying VN.lookup() may assert. Avoid performing PRE on such
instructions.
Fixes: #216265.
Added:
llvm/test/Transforms/GVN/pre-coerced-value-not-numbered.ll
Modified:
llvm/lib/Transforms/Scalar/GVN.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index 2f34f9124e580..c8989a4c8e0d4 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -2122,7 +2122,10 @@ bool GVNPass::processNonLocalLoad(LoadInst *Load,
if (GetElementPtrInst *GEP =
dyn_cast<GetElementPtrInst>(Load->getOperand(0))) {
for (Use &U : GEP->indices())
- if (Instruction *I = dyn_cast<Instruction>(U.get()))
+ // Instructions inserted by GVN during this iteration (e.g. coercion
+ // casts from MaterializeAdjustedValue) may not have value numbers yet,
+ // so they are skipped.
+ if (Instruction *I = dyn_cast<Instruction>(U.get()); I && VN.exists(I))
Changed |= performScalarPRE(I);
}
}
diff --git a/llvm/test/Transforms/GVN/pre-coerced-value-not-numbered.ll b/llvm/test/Transforms/GVN/pre-coerced-value-not-numbered.ll
new file mode 100644
index 0000000000000..555ea301c0caa
--- /dev/null
+++ b/llvm/test/Transforms/GVN/pre-coerced-value-not-numbered.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=gvn -S < %s | FileCheck %s
+
+; Test for #216265. GVN forwards the i64 store to the i8 load (%conv),
+; inserting a coercing `trunc i64 %x to i8` via MaterializeAdjustedValue
+; without assigning it a value number. When scalar PRE later runs on the GEP
+; indices of the PRE'd load, it encounters the unnumbered trunc and asserts
+; in VN.lookup().
+
+ at g = external global i64
+
+define void @test_coerced_value_not_numbered(i64 noundef %x) {
+; CHECK-LABEL: define void @test_coerced_value_not_numbered(
+; CHECK-SAME: i64 noundef [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[ARR:%.*]] = alloca [256 x i8], align 1
+; CHECK-NEXT: [[BASE:%.*]] = getelementptr inbounds i8, ptr [[ARR]], i64 128
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[TMP0:%.*]], %[[LOOP]] ]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i8 [[IV]]
+; CHECK-NEXT: call void @use(i8 undef)
+; CHECK-NEXT: store i64 [[X]], ptr @g, align 4
+; CHECK-NEXT: [[TMP0]] = trunc i64 [[X]] to i8
+; CHECK-NEXT: [[GEP_PHI_TRANS_INSERT:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i8 [[TMP0]]
+; CHECK-NEXT: br label %[[LOOP]]
+;
+entry:
+ %arr = alloca [256 x i8]
+ %base = getelementptr inbounds i8, ptr %arr, i64 128
+ br label %loop
+
+loop:
+ %iv = phi i8 [ 0, %entry ], [ %conv, %loop ]
+ %gep = getelementptr inbounds i8, ptr %base, i8 %iv
+ %load1 = load i8, ptr %gep
+ call void @use(i8 %load1)
+ store i64 %x, ptr @g
+ %conv = load i8, ptr @g
+ br label %loop
+}
+
+declare void @use(i8)
More information about the llvm-commits
mailing list