[clang] [Clang][LoongArch] Match GCC behaviour when parsing FPRs in asm clobbers (PR #138391)
Yao Zi via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 27 22:41:45 PDT 2025
https://github.com/ziyao233 updated https://github.com/llvm/llvm-project/pull/138391
>From 1f14ee7b8e368ddf6e248eae8c54596c4b7bf051 Mon Sep 17 00:00:00 2001
From: Yao Zi <ziyao at 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-ziyao@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 | 62 +++++++++++-----
3 files changed, 86 insertions(+), 57 deletions(-)
diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp
index 5312767498d96..f6915df1520b7 100644
--- a/clang/lib/Basic/Targets/LoongArch.cpp
+++ b/clang/lib/Basic/Targets/LoongArch.cpp
@@ -81,38 +81,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..80623c7fc3560 100644
--- a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c
+++ b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c
@@ -4,7 +4,8 @@
/// Check GCC register names and alias can be used in register variable definition.
// CHECK-LABEL: @test_r0
-// CHECK: call void asm sideeffect "", "{$r0}"(i32 undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$r0}"(i32 undef)
+// CHECK-NOT: call void asm sideeffect "", "{$r0}"(i32 undef)
void test_r0() {
register int a asm ("$r0");
register int b asm ("r0");
@@ -13,7 +14,8 @@ void test_r0() {
}
// CHECK-LABEL: @test_r12
-// CHECK: call void asm sideeffect "", "{$r12}"(i32 undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$r12}"(i32 undef)
+// CHECK-NOT: call void asm sideeffect "", "{$r12}"(i32 undef)
void test_r12() {
register int a asm ("$r12");
register int b asm ("r12");
@@ -22,7 +24,8 @@ void test_r12() {
}
// CHECK-LABEL: @test_r31
-// CHECK: call void asm sideeffect "", "{$r31}"(i32 undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$r31}"(i32 undef)
+// CHECK-NOT: call void asm sideeffect "", "{$r31}"(i32 undef)
void test_r31() {
register int a asm ("$r31");
register int b asm ("r31");
@@ -31,7 +34,8 @@ void test_r31() {
}
// CHECK-LABEL: @test_zero
-// CHECK: call void asm sideeffect "", "{$r0}"(i32 undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$r0}"(i32 undef)
+// CHECK-NOT: call void asm sideeffect "", "{$r0}"(i32 undef)
void test_zero() {
register int a asm ("$zero");
register int b asm ("zero");
@@ -40,7 +44,8 @@ void test_zero() {
}
// CHECK-LABEL: @test_a0
-// CHECK: call void asm sideeffect "", "{$r4}"(i32 undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$r4}"(i32 undef)
+// CHECK-NOT: call void asm sideeffect "", "{$r4}"(i32 undef)
void test_a0() {
register int a asm ("$a0");
register int b asm ("a0");
@@ -49,7 +54,8 @@ void test_a0() {
}
// CHECK-LABEL: @test_t1
-// CHECK: call void asm sideeffect "", "{$r13}"(i32 undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$r13}"(i32 undef)
+// CHECK-NOT: call void asm sideeffect "", "{$r13}"(i32 undef)
void test_t1() {
register int a asm ("$t1");
register int b asm ("t1");
@@ -58,7 +64,8 @@ void test_t1() {
}
// CHECK-LABEL: @test_fp
-// CHECK: call void asm sideeffect "", "{$r22}"(i32 undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$r22}"(i32 undef)
+// CHECK-NOT: call void asm sideeffect "", "{$r22}"(i32 undef)
void test_fp() {
register int a asm ("$fp");
register int b asm ("fp");
@@ -67,7 +74,8 @@ void test_fp() {
}
// CHECK-LABEL: @test_s2
-// CHECK: call void asm sideeffect "", "{$r25}"(i32 undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$r25}"(i32 undef)
+// CHECK-NOT: call void asm sideeffect "", "{$r25}"(i32 undef)
void test_s2() {
register int a asm ("$s2");
register int b asm ("s2");
@@ -76,51 +84,73 @@ void test_s2() {
}
// CHECK-LABEL: @test_f0
-// CHECK: call void asm sideeffect "", "{$f0}"(float undef)
+// CHECK-COUNT-2: call void asm sideeffect "", "{$f0}"(float undef)
+// CHECK-NOT: 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-COUNT-2: call void asm sideeffect "", "{$f14}"(float undef)
+// CHECK-NOT: 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-COUNT-2: call void asm sideeffect "", "{$f31}"(float undef)
+// CHECK-NOT: 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-COUNT-2: call void asm sideeffect "", "{$f0}"(float undef)
+// CHECK-NOT: 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-COUNT-2: call void asm sideeffect "", "{$f9}"(float undef)
+// CHECK-NOT: 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-COUNT-2: call void asm sideeffect "", "{$f26}"(float undef)
+// CHECK-NOT: 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 "", "~{$fcc7}"()
+// CHECK-COUNT-2: call void asm sideeffect "", "~{$fcc0}"()
+// CHECK-NOT: call void asm sideeffect "", "~{$fcc0}"()
+// CHECK-COUNT-2: call void asm sideeffect "", "~{$fcc7}"()
+// CHECK-NOT: call void asm sideeffect "", "~{$fcc7}"()
void test_fcc() {
asm ("" ::: "$fcc0");
+ asm ("" ::: "fcc0");
asm ("" ::: "$fcc7");
+ asm ("" ::: "fcc7");
}
More information about the cfe-commits
mailing list