https://github.com/ziyao233 updated https://github.com/llvm/llvm-project/pull/138391
>From 4a3bf6d7aca36baa93ed30f6f2f458c817380168 Mon Sep 17 00:00:00 2001 From: Yao Zi <zi...@disroot.org> Date: Sat, 3 May 2025 09:49:25 +0000 Subject: [PATCH] [Clang][LoongArch] Match GCC behaviour when parsing FPRs in asm clobbers There're four possible formats to refer a register in inline assembly, 1. Numeric name without dollar sign ("f0") 2. Numeric name with dollar sign ("$f0") 3. ABI name without dollar sign ("fa0") 4. ABI name with dollar sign ("$fa0") LoongArch GCC accepts 1 and 2 for FPRs before r15-8284[1] and all these formats after the chagne. But Clang supports only 2 and 4 for FPRs. The inconsistency has caused compatibility issues, such as QEMU's case[2]. This patch follows 0bbf3ddf5fea ("[Clang][LoongArch] Add GPR alias handling without `$` prefix") and accepts FPRs without dollar sign prefixes as well to keep aligned with GCC, avoiding future compatibility problems. Link: https://gcc.gnu.org/cgit/gcc/commit/?id=d0110185eb78f14a8e485f410bee237c9c71548d [1] Link: https://lore.kernel.org/qemu-devel/20250314033150.53268-3-zi...@disroot.org/ [2] --- clang/lib/Basic/Targets/LoongArch.cpp | 72 ++++++++++--------- .../LoongArch/inline-asm-gcc-regs-error.c | 9 --- .../CodeGen/LoongArch/inline-asm-gcc-regs.c | 30 ++++++++ 3 files changed, 70 insertions(+), 41 deletions(-) diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp index ca742797d7a3b..0dc92b8a74639 100644 --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -82,38 +82,46 @@ LoongArchTargetInfo::getGCCRegAliases() const { {{"s6", "$s6", "r29"}, "$r29"}, {{"s7", "$s7", "r30"}, "$r30"}, {{"s8", "$s8", "r31"}, "$r31"}, - {{"$fa0"}, "$f0"}, - {{"$fa1"}, "$f1"}, - {{"$fa2"}, "$f2"}, - {{"$fa3"}, "$f3"}, - {{"$fa4"}, "$f4"}, - {{"$fa5"}, "$f5"}, - {{"$fa6"}, "$f6"}, - {{"$fa7"}, "$f7"}, - {{"$ft0"}, "$f8"}, - {{"$ft1"}, "$f9"}, - {{"$ft2"}, "$f10"}, - {{"$ft3"}, "$f11"}, - {{"$ft4"}, "$f12"}, - {{"$ft5"}, "$f13"}, - {{"$ft6"}, "$f14"}, - {{"$ft7"}, "$f15"}, - {{"$ft8"}, "$f16"}, - {{"$ft9"}, "$f17"}, - {{"$ft10"}, "$f18"}, - {{"$ft11"}, "$f19"}, - {{"$ft12"}, "$f20"}, - {{"$ft13"}, "$f21"}, - {{"$ft14"}, "$f22"}, - {{"$ft15"}, "$f23"}, - {{"$fs0"}, "$f24"}, - {{"$fs1"}, "$f25"}, - {{"$fs2"}, "$f26"}, - {{"$fs3"}, "$f27"}, - {{"$fs4"}, "$f28"}, - {{"$fs5"}, "$f29"}, - {{"$fs6"}, "$f30"}, - {{"$fs7"}, "$f31"}, + {{"fa0", "$fa0", "f0"}, "$f0"}, + {{"fa1", "$fa1", "f1"}, "$f1"}, + {{"fa2", "$fa2", "f2"}, "$f2"}, + {{"fa3", "$fa3", "f3"}, "$f3"}, + {{"fa4", "$fa4", "f4"}, "$f4"}, + {{"fa5", "$fa5", "f5"}, "$f5"}, + {{"fa6", "$fa6", "f6"}, "$f6"}, + {{"fa7", "$fa7", "f7"}, "$f7"}, + {{"ft0", "$ft0", "f8"}, "$f8"}, + {{"ft1", "$ft1", "f9"}, "$f9"}, + {{"ft2", "$ft2", "f10"}, "$f10"}, + {{"ft3", "$ft3", "f11"}, "$f11"}, + {{"ft4", "$ft4", "f12"}, "$f12"}, + {{"ft5", "$ft5", "f13"}, "$f13"}, + {{"ft6", "$ft6", "f14"}, "$f14"}, + {{"ft7", "$ft7", "f15"}, "$f15"}, + {{"ft8", "$ft8", "f16"}, "$f16"}, + {{"ft9", "$ft9", "f17"}, "$f17"}, + {{"ft10", "$ft10", "f18"}, "$f18"}, + {{"ft11", "$ft11", "f19"}, "$f19"}, + {{"ft12", "$ft12", "f20"}, "$f20"}, + {{"ft13", "$ft13", "f21"}, "$f21"}, + {{"ft14", "$ft14", "f22"}, "$f22"}, + {{"ft15", "$ft15", "f23"}, "$f23"}, + {{"fs0", "$fs0", "f24"}, "$f24"}, + {{"fs1", "$fs1", "f25"}, "$f25"}, + {{"fs2", "$fs2", "f26"}, "$f26"}, + {{"fs3", "$fs3", "f27"}, "$f27"}, + {{"fs4", "$fs4", "f28"}, "$f28"}, + {{"fs5", "$fs5", "f29"}, "$f29"}, + {{"fs6", "$fs6", "f30"}, "$f30"}, + {{"fs7", "$fs7", "f31"}, "$f31"}, + {{"fcc0"}, "$fcc0"}, + {{"fcc1"}, "$fcc1"}, + {{"fcc2"}, "$fcc2"}, + {{"fcc3"}, "$fcc3"}, + {{"fcc4"}, "$fcc4"}, + {{"fcc5"}, "$fcc5"}, + {{"fcc6"}, "$fcc6"}, + {{"fcc7"}, "$fcc7"}, }; return llvm::ArrayRef(GCCRegAliases); } diff --git a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs-error.c b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs-error.c index c5ecf0c929af8..cab6182ac61c3 100644 --- a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs-error.c +++ b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs-error.c @@ -8,13 +8,4 @@ void test(void) { register float a1 asm ("$f32"); // CHECK: :[[#@LINE+1]]:24: error: unknown register name '$foo' in asm register int a2 asm ("$foo"); - -/// Names not prefixed with '$' are invalid. - -// CHECK: :[[#@LINE+1]]:26: error: unknown register name 'f0' in asm - register float a5 asm ("f0"); -// CHECK: :[[#@LINE+1]]:26: error: unknown register name 'fa0' in asm - register float a6 asm ("fa0"); -// CHECK: :[[#@LINE+1]]:15: error: unknown register name 'fcc0' in asm - asm ("" ::: "fcc0"); } diff --git a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c index e1015f6fc01d5..99be034824987 100644 --- a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c +++ b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c @@ -5,6 +5,7 @@ // CHECK-LABEL: @test_r0 // CHECK: call void asm sideeffect "", "{$r0}"(i32 undef) +// CHECK: call void asm sideeffect "", "{$r0}"(i32 undef) void test_r0() { register int a asm ("$r0"); register int b asm ("r0"); @@ -14,6 +15,7 @@ void test_r0() { // CHECK-LABEL: @test_r12 // CHECK: call void asm sideeffect "", "{$r12}"(i32 undef) +// CHECK: call void asm sideeffect "", "{$r12}"(i32 undef) void test_r12() { register int a asm ("$r12"); register int b asm ("r12"); @@ -23,6 +25,7 @@ void test_r12() { // CHECK-LABEL: @test_r31 // CHECK: call void asm sideeffect "", "{$r31}"(i32 undef) +// CHECK: call void asm sideeffect "", "{$r31}"(i32 undef) void test_r31() { register int a asm ("$r31"); register int b asm ("r31"); @@ -32,6 +35,7 @@ void test_r31() { // CHECK-LABEL: @test_zero // CHECK: call void asm sideeffect "", "{$r0}"(i32 undef) +// CHECK: call void asm sideeffect "", "{$r0}"(i32 undef) void test_zero() { register int a asm ("$zero"); register int b asm ("zero"); @@ -41,6 +45,7 @@ void test_zero() { // CHECK-LABEL: @test_a0 // CHECK: call void asm sideeffect "", "{$r4}"(i32 undef) +// CHECK: call void asm sideeffect "", "{$r4}"(i32 undef) void test_a0() { register int a asm ("$a0"); register int b asm ("a0"); @@ -50,6 +55,7 @@ void test_a0() { // CHECK-LABEL: @test_t1 // CHECK: call void asm sideeffect "", "{$r13}"(i32 undef) +// CHECK: call void asm sideeffect "", "{$r13}"(i32 undef) void test_t1() { register int a asm ("$t1"); register int b asm ("t1"); @@ -59,6 +65,7 @@ void test_t1() { // CHECK-LABEL: @test_fp // CHECK: call void asm sideeffect "", "{$r22}"(i32 undef) +// CHECK: call void asm sideeffect "", "{$r22}"(i32 undef) void test_fp() { register int a asm ("$fp"); register int b asm ("fp"); @@ -68,6 +75,7 @@ void test_fp() { // CHECK-LABEL: @test_s2 // CHECK: call void asm sideeffect "", "{$r25}"(i32 undef) +// CHECK: call void asm sideeffect "", "{$r25}"(i32 undef) void test_s2() { register int a asm ("$s2"); register int b asm ("s2"); @@ -77,50 +85,72 @@ void test_s2() { // CHECK-LABEL: @test_f0 // CHECK: call void asm sideeffect "", "{$f0}"(float undef) +// CHECK: call void asm sideeffect "", "{$f0}"(float undef) void test_f0() { register float a asm ("$f0"); + register float b asm ("f0"); asm ("" :: "f" (a)); + asm ("" :: "f" (b)); } // CHECK-LABEL: @test_f14 // CHECK: call void asm sideeffect "", "{$f14}"(float undef) +// CHECK: call void asm sideeffect "", "{$f14}"(float undef) void test_f14() { register float a asm ("$f14"); + register float b asm ("f14"); asm ("" :: "f" (a)); + asm ("" :: "f" (b)); } // CHECK-LABEL: @test_f31 // CHECK: call void asm sideeffect "", "{$f31}"(float undef) +// CHECK: call void asm sideeffect "", "{$f31}"(float undef) void test_f31() { register float a asm ("$f31"); + register float b asm ("f31"); asm ("" :: "f" (a)); + asm ("" :: "f" (b)); } // CHECK-LABEL: @test_fa0 // CHECK: call void asm sideeffect "", "{$f0}"(float undef) +// CHECK: call void asm sideeffect "", "{$f0}"(float undef) void test_fa0() { register float a asm ("$fa0"); + register float b asm ("fa0"); asm ("" :: "f" (a)); + asm ("" :: "f" (b)); } // CHECK-LABEL: @test_ft1 // CHECK: call void asm sideeffect "", "{$f9}"(float undef) +// CHECK: call void asm sideeffect "", "{$f9}"(float undef) void test_ft1() { register float a asm ("$ft1"); + register float b asm ("ft1"); asm ("" :: "f" (a)); + asm ("" :: "f" (b)); } // CHECK-LABEL: @test_fs2 // CHECK: call void asm sideeffect "", "{$f26}"(float undef) +// CHECK: call void asm sideeffect "", "{$f26}"(float undef) void test_fs2() { register float a asm ("$fs2"); + register float b asm ("fs2"); asm ("" :: "f" (a)); + asm ("" :: "f" (b)); } // CHECK-LABEL: @test_fcc // CHECK: call void asm sideeffect "", "~{$fcc0}"() +// CHECK: call void asm sideeffect "", "~{$fcc0}"() +// CHECK: call void asm sideeffect "", "~{$fcc7}"() // CHECK: call void asm sideeffect "", "~{$fcc7}"() void test_fcc() { asm ("" ::: "$fcc0"); + asm ("" ::: "fcc0"); asm ("" ::: "$fcc7"); + asm ("" ::: "fcc7"); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits