[clang] [llvm] [clang] Add more test coverage for "zero-call-used-regs" (PR #201834)
Lucas Chollet via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 8 23:59:41 PDT 2026
https://github.com/LucasChollet updated https://github.com/llvm/llvm-project/pull/201834
>From df9d6b85153b564e8c63e824a5f2a52d93554a1d Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Fri, 5 Jun 2026 14:52:44 +0200
Subject: [PATCH 1/2] [clang] Add more test coverage for "zero-call-used-regs"
In clang, the main function is treated as a special case and no
"zero-call-used-regs" attributes are emitted for it. This patch adds
proper unit testing for that functionality.
AFAIU, treating `main` as a special case was initially implemented in
the backend. However, during review [1] the logic was moved to clang
while the associated test case was never updated (and then copied over
to the AArch64 test file).
[1] https://reviews.llvm.org/D110869
More specifically this comment: https://reviews.llvm.org/D110869#3285932
---
clang/test/CodeGen/zero-call-used-regs.c | 28 +++++++++++++++++++
.../CodeGen/AArch64/zero-call-used-regs.ll | 11 --------
llvm/test/CodeGen/X86/zero-call-used-regs.ll | 16 -----------
3 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/clang/test/CodeGen/zero-call-used-regs.c b/clang/test/CodeGen/zero-call-used-regs.c
index 4437751ba7b31..86dd1bfa6ac63 100644
--- a/clang/test/CodeGen/zero-call-used-regs.c
+++ b/clang/test/CodeGen/zero-call-used-regs.c
@@ -20,6 +20,7 @@
// CHECK-SKIP: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR:[0-9]*]]
// CHECK-SKIP: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG:[0-9]*]]
// CHECK-SKIP: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL:[0-9]*]]
+// CHECK-SKIP: define {{.*}} @main({{.*}} #[[ATTR_NUM]]
//
// CHECK-SKIP-NOT: attributes #[[ATTR_NUM]] = {{.*}} "zero-call-used-regs"=
// CHECK-SKIP: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -44,6 +45,7 @@
// CHECK-USED-GPR-ARG: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR:[0-9]*]]
// CHECK-USED-GPR-ARG: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG:[0-9]*]]
// CHECK-USED-GPR-ARG: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL:[0-9]*]]
+// CHECK-USED-GPR-ARG: define {{.*}} @main({{.*}} #[[ATTR_NUM_MAIN:[0-9]*]]
//
// CHECK-USED-GPR-ARG: attributes #[[ATTR_NUM_USED_GPR_ARG]] = {{.*}} "zero-call-used-regs"="used-gpr-arg"
// CHECK-USED-GPR-ARG: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -54,6 +56,8 @@
// CHECK-USED-GPR-ARG: attributes #[[ATTR_NUM_ALL_GPR]] = {{.*}} "zero-call-used-regs"="all-gpr"
// CHECK-USED-GPR-ARG: attributes #[[ATTR_NUM_ALL_ARG]] = {{.*}} "zero-call-used-regs"="all-arg"
// CHECK-USED-GPR-ARG: attributes #[[ATTR_NUM_ALL]] = {{.*}} "zero-call-used-regs"="all"
+// CHECK-USED-GPR-ARG: attributes #[[ATTR_NUM_MAIN]] =
+// CHECK-USED-GPR-ARG-NOT: "zero-call-used-regs"=
// -fzero-call-used-regs=used-gpr:
//
@@ -67,6 +71,7 @@
// CHECK-USED-GPR: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR:[0-9]*]]
// CHECK-USED-GPR: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG:[0-9]*]]
// CHECK-USED-GPR: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL:[0-9]*]]
+// CHECK-USED-GPR: define {{.*}} @main({{.*}} #[[ATTR_NUM_MAIN:[0-9]*]]
//
// CHECK-USED-GPR: attributes #[[ATTR_NUM_USED_GPR]] = {{.*}} "zero-call-used-regs"="used-gpr"
// CHECK-USED-GPR: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -77,6 +82,8 @@
// CHECK-USED-GPR: attributes #[[ATTR_NUM_ALL_GPR]] = {{.*}} "zero-call-used-regs"="all-gpr"
// CHECK-USED-GPR: attributes #[[ATTR_NUM_ALL_ARG]] = {{.*}} "zero-call-used-regs"="all-arg"
// CHECK-USED-GPR: attributes #[[ATTR_NUM_ALL]] = {{.*}} "zero-call-used-regs"="all"
+// CHECK-USED-GPR: attributes #[[ATTR_NUM_MAIN]] =
+// CHECK-USED-GPR-NOT: "zero-call-used-regs"=
// -fzero-call-used-regs=used-arg:
//
@@ -90,6 +97,7 @@
// CHECK-USED-ARG: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR:[0-9]*]]
// CHECK-USED-ARG: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG:[0-9]*]]
// CHECK-USED-ARG: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL:[0-9]*]]
+// CHECK-USED-ARG: define {{.*}} @main({{.*}} #[[ATTR_NUM_MAIN:[0-9]*]]
//
// CHECK-USED-ARG: attributes #[[ATTR_NUM_USED_ARG]] = {{.*}} "zero-call-used-regs"="used-arg"
// CHECK-USED-ARG: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -100,6 +108,8 @@
// CHECK-USED-ARG: attributes #[[ATTR_NUM_ALL_GPR]] = {{.*}} "zero-call-used-regs"="all-gpr"
// CHECK-USED-ARG: attributes #[[ATTR_NUM_ALL_ARG]] = {{.*}} "zero-call-used-regs"="all-arg"
// CHECK-USED-ARG: attributes #[[ATTR_NUM_ALL]] = {{.*}} "zero-call-used-regs"="all"
+// CHECK-USED-ARG: attributes #[[ATTR_NUM_MAIN]] =
+// CHECK-USED-ARG-NOT: "zero-call-used-regs"=
// -fzero-call-used-regs=used:
//
@@ -113,6 +123,7 @@
// CHECK-USED: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR:[0-9]*]]
// CHECK-USED: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG:[0-9]*]]
// CHECK-USED: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL:[0-9]*]]
+// CHECK-USED: define {{.*}} @main({{.*}} #[[ATTR_NUM_MAIN:[0-9]*]]
//
// CHECK-USED: attributes #[[ATTR_NUM_USED]] = {{.*}} "zero-call-used-regs"="used"
// CHECK-USED: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -123,6 +134,8 @@
// CHECK-USED: attributes #[[ATTR_NUM_ALL_GPR]] = {{.*}} "zero-call-used-regs"="all-gpr"
// CHECK-USED: attributes #[[ATTR_NUM_ALL_ARG]] = {{.*}} "zero-call-used-regs"="all-arg"
// CHECK-USED: attributes #[[ATTR_NUM_ALL]] = {{.*}} "zero-call-used-regs"="all"
+// CHECK-USED: attributes #[[ATTR_NUM_MAIN]] =
+// CHECK-USED-NOT: "zero-call-used-regs"=
// -fzero-call-used-regs=all-gpr-arg:
//
@@ -136,6 +149,7 @@
// CHECK-ALL-GPR-ARG: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR:[0-9]*]]
// CHECK-ALL-GPR-ARG: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG:[0-9]*]]
// CHECK-ALL-GPR-ARG: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL:[0-9]*]]
+// CHECK-ALL-GPR-ARG: define {{.*}} @main({{.*}} #[[ATTR_NUM_MAIN:[0-9]*]]
//
// CHECK-ALL-GPR-ARG: attributes #[[ATTR_NUM_ALL_GPR_ARG]] = {{.*}} "zero-call-used-regs"="all-gpr-arg"
// CHECK-ALL-GPR-ARG: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -146,6 +160,8 @@
// CHECK-ALL-GPR-ARG: attributes #[[ATTR_NUM_ALL_GPR]] = {{.*}} "zero-call-used-regs"="all-gpr"
// CHECK-ALL-GPR-ARG: attributes #[[ATTR_NUM_ALL_ARG]] = {{.*}} "zero-call-used-regs"="all-arg"
// CHECK-ALL-GPR-ARG: attributes #[[ATTR_NUM_ALL]] = {{.*}} "zero-call-used-regs"="all"
+// CHECK-ALL-GPR-ARG: attributes #[[ATTR_NUM_MAIN]] =
+// CHECK-ALL-GPR-ARG-NOT: "zero-call-used-regs"=
// -fzero-call-used-regs=all-gpr:
//
@@ -159,6 +175,7 @@
// CHECK-ALL-GPR: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR]]
// CHECK-ALL-GPR: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG:[0-9]*]]
// CHECK-ALL-GPR: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL:[0-9]*]]
+// CHECK-ALL-GPR: define {{.*}} @main({{.*}} #[[ATTR_NUM_MAIN:[0-9]*]]
//
// CHECK-ALL-GPR: attributes #[[ATTR_NUM_ALL_GPR]] = {{.*}} "zero-call-used-regs"="all-gpr"
// CHECK-ALL-GPR: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -169,6 +186,8 @@
// CHECK-ALL-GPR: attributes #[[ATTR_NUM_ALL_GPR_ARG]] = {{.*}} "zero-call-used-regs"="all-gpr-arg"
// CHECK-ALL-GPR: attributes #[[ATTR_NUM_ALL_ARG]] = {{.*}} "zero-call-used-regs"="all-arg"
// CHECK-ALL-GPR: attributes #[[ATTR_NUM_ALL]] = {{.*}} "zero-call-used-regs"="all"
+// CHECK-ALL-GPR: attributes #[[ATTR_NUM_MAIN]] =
+// CHECK-ALL-GPR-NOT: "zero-call-used-regs"=
// -fzero-call-used-regs=all-arg:
//
@@ -182,6 +201,7 @@
// CHECK-ALL-ARG: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR:[0-9]*]]
// CHECK-ALL-ARG: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG]]
// CHECK-ALL-ARG: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL:[0-9]*]]
+// CHECK-ALL-ARG: define {{.*}} @main({{.*}} #[[ATTR_NUM_MAIN:[0-9]*]]
//
// CHECK-ALL-ARG: attributes #[[ATTR_NUM_ALL_ARG]] = {{.*}} "zero-call-used-regs"="all-arg"
// CHECK-ALL-ARG: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -192,6 +212,8 @@
// CHECK-ALL-ARG: attributes #[[ATTR_NUM_ALL_GPR_ARG]] = {{.*}} "zero-call-used-regs"="all-gpr-arg"
// CHECK-ALL-ARG: attributes #[[ATTR_NUM_ALL_GPR]] = {{.*}} "zero-call-used-regs"="all-gpr"
// CHECK-ALL-ARG: attributes #[[ATTR_NUM_ALL]] = {{.*}} "zero-call-used-regs"="all"
+// CHECK-ALL-ARG: attributes #[[ATTR_NUM_MAIN]] =
+// CHECK-ALL-ARG-NOT: "zero-call-used-regs"=
// -fzero-call-used-regs=all:
//
@@ -205,6 +227,7 @@
// CHECK-ALL: define {{.*}} @all_gpr_test({{.*}} #[[ATTR_NUM_ALL_GPR:[0-9]*]]
// CHECK-ALL: define {{.*}} @all_arg_test({{.*}} #[[ATTR_NUM_ALL_ARG:[0-9]*]]
// CHECK-ALL: define {{.*}} @all_test({{.*}} #[[ATTR_NUM_ALL]]
+// CHECK-ALL: define {{.*}} @main({{.*}} #[[ATTR_NUM_MAIN:[0-9]*]]
//
// CHECK-ALL: attributes #[[ATTR_NUM_ALL]] = {{.*}} "zero-call-used-regs"="all"
// CHECK-ALL: attributes #[[ATTR_NUM_SKIP]] = {{.*}} "zero-call-used-regs"="skip"
@@ -215,6 +238,8 @@
// CHECK-ALL: attributes #[[ATTR_NUM_ALL_GPR_ARG]] = {{.*}} "zero-call-used-regs"="all-gpr-arg"
// CHECK-ALL: attributes #[[ATTR_NUM_ALL_GPR]] = {{.*}} "zero-call-used-regs"="all-gpr"
// CHECK-ALL: attributes #[[ATTR_NUM_ALL_ARG]] = {{.*}} "zero-call-used-regs"="all-arg"
+// CHECK-ALL: attributes #[[ATTR_NUM_MAIN]] =
+// CHECK-ALL-NOT: "zero-call-used-regs"=
#define __zero_call_used_regs(kind) __attribute__((zero_call_used_regs(kind)))
@@ -247,3 +272,6 @@ void __zero_call_used_regs("all-arg") all_arg_test(void) {
void __zero_call_used_regs("all") all_test(void) {
}
+
+int main() {
+}
diff --git a/llvm/test/CodeGen/AArch64/zero-call-used-regs.ll b/llvm/test/CodeGen/AArch64/zero-call-used-regs.ll
index 986666e015e9e..1a13270bf7856 100644
--- a/llvm/test/CodeGen/AArch64/zero-call-used-regs.ll
+++ b/llvm/test/CodeGen/AArch64/zero-call-used-regs.ll
@@ -780,15 +780,4 @@ entry:
ret double %mul
}
-; Don't emit zeroing registers in "main" function.
-define dso_local i32 @main() local_unnamed_addr #0 {
-; CHECK-LABEL: main:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: mov w0, wzr
-; CHECK-NEXT: ret
-
-entry:
- ret i32 0
-}
-
attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon,+v8a" }
diff --git a/llvm/test/CodeGen/X86/zero-call-used-regs.ll b/llvm/test/CodeGen/X86/zero-call-used-regs.ll
index 97ad5ce9c8cbb..84d71e2d57453 100644
--- a/llvm/test/CodeGen/X86/zero-call-used-regs.ll
+++ b/llvm/test/CodeGen/X86/zero-call-used-regs.ll
@@ -255,21 +255,5 @@ define dso_local void @tailcall(ptr %p) local_unnamed_addr #0 "zero-call-used-re
ret void
}
-; Don't emit zeroing registers in "main" function.
-define dso_local i32 @main() local_unnamed_addr #1 {
-; I386-LABEL: main:
-; I386: # %bb.0: # %entry
-; I386-NEXT: xorl %eax, %eax
-; I386-NEXT: retl
-;
-; X86-64-LABEL: main:
-; X86-64: # %bb.0: # %entry
-; X86-64-NEXT: xorl %eax, %eax
-; X86-64-NEXT: retq
-
-entry:
- ret i32 0
-}
-
attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { nofree norecurse nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
>From 6a6d888174fb1e8273fc644a0c6900a90e303f12 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 9 Jun 2026 08:58:31 +0200
Subject: [PATCH 2/2] Remove unused attributes #1
---
llvm/test/CodeGen/X86/zero-call-used-regs.ll | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/test/CodeGen/X86/zero-call-used-regs.ll b/llvm/test/CodeGen/X86/zero-call-used-regs.ll
index 84d71e2d57453..bc59796389e8e 100644
--- a/llvm/test/CodeGen/X86/zero-call-used-regs.ll
+++ b/llvm/test/CodeGen/X86/zero-call-used-regs.ll
@@ -256,4 +256,3 @@ define dso_local void @tailcall(ptr %p) local_unnamed_addr #0 "zero-call-used-re
}
attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
-attributes #1 = { nofree norecurse nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
More information about the cfe-commits
mailing list