[llvm] [GVN] Fix vtable processing of static object (PR #223456)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 09:51:06 PDT 2026
https://github.com/eleviant created https://github.com/llvm/llvm-project/pull/223456
Patch fixes crash in GVN pass when compiling this C++ code:
https://godbolt.org/z/sbKMa5K1d
>From 435cffebc28c5cfe1beb686b412d8174c1587dc9 Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <eleviant at accesssoftek.com>
Date: Mon, 14 Sep 2026 18:44:52 +0200
Subject: [PATCH] [GVN] Fix vtable processing of static object
Patch fixes crash in GVN pass when compiling this C++ code:
https://godbolt.org/z/sbKMa5K1d
---
.../lib/Analysis/MemoryDependenceAnalysis.cpp | 3 +-
llvm/test/Transforms/GVN/strict-vtable.ll | 38 +++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/Transforms/GVN/strict-vtable.ll
diff --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
index a58608b53bb1f..1b1c8542049b3 100644
--- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -323,7 +323,8 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
for (const Use &Us : LoadOperand->uses()) {
auto *U = dyn_cast<Instruction>(Us.getUser());
- if (!U || U == LI || !DT.dominates(U, LI))
+ if (!U || U == LI || U->getFunction() != LI->getFunction() ||
+ !DT.dominates(U, LI))
continue;
// If we hit load/store with the same invariant.group metadata (and the
diff --git a/llvm/test/Transforms/GVN/strict-vtable.ll b/llvm/test/Transforms/GVN/strict-vtable.ll
new file mode 100644
index 0000000000000..91c6575d7e2fb
--- /dev/null
+++ b/llvm/test/Transforms/GVN/strict-vtable.ll
@@ -0,0 +1,38 @@
+; RUN: opt -passes=gvn -S %s -o /dev/null
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
+
+$_ZTV1i = comdat any
+
+$_ZTI1i = comdat any
+
+$_ZTS1i = comdat any
+
+ at f = dso_local local_unnamed_addr global float 0.000000e+00, align 4
+ at _ZZ1gvE1a = internal global { ptr, ptr } { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr], [3 x ptr] }, ptr @_ZTV1i, i32 0, i32 0, i32 2), ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr], [3 x ptr] }, ptr @_ZTV1i, i32 0, i32 1, i32 2) }, align 8
+ at _ZTV1i = linkonce_odr dso_local constant { [3 x ptr], [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI1i, ptr @_ZN1b1cEv], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr @_ZTI1i, ptr @_ZN1d1eEf] }, comdat, align 8
+ at _ZTI1i = linkonce_odr dso_local constant { ptr, ptr, i32, i32, ptr, i64, ptr, i64 } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2), ptr @_ZTS1i, i32 0, i32 2, ptr @_ZTI1b, i64 2, ptr @_ZTI1d, i64 2050 }, comdat, align 8
+ at _ZTVN10__cxxabiv121__vmi_class_type_infoE = external global [0 x ptr]
+ at _ZTS1i = linkonce_odr dso_local constant [3 x i8] c"1i\00", comdat, align 1
+ at _ZTI1b = external constant ptr
+ at _ZTI1d = external constant ptr
+
+define dso_local void @_Z1hv() local_unnamed_addr {
+entry:
+ %0 = load float, ptr @f, align 4
+ %vtable = load ptr, ptr getelementptr inbounds nuw (i8, ptr @_ZZ1gvE1a, i64 8), align 8, !invariant.group !0
+ %1 = load ptr, ptr %vtable, align 8, !invariant.load !0
+ tail call void %1(ptr noundef nonnull align 8 dereferenceable(8) getelementptr inbounds nuw (i8, ptr @_ZZ1gvE1a, i64 8), float noundef %0)
+ ret void
+}
+
+define dso_local noundef nonnull align 8 dereferenceable(8) ptr @_Z1gv() local_unnamed_addr {
+entry:
+ ret ptr getelementptr inbounds nuw (i8, ptr @_ZZ1gvE1a, i64 8)
+}
+
+declare noundef i32 @_ZN1b1cEv(ptr noundef nonnull align 8 dereferenceable(8)) unnamed_addr
+
+declare void @_ZN1d1eEf(ptr noundef nonnull align 8 dereferenceable(8), float noundef) unnamed_addr
+
+!0 = !{}
More information about the llvm-commits
mailing list