[llvm] [MergeFunctions] Fix merging functions with different KCFI type identifiers (PR #217665)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 21 08:51:53 PDT 2026
https://github.com/Lane0218 updated https://github.com/llvm/llvm-project/pull/217665
>From 6996e634dee1a7b05f83c9fd949aea37c695a0a2 Mon Sep 17 00:00:00 2001
From: Lane0218 <laneljc at qq.com>
Date: Thu, 20 Aug 2026 23:26:33 +0800
Subject: [PATCH 1/3] [MergeFunctions] Fix merging functions with different
KCFI type identifiers
---
llvm/docs/MergeFunctions.md | 2 ++
.../Transforms/Utils/FunctionComparator.cpp | 4 +++
.../MergeFunc/kcfi-function-merging.ll | 36 +++++++++++++++++++
3 files changed, 42 insertions(+)
create mode 100644 llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
diff --git a/llvm/docs/MergeFunctions.md b/llvm/docs/MergeFunctions.md
index bb39e40032894..adc8bcec7c5d4 100644
--- a/llvm/docs/MergeFunctions.md
+++ b/llvm/docs/MergeFunctions.md
@@ -279,6 +279,8 @@ properties to be compared on this stage:
- *Variable arguments*. *LHS* and *RHS* should be both either with or
without *var-args*.
- *Calling convention* should be the same.
+ - *KCFI type metadata*. Function-level `!kcfi_type` metadata, if present,
+ should be identical.
2. Function type. Checked by `FunctionComparator::cmpType(Type*, Type*)`
method. It checks return type and parameters type; the method itself will be
diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp
index 05c24af6efb39..9e84c78087303 100644
--- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp
@@ -990,6 +990,10 @@ int FunctionComparator::compareSignature() const {
if (int Res = cmpAttrs(FnL->getAttributes(), FnR->getAttributes()))
return Res;
+ if (int Res = cmpMDNode(FnL->getMetadata(LLVMContext::MD_kcfi_type),
+ FnR->getMetadata(LLVMContext::MD_kcfi_type)))
+ return Res;
+
if (int Res = cmpNumbers(FnL->hasGC(), FnR->hasGC()))
return Res;
diff --git a/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll b/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
new file mode 100644
index 0000000000000..c3d3daadc5f51
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
@@ -0,0 +1,36 @@
+; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
+
+; Functions with different KCFI type identifiers must not be merged.
+
+define internal i32 @a() unnamed_addr !kcfi_type !0 {
+; CHECK-LABEL: define internal i32 @a()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i32 0
+; CHECK-NEXT: }
+entry:
+ ret i32 0
+}
+
+define internal i32 @b() unnamed_addr !kcfi_type !1 {
+; CHECK-LABEL: define internal i32 @b()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i32 0
+; CHECK-NEXT: }
+entry:
+ ret i32 0
+}
+
+define i32 @caller() {
+; CHECK-LABEL: define i32 @caller()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %x = call i32 @a()
+; CHECK-NEXT: %y = call i32 @b()
+; CHECK-NEXT: ret i32 %y
+entry:
+ %x = call i32 @a()
+ %y = call i32 @b()
+ ret i32 %y
+}
+
+!0 = !{i32 1234}
+!1 = !{i32 6789}
>From 1d681d4dd119d08ed7b65a11d4183d97ada1e165 Mon Sep 17 00:00:00 2001
From: Lane0218 <laneljc at qq.com>
Date: Fri, 21 Aug 2026 13:56:42 +0800
Subject: [PATCH 2/3] [MergeFunctions] Update KCFI test checks
---
.../MergeFunc/kcfi-function-merging.ll | 34 ++++++++++++-------
1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll b/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
index c3d3daadc5f51..90843e3bf6e84 100644
--- a/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
+++ b/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
@@ -1,31 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
; Functions with different KCFI type identifiers must not be merged.
define internal i32 @a() unnamed_addr !kcfi_type !0 {
-; CHECK-LABEL: define internal i32 @a()
-; CHECK-NEXT: entry:
-; CHECK-NEXT: ret i32 0
-; CHECK-NEXT: }
+; CHECK-LABEL: define internal i32 @a(
+; CHECK-SAME: ) unnamed_addr !kcfi_type [[META0:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: ret i32 0
+;
entry:
ret i32 0
}
define internal i32 @b() unnamed_addr !kcfi_type !1 {
-; CHECK-LABEL: define internal i32 @b()
-; CHECK-NEXT: entry:
-; CHECK-NEXT: ret i32 0
-; CHECK-NEXT: }
+; CHECK-LABEL: define internal i32 @b(
+; CHECK-SAME: ) unnamed_addr !kcfi_type [[META1:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: ret i32 0
+;
entry:
ret i32 0
}
define i32 @caller() {
-; CHECK-LABEL: define i32 @caller()
-; CHECK-NEXT: entry:
-; CHECK-NEXT: %x = call i32 @a()
-; CHECK-NEXT: %y = call i32 @b()
-; CHECK-NEXT: ret i32 %y
+; CHECK-LABEL: define i32 @caller() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[X:%.*]] = call i32 @a()
+; CHECK-NEXT: [[Y:%.*]] = call i32 @b()
+; CHECK-NEXT: ret i32 [[Y]]
+;
entry:
%x = call i32 @a()
%y = call i32 @b()
@@ -34,3 +38,7 @@ entry:
!0 = !{i32 1234}
!1 = !{i32 6789}
+;.
+; CHECK: [[META0]] = !{i32 1234}
+; CHECK: [[META1]] = !{i32 6789}
+;.
>From 81a6a2d455de90acf1c27851470d03347ff13319 Mon Sep 17 00:00:00 2001
From: Lane0218 <laneljc at qq.com>
Date: Fri, 21 Aug 2026 23:36:17 +0800
Subject: [PATCH 3/3] [MergeFunctions] Test KCFI metadata equivalence cases
---
.../MergeFunc/kcfi-function-merging.ll | 68 +++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll b/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
index 90843e3bf6e84..b7d68128656bb 100644
--- a/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
+++ b/llvm/test/Transforms/MergeFunc/kcfi-function-merging.ll
@@ -36,9 +36,77 @@ entry:
ret i32 %y
}
+; Functions with matching KCFI type identifiers should still be merged.
+
+define internal i32 @same_a() unnamed_addr !kcfi_type !2 {
+; CHECK-LABEL: define internal i32 @same_a(
+; CHECK-SAME: ) unnamed_addr !kcfi_type [[META2:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ ret i32 0
+}
+
+define internal i32 @same_b() unnamed_addr !kcfi_type !2 {
+entry:
+ ret i32 0
+}
+
+define i32 @same_caller() {
+; CHECK-LABEL: define i32 @same_caller() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[X:%.*]] = call i32 @same_a()
+; CHECK-NEXT: [[Y:%.*]] = call i32 @same_a()
+; CHECK-NEXT: ret i32 [[Y]]
+;
+entry:
+ %x = call i32 @same_a()
+ %y = call i32 @same_b()
+ ret i32 %y
+}
+
+; A missing KCFI type identifier must not match a present one.
+
+define internal i32 @with_a() unnamed_addr !kcfi_type !3 {
+; CHECK-LABEL: define internal i32 @with_a(
+; CHECK-SAME: ) unnamed_addr !kcfi_type [[META3:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ ret i32 0
+}
+
+define internal i32 @without_b() unnamed_addr {
+; CHECK-LABEL: define internal i32 @without_b() unnamed_addr {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ ret i32 0
+}
+
+define i32 @mixed_caller() {
+; CHECK-LABEL: define i32 @mixed_caller() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[X:%.*]] = call i32 @with_a()
+; CHECK-NEXT: [[Y:%.*]] = call i32 @without_b()
+; CHECK-NEXT: ret i32 [[Y]]
+;
+entry:
+ %x = call i32 @with_a()
+ %y = call i32 @without_b()
+ ret i32 %y
+}
+
!0 = !{i32 1234}
!1 = !{i32 6789}
+!2 = !{i32 2468}
+!3 = !{i32 9753}
;.
; CHECK: [[META0]] = !{i32 1234}
; CHECK: [[META1]] = !{i32 6789}
+; CHECK: [[META2]] = !{i32 2468}
+; CHECK: [[META3]] = !{i32 9753}
;.
More information about the llvm-commits
mailing list