[Clang][LoongArch] Add inline asm support for the q constraint (#141037)

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
This commit is contained in:
hev
2025-05-23 11:14:41 +08:00
committed by GitHub
parent 73b8330054
commit 689342de25
4 changed files with 37 additions and 0 deletions

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -0,0 +1,21 @@
; RUN: llc --mtriple=loongarch32 --mattr=+f --verify-machineinstrs < %s | FileCheck %s
; RUN: llc --mtriple=loongarch64 --mattr=+f --verify-machineinstrs < %s | FileCheck %s
;; Check that the "q" operand is not R0.
define i32 @constraint_q_not_r0() {
; CHECK-NOT: csrxchg ${{[a-z]*}}, $r0, 0
; CHECK-NOT: csrxchg ${{[a-z]*}}, $zero, 0
entry:
%2 = tail call i32 asm "csrxchg $0, $1, 0", "=r,q,0"(i32 0, i32 0)
ret i32 %2
}
;; Check that the "q" operand is not R1.
define i32 @constraint_q_not_r1(i32 %0) {
; CHECK-NOT: csrxchg ${{[a-z]*}}, $r1, 0
; CHECK-NOT: csrxchg ${{[a-z]*}}, $ra, 0
entry:
%2 = tail call i32 asm "", "={$r1},{$r1}"(i32 0)
%3 = tail call i32 asm "csrxchg $0, $1, 0", "=r,q,0"(i32 %2, i32 %0)
ret i32 %3
}