Author: hev
Date: 2025-05-23T11:14:41+08:00
New Revision: 689342de25e65597583805eecd367c4982fd53b8

URL: 
https://github.com/llvm/llvm-project/commit/689342de25e65597583805eecd367c4982fd53b8
DIFF: 
https://github.com/llvm/llvm-project/commit/689342de25e65597583805eecd367c4982fd53b8.diff

LOG: [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

Added: 
    llvm/test/CodeGen/LoongArch/inline-asm-constraint-q.ll

Modified: 
    clang/lib/Basic/Targets/LoongArch.cpp
    clang/test/CodeGen/LoongArch/inline-asm-constraints.c
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Removed: 
    


################################################################################
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-q.ll 
b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-q.ll
new file mode 100644
index 0000000000000..e16bd1d8aacf3
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-q.ll
@@ -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
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to