Skip to content

Commit acba882

Browse files
committed
[Clang][LoongArch] Add inline asm support for the q constraint
This patch adds support for the `q` constraint: a general-purpose register except for $r0 and $r1 (for the csrxchg instruction) Based on llvm#140862 Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-May/684339.html
1 parent cbd0f13 commit acba882

File tree

4 files changed

+27
-0
lines changed

4 files changed

+27
-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
@@ -7278,6 +7278,8 @@ LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {
72787278
// 'm': A memory operand whose address is formed by a base register and
72797279
// offset that is suitable for use in instructions with the same
72807280
// addressing mode as st.w and ld.w.
7281+
// 'q': A general-purpose register except for $r0 and $r1 (for the csrxchg
7282+
// instruction)
72817283
// 'I': A signed 12-bit constant (for arithmetic instructions).
72827284
// 'J': Integer zero.
72837285
// 'K': An unsigned 12-bit constant (for logic instructions).
@@ -7291,6 +7293,7 @@ LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {
72917293
default:
72927294
break;
72937295
case 'f':
7296+
case 'q':
72947297
return C_RegisterClass;
72957298
case 'l':
72967299
case 'I':
@@ -7330,6 +7333,8 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint(
73307333
if (VT.isVector())
73317334
break;
73327335
return std::make_pair(0U, &LoongArch::GPRRegClass);
7336+
case 'q':
7337+
return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
73337338
case 'f':
73347339
if (Subtarget.hasBasicF() && VT == MVT::f32)
73357340
return std::make_pair(0U, &LoongArch::FPR32RegClass);

llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ define i32 @constraint_r(i32 %a, i32 %b) nounwind {
1717
ret i32 %1
1818
}
1919

20+
define i32 @constraint_q(i32 %a, i32 %b) nounwind {
21+
; CHECK-LABEL: constraint_q:
22+
; CHECK: # %bb.0:
23+
; CHECK-NEXT: #APP
24+
; CHECK-NEXT: csrxchg $a0, $a0, $a1
25+
; CHECK-NEXT: #NO_APP
26+
; CHECK-NEXT: ret
27+
%1 = tail call i32 asm "csrxchg $0, $1, $2", "=r,r,q,i"(i32 %a, i32 %b, i32 0)
28+
ret i32 %1
29+
}
30+
2031
define i32 @constraint_i(i32 %a) nounwind {
2132
; CHECK-LABEL: constraint_i:
2233
; CHECK: # %bb.0:

0 commit comments

Comments
 (0)