Skip to content

Commit 689342d

Browse files
authored
[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
1 parent 73b8330 commit 689342d

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

clang/lib/Basic/Targets/LoongArch.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ bool LoongArchTargetInfo::validateAsmConstraint(
139139
// A signed 16-bit constant.
140140
Info.setRequiresImmediate(-32768, 32767);
141141
return true;
142+
case 'q':
143+
// A general-purpose register except for $r0 and $r1 (for the csrxchg
144+
// instruction)
145+
Info.setAllowsRegister();
146+
return true;
142147
case 'I':
143148
// A signed 12-bit constant (for arithmetic instructions).
144149
Info.setRequiresImmediate(-2048, 2047);

clang/test/CodeGen/LoongArch/inline-asm-constraints.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ void test_m(int *p) {
3535
asm volatile("" :: "m"(*(p+4)));
3636
}
3737

38+
void test_q(void) {
39+
// CHECK-LABEL: define{{.*}} void @test_q()
40+
// CHECK: call void asm sideeffect "", "q"(i32 0)
41+
asm volatile ("" :: "q"(0));
42+
}
43+
3844
void test_I(void) {
3945
// CHECK-LABEL: define{{.*}} void @test_I()
4046
// CHECK: call void asm sideeffect "", "I"(i32 2047)

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7276,6 +7276,8 @@ LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {
72767276
// 'm': A memory operand whose address is formed by a base register and
72777277
// offset that is suitable for use in instructions with the same
72787278
// addressing mode as st.w and ld.w.
7279+
// 'q': A general-purpose register except for $r0 and $r1 (for the csrxchg
7280+
// instruction)
72797281
// 'I': A signed 12-bit constant (for arithmetic instructions).
72807282
// 'J': Integer zero.
72817283
// 'K': An unsigned 12-bit constant (for logic instructions).
@@ -7289,6 +7291,7 @@ LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {
72897291
default:
72907292
break;
72917293
case 'f':
7294+
case 'q':
72927295
return C_RegisterClass;
72937296
case 'l':
72947297
case 'I':
@@ -7328,6 +7331,8 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint(
73287331
if (VT.isVector())
73297332
break;
73307333
return std::make_pair(0U, &LoongArch::GPRRegClass);
7334+
case 'q':
7335+
return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
73317336
case 'f':
73327337
if (Subtarget.hasBasicF() && VT == MVT::f32)
73337338
return std::make_pair(0U, &LoongArch::FPR32RegClass);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: llc --mtriple=loongarch32 --mattr=+f --verify-machineinstrs < %s | FileCheck %s
2+
; RUN: llc --mtriple=loongarch64 --mattr=+f --verify-machineinstrs < %s | FileCheck %s
3+
4+
;; Check that the "q" operand is not R0.
5+
define i32 @constraint_q_not_r0() {
6+
; CHECK-NOT: csrxchg ${{[a-z]*}}, $r0, 0
7+
; CHECK-NOT: csrxchg ${{[a-z]*}}, $zero, 0
8+
entry:
9+
%2 = tail call i32 asm "csrxchg $0, $1, 0", "=r,q,0"(i32 0, i32 0)
10+
ret i32 %2
11+
}
12+
13+
;; Check that the "q" operand is not R1.
14+
define i32 @constraint_q_not_r1(i32 %0) {
15+
; CHECK-NOT: csrxchg ${{[a-z]*}}, $r1, 0
16+
; CHECK-NOT: csrxchg ${{[a-z]*}}, $ra, 0
17+
entry:
18+
%2 = tail call i32 asm "", "={$r1},{$r1}"(i32 0)
19+
%3 = tail call i32 asm "csrxchg $0, $1, 0", "=r,q,0"(i32 %2, i32 %0)
20+
ret i32 %3
21+
}

0 commit comments

Comments
 (0)