-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Clang][LoongArch] Add inline asm support for the q
constraint
#141037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang Author: hev (heiher) ChangesThis patch adds support for the Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-May/684339.html Full diff: https://github.com/llvm/llvm-project/pull/141037.diff 4 Files Affected:
diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp
index ca742797d7a3b..f4bcb54bd470d 100644
--- a/clang/lib/Basic/Targets/LoongArch.cpp
+++ b/clang/lib/Basic/Targets/LoongArch.cpp
@@ -139,6 +139,11 @@ bool LoongArchTargetInfo::validateAsmConstraint(
// A signed 16-bit constant.
Info.setRequiresImmediate(-32768, 32767);
return true;
+ case 'q':
+ // A general-purpose register except for $r0 and $r1 (for the csrxchg
+ // instruction)
+ Info.setAllowsRegister();
+ return true;
case 'I':
// A signed 12-bit constant (for arithmetic instructions).
Info.setRequiresImmediate(-2048, 2047);
diff --git a/clang/test/CodeGen/LoongArch/inline-asm-constraints.c b/clang/test/CodeGen/LoongArch/inline-asm-constraints.c
index b19494284bd99..ded21206d63bf 100644
--- a/clang/test/CodeGen/LoongArch/inline-asm-constraints.c
+++ b/clang/test/CodeGen/LoongArch/inline-asm-constraints.c
@@ -35,6 +35,12 @@ void test_m(int *p) {
asm volatile("" :: "m"(*(p+4)));
}
+void test_q(void) {
+// CHECK-LABEL: define{{.*}} void @test_q()
+// CHECK: call void asm sideeffect "", "q"(i32 0)
+ asm volatile ("" :: "q"(0));
+}
+
void test_I(void) {
// CHECK-LABEL: define{{.*}} void @test_I()
// CHECK: call void asm sideeffect "", "I"(i32 2047)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 9774683e16291..50ec0b2e3ca78 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -7276,6 +7276,8 @@ LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {
// 'm': A memory operand whose address is formed by a base register and
// offset that is suitable for use in instructions with the same
// addressing mode as st.w and ld.w.
+ // 'q': A general-purpose register except for $r0 and $r1 (for the csrxchg
+ // instruction)
// 'I': A signed 12-bit constant (for arithmetic instructions).
// 'J': Integer zero.
// 'K': An unsigned 12-bit constant (for logic instructions).
@@ -7289,6 +7291,7 @@ LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {
default:
break;
case 'f':
+ case 'q':
return C_RegisterClass;
case 'l':
case 'I':
@@ -7328,6 +7331,8 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint(
if (VT.isVector())
break;
return std::make_pair(0U, &LoongArch::GPRRegClass);
+ case 'q':
+ return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
case 'f':
if (Subtarget.hasBasicF() && VT == MVT::f32)
return std::make_pair(0U, &LoongArch::FPR32RegClass);
diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll
index 4bcc88be97396..426082b2906d5 100644
--- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll
+++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll
@@ -17,6 +17,17 @@ define i32 @constraint_r(i32 %a, i32 %b) nounwind {
ret i32 %1
}
+define i32 @constraint_q(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: constraint_q:
+; CHECK: # %bb.0:
+; CHECK-NEXT: #APP
+; CHECK-NEXT: csrxchg $a0, $a0, $a1
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ret
+ %1 = tail call i32 asm "csrxchg $0, $1, $2", "=r,r,q,i"(i32 %a, i32 %b, i32 0)
+ ret i32 %1
+}
+
define i32 @constraint_i(i32 %a) nounwind {
; CHECK-LABEL: constraint_i:
; CHECK: # %bb.0:
|
@llvm/pr-subscribers-backend-loongarch Author: hev (heiher) ChangesThis patch adds support for the Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-May/684339.html Full diff: https://github.com/llvm/llvm-project/pull/141037.diff 4 Files Affected:
diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp
index ca742797d7a3b..f4bcb54bd470d 100644
--- a/clang/lib/Basic/Targets/LoongArch.cpp
+++ b/clang/lib/Basic/Targets/LoongArch.cpp
@@ -139,6 +139,11 @@ bool LoongArchTargetInfo::validateAsmConstraint(
// A signed 16-bit constant.
Info.setRequiresImmediate(-32768, 32767);
return true;
+ case 'q':
+ // A general-purpose register except for $r0 and $r1 (for the csrxchg
+ // instruction)
+ Info.setAllowsRegister();
+ return true;
case 'I':
// A signed 12-bit constant (for arithmetic instructions).
Info.setRequiresImmediate(-2048, 2047);
diff --git a/clang/test/CodeGen/LoongArch/inline-asm-constraints.c b/clang/test/CodeGen/LoongArch/inline-asm-constraints.c
index b19494284bd99..ded21206d63bf 100644
--- a/clang/test/CodeGen/LoongArch/inline-asm-constraints.c
+++ b/clang/test/CodeGen/LoongArch/inline-asm-constraints.c
@@ -35,6 +35,12 @@ void test_m(int *p) {
asm volatile("" :: "m"(*(p+4)));
}
+void test_q(void) {
+// CHECK-LABEL: define{{.*}} void @test_q()
+// CHECK: call void asm sideeffect "", "q"(i32 0)
+ asm volatile ("" :: "q"(0));
+}
+
void test_I(void) {
// CHECK-LABEL: define{{.*}} void @test_I()
// CHECK: call void asm sideeffect "", "I"(i32 2047)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 9774683e16291..50ec0b2e3ca78 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -7276,6 +7276,8 @@ LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {
// 'm': A memory operand whose address is formed by a base register and
// offset that is suitable for use in instructions with the same
// addressing mode as st.w and ld.w.
+ // 'q': A general-purpose register except for $r0 and $r1 (for the csrxchg
+ // instruction)
// 'I': A signed 12-bit constant (for arithmetic instructions).
// 'J': Integer zero.
// 'K': An unsigned 12-bit constant (for logic instructions).
@@ -7289,6 +7291,7 @@ LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {
default:
break;
case 'f':
+ case 'q':
return C_RegisterClass;
case 'l':
case 'I':
@@ -7328,6 +7331,8 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint(
if (VT.isVector())
break;
return std::make_pair(0U, &LoongArch::GPRRegClass);
+ case 'q':
+ return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
case 'f':
if (Subtarget.hasBasicF() && VT == MVT::f32)
return std::make_pair(0U, &LoongArch::FPR32RegClass);
diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll
index 4bcc88be97396..426082b2906d5 100644
--- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll
+++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll
@@ -17,6 +17,17 @@ define i32 @constraint_r(i32 %a, i32 %b) nounwind {
ret i32 %1
}
+define i32 @constraint_q(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: constraint_q:
+; CHECK: # %bb.0:
+; CHECK-NEXT: #APP
+; CHECK-NEXT: csrxchg $a0, $a0, $a1
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ret
+ %1 = tail call i32 asm "csrxchg $0, $1, $2", "=r,r,q,i"(i32 %a, i32 %b, i32 0)
+ ret i32 %1
+}
+
define i32 @constraint_i(i32 %a) nounwind {
; CHECK-LABEL: constraint_i:
; CHECK: # %bb.0:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about making a test case that exerts great pressure on the register allocator to verify that $ra
does not get accidentally handed out? Or if that's too fragile, if it's possible, make a variable pinned to $ra
or $zero
then pass it to the inline asm block with the newly added q
constraint, to ensure a new temp gets allocated.
This patch adds support for the `q` constraint: a general-purpose register except for $r0 and $r1 (for the csrxchg instruction) Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-May/684339.html
I've done that, similar to what was done in #140862
It doesn't seem to work. A |
I have a C test case: unsigned long
test (unsigned long x, unsigned long y)
{
register unsigned long ra asm ("ra");
asm("" : "+r"(ra));
unsigned long t = ra;
asm ("csrxchg %0, %1, 0" : "+r" (x) : "r" (t));
return x;
} clang-20.1.4 errors out:
And I suppose it should work after this PR and changing the second |
Good idea! |
✅ With the latest revision this PR passed the undef deprecator. |
Took xry's idea [^1] to improve the csrxchg instrinsic test case. [^1]: llvm#141037 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
This patch adds support for the
q
constraint:a general-purpose register except for $r0 and $r1 (for the csrxchg instruction)
Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-May/684339.html