[llvm] [JumpTableToSwitch] Fix wrong function used for GUID computation (PR #192877)
Alexander Shaposhnikov via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 19 15:36:08 PDT 2026
https://github.com/alexander-shaposhnikov updated https://github.com/llvm/llvm-project/pull/192877
>From 7d11f9e21f73042bfb6972fedf7ad7d1a5e9cf5a Mon Sep 17 00:00:00 2001
From: Alexander Shaposhnikov <alexander.v.shaposhnikov at gmail.com>
Date: Sun, 19 Apr 2026 15:11:22 -0700
Subject: [PATCH 1/3] [JumpTableToSwitch] Fix wrong function used for GUID
computation in profile data lookup
---
.../Transforms/Scalar/JumpTableToSwitch.cpp | 2 +-
.../profile-no-guid-metadata.ll | 41 +++++++++++++++++++
2 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/Transforms/JumpTableToSwitch/profile-no-guid-metadata.ll
diff --git a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
index a3e3b9a207ca1..4ff9756705320 100644
--- a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
@@ -215,7 +215,7 @@ PreservedAnalyses JumpTableToSwitchPass::run(Function &F,
if (Fct.getMetadata(AssignGUIDPass::GUIDMetadataName))
return AssignGUIDPass::getGUID(Fct);
- return Function::getGUIDAssumingExternalLinkage(getIRPGOFuncName(F, InLTO));
+ return Function::getGUIDAssumingExternalLinkage(getIRPGOFuncName(Fct, InLTO));
};
for (BasicBlock &BB : make_early_inc_range(F)) {
diff --git a/llvm/test/Transforms/JumpTableToSwitch/profile-no-guid-metadata.ll b/llvm/test/Transforms/JumpTableToSwitch/profile-no-guid-metadata.ll
new file mode 100644
index 0000000000000..32c416cd9355b
--- /dev/null
+++ b/llvm/test/Transforms/JumpTableToSwitch/profile-no-guid-metadata.ll
@@ -0,0 +1,41 @@
+; RUN: opt < %s -passes=jump-table-to-switch -S | FileCheck %s
+
+;; Test that when target functions lack !guid metadata, the pass correctly
+;; computes GUIDs from the target function names (not the caller's name)
+;; for matching against value profile data. This is a regression test for
+;; a bug where the caller function was used instead of the callee when
+;; computing PGO function names for GUID lookup.
+
+ at jt = constant [2 x ptr] [ptr @jt_target_0, ptr @jt_target_1]
+
+;; Note: these functions intentionally do NOT have !guid metadata,
+;; forcing the pass to compute GUIDs via getIRPGOFuncName.
+define i32 @jt_target_0() {
+ ret i32 10
+}
+
+define i32 @jt_target_1() {
+ ret i32 20
+}
+
+define i32 @caller(i32 %idx) {
+; CHECK-LABEL: define i32 @caller(
+; CHECK: switch i32 [[IDX:%.*]], label %{{.*}} [
+; CHECK-NEXT: i32 0, label %[[CALL0:.*]]
+; CHECK-NEXT: i32 1, label %[[CALL1:.*]]
+; CHECK-NEXT: ], !prof [[PROF:![0-9]+]]
+; CHECK: [[CALL0]]:
+; CHECK-NEXT: {{.*}} = call i32 @jt_target_0()
+; CHECK: [[CALL1]]:
+; CHECK-NEXT: {{.*}} = call i32 @jt_target_1()
+ %gep = getelementptr inbounds [2 x ptr], ptr @jt, i32 0, i32 %idx
+ %fptr = load ptr, ptr %gep
+ %r = call i32 %fptr(), !prof !0
+ ret i32 %r
+}
+
+;; VP metadata: GUID 11912887233601027218 = MD5("jt_target_0"), count 100
+;; GUID 18156790114353049777 = MD5("jt_target_1"), count 50
+!0 = !{!"VP", i32 0, i64 150, i64 11912887233601027218, i64 100, i64 18156790114353049777, i64 50}
+
+; CHECK: [[PROF]] = !{!"branch_weights", i32 0, i32 100, i32 50}
>From 6884ff85441c4cae4d545abebe5e5be8d61c4375 Mon Sep 17 00:00:00 2001
From: Alexander Shaposhnikov <alexander.v.shaposhnikov at gmail.com>
Date: Sun, 19 Apr 2026 15:16:28 -0700
Subject: [PATCH 2/3] Apply clang-format
---
llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
index 4ff9756705320..a236c82827358 100644
--- a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
@@ -215,7 +215,8 @@ PreservedAnalyses JumpTableToSwitchPass::run(Function &F,
if (Fct.getMetadata(AssignGUIDPass::GUIDMetadataName))
return AssignGUIDPass::getGUID(Fct);
- return Function::getGUIDAssumingExternalLinkage(getIRPGOFuncName(Fct, InLTO));
+ return Function::getGUIDAssumingExternalLinkage(
+ getIRPGOFuncName(Fct, InLTO));
};
for (BasicBlock &BB : make_early_inc_range(F)) {
>From 8fba6ac81f8ed7cf701280f16f60601db8f5912c Mon Sep 17 00:00:00 2001
From: Alexander Shaposhnikov <alexander.v.shaposhnikov at gmail.com>
Date: Sun, 19 Apr 2026 15:35:56 -0700
Subject: [PATCH 3/3] Address comments
---
.../Transforms/Scalar/JumpTableToSwitch.cpp | 2 +-
.../profile-no-guid-metadata.ll | 30 +++++++++++++++----
2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
index a236c82827358..128d23bee20f9 100644
--- a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
@@ -211,7 +211,7 @@ PreservedAnalyses JumpTableToSwitchPass::run(Function &F,
PostDominatorTree *PDT = AM.getCachedResult<PostDominatorTreeAnalysis>(F);
DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
bool Changed = false;
- auto FuncToGuid = [&](const Function &Fct) {
+ auto FuncToGuid = [InLTO = this->InLTO](const Function &Fct) {
if (Fct.getMetadata(AssignGUIDPass::GUIDMetadataName))
return AssignGUIDPass::getGUID(Fct);
diff --git a/llvm/test/Transforms/JumpTableToSwitch/profile-no-guid-metadata.ll b/llvm/test/Transforms/JumpTableToSwitch/profile-no-guid-metadata.ll
index 32c416cd9355b..f4e71c637608a 100644
--- a/llvm/test/Transforms/JumpTableToSwitch/profile-no-guid-metadata.ll
+++ b/llvm/test/Transforms/JumpTableToSwitch/profile-no-guid-metadata.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes=jump-table-to-switch -S | FileCheck %s
;; Test that when target functions lack !guid metadata, the pass correctly
@@ -11,23 +12,40 @@
;; Note: these functions intentionally do NOT have !guid metadata,
;; forcing the pass to compute GUIDs via getIRPGOFuncName.
define i32 @jt_target_0() {
+; CHECK-LABEL: define i32 @jt_target_0() {
+; CHECK-NEXT: ret i32 10
+;
ret i32 10
}
define i32 @jt_target_1() {
+; CHECK-LABEL: define i32 @jt_target_1() {
+; CHECK-NEXT: ret i32 20
+;
ret i32 20
}
define i32 @caller(i32 %idx) {
; CHECK-LABEL: define i32 @caller(
-; CHECK: switch i32 [[IDX:%.*]], label %{{.*}} [
+; CHECK-SAME: i32 [[IDX:%.*]]) {
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @jt, i32 0, i32 [[IDX]]
+; CHECK-NEXT: [[FPTR:%.*]] = load ptr, ptr [[GEP]], align 8
+; CHECK-NEXT: switch i32 [[IDX]], label %[[DEFAULT_SWITCH_CASE_UNREACHABLE:.*]] [
; CHECK-NEXT: i32 0, label %[[CALL0:.*]]
; CHECK-NEXT: i32 1, label %[[CALL1:.*]]
-; CHECK-NEXT: ], !prof [[PROF:![0-9]+]]
+; CHECK-NEXT: ], !prof [[PROF0:![0-9]+]]
+; CHECK: [[DEFAULT_SWITCH_CASE_UNREACHABLE]]:
+; CHECK-NEXT: unreachable
; CHECK: [[CALL0]]:
-; CHECK-NEXT: {{.*}} = call i32 @jt_target_0()
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @jt_target_0()
+; CHECK-NEXT: br [[DOTTAIL:label %.*]]
; CHECK: [[CALL1]]:
-; CHECK-NEXT: {{.*}} = call i32 @jt_target_1()
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @jt_target_1()
+; CHECK-NEXT: br [[DOTTAIL]]
+; CHECK: [[_TAIL:.*:]]
+; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP1]], %[[CALL0]] ], [ [[TMP2]], %[[CALL1]] ]
+; CHECK-NEXT: ret i32 [[TMP3]]
+;
%gep = getelementptr inbounds [2 x ptr], ptr @jt, i32 0, i32 %idx
%fptr = load ptr, ptr %gep
%r = call i32 %fptr(), !prof !0
@@ -38,4 +56,6 @@ define i32 @caller(i32 %idx) {
;; GUID 18156790114353049777 = MD5("jt_target_1"), count 50
!0 = !{!"VP", i32 0, i64 150, i64 11912887233601027218, i64 100, i64 18156790114353049777, i64 50}
-; CHECK: [[PROF]] = !{!"branch_weights", i32 0, i32 100, i32 50}
+;.
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 0, i32 100, i32 50}
+;.
More information about the llvm-commits
mailing list