[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