mirror of
https://github.com/intel/llvm.git
synced 2026-02-06 06:31:50 +08:00
[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:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
21
llvm/test/CodeGen/LoongArch/inline-asm-constraint-q.ll
Normal file
21
llvm/test/CodeGen/LoongArch/inline-asm-constraint-q.ll
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user