[clang] [llvm] [RISCV] Support cR Inline Asm Constraint (PR #124174)

2025-01-23 Thread Sam Elliott via cfe-commits

https://github.com/lenary closed 
https://github.com/llvm/llvm-project/pull/124174
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [RISCV] Support cR Inline Asm Constraint (PR #124174)

2025-01-23 Thread Sam Elliott via cfe-commits

https://github.com/lenary created 
https://github.com/llvm/llvm-project/pull/124174

This denotes RVC-compatible GPR Pairs, which are used by the Zclsd extension.

C API PR: riscv-non-isa/riscv-c-api-doc#102

>From d26d237f6586b879aab96b5f604e2e85156e778f Mon Sep 17 00:00:00 2001
From: Sam Elliott 
Date: Thu, 23 Jan 2025 10:48:08 -0800
Subject: [PATCH] [RISCV] Support cR Inline Asm Constraint

This denotes RVC-compatible GPR Pairs, which are used by the Zclsd
extension.

C API PR: riscv-non-isa/riscv-c-api-doc#102
---
 clang/lib/Basic/Targets/RISCV.cpp |  2 +-
 clang/test/CodeGen/RISCV/riscv-inline-asm.c   |  8 +++
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  4 +-
 .../CodeGen/RISCV/rv32-inline-asm-pairs.ll| 70 +++
 .../CodeGen/RISCV/rv64-inline-asm-pairs.ll| 70 +++
 .../CodeGen/RISCV/zdinx-asm-constraint.ll | 44 
 6 files changed, 196 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Basic/Targets/RISCV.cpp 
b/clang/lib/Basic/Targets/RISCV.cpp
index db23b0c2283385..8167d7603b0e14 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -102,7 +102,7 @@ bool RISCVTargetInfo::validateAsmConstraint(
 return true;
   case 'c':
 // A RVC register - GPR or FPR
-if (Name[1] == 'r' || Name[1] == 'f') {
+if (Name[1] == 'r' || Name[1] == 'R' || Name[1] == 'f') {
   Info.setAllowsRegister();
   Name += 1;
   return true;
diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c 
b/clang/test/CodeGen/RISCV/riscv-inline-asm.c
index 9da306807ed0dc..f2031e0adcbcb2 100644
--- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c
+++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c
@@ -46,6 +46,14 @@ double_xlen_t test_R_wide_scalar(double_xlen_t p) {
   return ret;
 }
 
+double_xlen_t test_cR_wide_scalar(double_xlen_t p) {
+// CHECK-LABEL: define{{.*}} {{i128|i64}} @test_cR_wide_scalar(
+// CHECK: call {{i128|i64}} asm sideeffect "", "=^cR,^cR"({{i128|i64}} %{{.*}})
+  double_xlen_t ret;
+  asm volatile("" : "=cR"(ret) : "cR"(p));
+  return ret;
+}
+
 void test_I(void) {
 // CHECK-LABEL: define{{.*}} void @test_I()
 // CHECK: call void asm sideeffect "", "I"(i32 2047)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index b25cb128bce9fb..e08b22e1f86fb0 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20903,7 +20903,7 @@ RISCVTargetLowering::getConstraintType(StringRef 
Constraint) const {
   } else {
 if (Constraint == "vr" || Constraint == "vd" || Constraint == "vm")
   return C_RegisterClass;
-if (Constraint == "cr" || Constraint == "cf")
+if (Constraint == "cr" || Constraint == "cR" || Constraint == "cf")
   return C_RegisterClass;
   }
   return TargetLowering::getConstraintType(Constraint);
@@ -20992,6 +20992,8 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const 
TargetRegisterInfo *TRI,
   return std::make_pair(0U, &RISCV::GPRPairCRegClass);
 if (!VT.isVector())
   return std::make_pair(0U, &RISCV::GPRCRegClass);
+  } else if (Constraint == "cR") {
+  return std::make_pair(0U, &RISCV::GPRPairCRegClass);
   } else if (Constraint == "cf") {
 if (VT == MVT::f16) {
   if (Subtarget.hasStdExtZfhmin())
diff --git a/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll 
b/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
index 04a5d268aebff7..f14fe2665835e4 100644
--- a/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
+++ b/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
@@ -71,3 +71,73 @@ entry:
   %9 = load i64, ptr %3, align 8
   ret i64 %9
 }
+
+define i64 @test_cR_wide_scalar_simple(i64 noundef %0) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_simple:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:#APP
+; CHECK-NEXT:# a2 <- a0
+; CHECK-NEXT:#NO_APP
+; CHECK-NEXT:mv a0, a2
+; CHECK-NEXT:mv a1, a3
+; CHECK-NEXT:ret
+entry:
+  %1 = call i64 asm sideeffect "/* $0 <- $1 */", "=&^cR,^cR"(i64 %0)
+  ret i64 %1
+}
+
+define i32 @test_cR_wide_scalar_with_ops(i32 noundef %0) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_with_ops:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:mv a1, a0
+; CHECK-NEXT:#APP
+; CHECK-NEXT:# a2 <- a0
+; CHECK-NEXT:#NO_APP
+; CHECK-NEXT:or a0, a2, a3
+; CHECK-NEXT:ret
+entry:
+  %1 = zext i32 %0 to i64
+  %2 = shl i64 %1, 32
+  %3 = or i64 %1, %2
+  %4 = call i64 asm sideeffect "/* $0 <- $1 */", "=&^cR,^cR"(i64 %3)
+  %5 = trunc i64 %4 to i32
+  %6 = lshr i64 %4, 32
+  %7 = trunc i64 %6 to i32
+  %8 = or i32 %5, %7
+  ret i32 %8
+}
+
+define i64 @test_cR_wide_scalar_inout(ptr %0, i64 noundef %1) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_inout:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:addi sp, sp, -16
+; CHECK-NEXT:mv a3, a2
+; CHECK-NEXT:sw a0, 12(sp)
+; CHECK-NEXT:mv a2, a1
+; CHECK-NEXT:sw a1, 0(sp)
+; CHECK-NEXT:sw a3, 4(sp)

[clang] [llvm] [RISCV] Support cR Inline Asm Constraint (PR #124174)

2025-01-23 Thread Craig Topper via cfe-commits

https://github.com/topperc approved this pull request.

LGTM

https://github.com/llvm/llvm-project/pull/124174
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [RISCV] Support cR Inline Asm Constraint (PR #124174)

2025-01-23 Thread Sam Elliott via cfe-commits

https://github.com/lenary updated 
https://github.com/llvm/llvm-project/pull/124174

>From d26d237f6586b879aab96b5f604e2e85156e778f Mon Sep 17 00:00:00 2001
From: Sam Elliott 
Date: Thu, 23 Jan 2025 10:48:08 -0800
Subject: [PATCH 1/2] [RISCV] Support cR Inline Asm Constraint

This denotes RVC-compatible GPR Pairs, which are used by the Zclsd
extension.

C API PR: riscv-non-isa/riscv-c-api-doc#102
---
 clang/lib/Basic/Targets/RISCV.cpp |  2 +-
 clang/test/CodeGen/RISCV/riscv-inline-asm.c   |  8 +++
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  4 +-
 .../CodeGen/RISCV/rv32-inline-asm-pairs.ll| 70 +++
 .../CodeGen/RISCV/rv64-inline-asm-pairs.ll| 70 +++
 .../CodeGen/RISCV/zdinx-asm-constraint.ll | 44 
 6 files changed, 196 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Basic/Targets/RISCV.cpp 
b/clang/lib/Basic/Targets/RISCV.cpp
index db23b0c2283385..8167d7603b0e14 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -102,7 +102,7 @@ bool RISCVTargetInfo::validateAsmConstraint(
 return true;
   case 'c':
 // A RVC register - GPR or FPR
-if (Name[1] == 'r' || Name[1] == 'f') {
+if (Name[1] == 'r' || Name[1] == 'R' || Name[1] == 'f') {
   Info.setAllowsRegister();
   Name += 1;
   return true;
diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c 
b/clang/test/CodeGen/RISCV/riscv-inline-asm.c
index 9da306807ed0dc..f2031e0adcbcb2 100644
--- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c
+++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c
@@ -46,6 +46,14 @@ double_xlen_t test_R_wide_scalar(double_xlen_t p) {
   return ret;
 }
 
+double_xlen_t test_cR_wide_scalar(double_xlen_t p) {
+// CHECK-LABEL: define{{.*}} {{i128|i64}} @test_cR_wide_scalar(
+// CHECK: call {{i128|i64}} asm sideeffect "", "=^cR,^cR"({{i128|i64}} %{{.*}})
+  double_xlen_t ret;
+  asm volatile("" : "=cR"(ret) : "cR"(p));
+  return ret;
+}
+
 void test_I(void) {
 // CHECK-LABEL: define{{.*}} void @test_I()
 // CHECK: call void asm sideeffect "", "I"(i32 2047)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index b25cb128bce9fb..e08b22e1f86fb0 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20903,7 +20903,7 @@ RISCVTargetLowering::getConstraintType(StringRef 
Constraint) const {
   } else {
 if (Constraint == "vr" || Constraint == "vd" || Constraint == "vm")
   return C_RegisterClass;
-if (Constraint == "cr" || Constraint == "cf")
+if (Constraint == "cr" || Constraint == "cR" || Constraint == "cf")
   return C_RegisterClass;
   }
   return TargetLowering::getConstraintType(Constraint);
@@ -20992,6 +20992,8 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const 
TargetRegisterInfo *TRI,
   return std::make_pair(0U, &RISCV::GPRPairCRegClass);
 if (!VT.isVector())
   return std::make_pair(0U, &RISCV::GPRCRegClass);
+  } else if (Constraint == "cR") {
+  return std::make_pair(0U, &RISCV::GPRPairCRegClass);
   } else if (Constraint == "cf") {
 if (VT == MVT::f16) {
   if (Subtarget.hasStdExtZfhmin())
diff --git a/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll 
b/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
index 04a5d268aebff7..f14fe2665835e4 100644
--- a/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
+++ b/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
@@ -71,3 +71,73 @@ entry:
   %9 = load i64, ptr %3, align 8
   ret i64 %9
 }
+
+define i64 @test_cR_wide_scalar_simple(i64 noundef %0) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_simple:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:#APP
+; CHECK-NEXT:# a2 <- a0
+; CHECK-NEXT:#NO_APP
+; CHECK-NEXT:mv a0, a2
+; CHECK-NEXT:mv a1, a3
+; CHECK-NEXT:ret
+entry:
+  %1 = call i64 asm sideeffect "/* $0 <- $1 */", "=&^cR,^cR"(i64 %0)
+  ret i64 %1
+}
+
+define i32 @test_cR_wide_scalar_with_ops(i32 noundef %0) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_with_ops:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:mv a1, a0
+; CHECK-NEXT:#APP
+; CHECK-NEXT:# a2 <- a0
+; CHECK-NEXT:#NO_APP
+; CHECK-NEXT:or a0, a2, a3
+; CHECK-NEXT:ret
+entry:
+  %1 = zext i32 %0 to i64
+  %2 = shl i64 %1, 32
+  %3 = or i64 %1, %2
+  %4 = call i64 asm sideeffect "/* $0 <- $1 */", "=&^cR,^cR"(i64 %3)
+  %5 = trunc i64 %4 to i32
+  %6 = lshr i64 %4, 32
+  %7 = trunc i64 %6 to i32
+  %8 = or i32 %5, %7
+  ret i32 %8
+}
+
+define i64 @test_cR_wide_scalar_inout(ptr %0, i64 noundef %1) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_inout:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:addi sp, sp, -16
+; CHECK-NEXT:mv a3, a2
+; CHECK-NEXT:sw a0, 12(sp)
+; CHECK-NEXT:mv a2, a1
+; CHECK-NEXT:sw a1, 0(sp)
+; CHECK-NEXT:sw a3, 4(sp)
+; CHECK-NEXT:#APP
+; CHECK-NEXT:# a0; a2
+; CHECK-NEXT:#NO_APP
+; CHECK-NEXT:sw a0, 12(sp)
+; CHECK-NEX

[clang] [llvm] [RISCV] Support cR Inline Asm Constraint (PR #124174)

2025-01-23 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-backend-risc-v

Author: Sam Elliott (lenary)


Changes

This denotes RVC-compatible GPR Pairs, which are used by the Zclsd extension.

C API PR: riscv-non-isa/riscv-c-api-doc#102

---
Full diff: https://github.com/llvm/llvm-project/pull/124174.diff


6 Files Affected:

- (modified) clang/lib/Basic/Targets/RISCV.cpp (+1-1) 
- (modified) clang/test/CodeGen/RISCV/riscv-inline-asm.c (+8) 
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+3-1) 
- (modified) llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll (+70) 
- (modified) llvm/test/CodeGen/RISCV/rv64-inline-asm-pairs.ll (+70) 
- (modified) llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll (+44) 


``diff
diff --git a/clang/lib/Basic/Targets/RISCV.cpp 
b/clang/lib/Basic/Targets/RISCV.cpp
index db23b0c2283385..8167d7603b0e14 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -102,7 +102,7 @@ bool RISCVTargetInfo::validateAsmConstraint(
 return true;
   case 'c':
 // A RVC register - GPR or FPR
-if (Name[1] == 'r' || Name[1] == 'f') {
+if (Name[1] == 'r' || Name[1] == 'R' || Name[1] == 'f') {
   Info.setAllowsRegister();
   Name += 1;
   return true;
diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c 
b/clang/test/CodeGen/RISCV/riscv-inline-asm.c
index 9da306807ed0dc..f2031e0adcbcb2 100644
--- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c
+++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c
@@ -46,6 +46,14 @@ double_xlen_t test_R_wide_scalar(double_xlen_t p) {
   return ret;
 }
 
+double_xlen_t test_cR_wide_scalar(double_xlen_t p) {
+// CHECK-LABEL: define{{.*}} {{i128|i64}} @test_cR_wide_scalar(
+// CHECK: call {{i128|i64}} asm sideeffect "", "=^cR,^cR"({{i128|i64}} %{{.*}})
+  double_xlen_t ret;
+  asm volatile("" : "=cR"(ret) : "cR"(p));
+  return ret;
+}
+
 void test_I(void) {
 // CHECK-LABEL: define{{.*}} void @test_I()
 // CHECK: call void asm sideeffect "", "I"(i32 2047)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index b25cb128bce9fb..e08b22e1f86fb0 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20903,7 +20903,7 @@ RISCVTargetLowering::getConstraintType(StringRef 
Constraint) const {
   } else {
 if (Constraint == "vr" || Constraint == "vd" || Constraint == "vm")
   return C_RegisterClass;
-if (Constraint == "cr" || Constraint == "cf")
+if (Constraint == "cr" || Constraint == "cR" || Constraint == "cf")
   return C_RegisterClass;
   }
   return TargetLowering::getConstraintType(Constraint);
@@ -20992,6 +20992,8 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const 
TargetRegisterInfo *TRI,
   return std::make_pair(0U, &RISCV::GPRPairCRegClass);
 if (!VT.isVector())
   return std::make_pair(0U, &RISCV::GPRCRegClass);
+  } else if (Constraint == "cR") {
+  return std::make_pair(0U, &RISCV::GPRPairCRegClass);
   } else if (Constraint == "cf") {
 if (VT == MVT::f16) {
   if (Subtarget.hasStdExtZfhmin())
diff --git a/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll 
b/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
index 04a5d268aebff7..f14fe2665835e4 100644
--- a/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
+++ b/llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
@@ -71,3 +71,73 @@ entry:
   %9 = load i64, ptr %3, align 8
   ret i64 %9
 }
+
+define i64 @test_cR_wide_scalar_simple(i64 noundef %0) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_simple:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:#APP
+; CHECK-NEXT:# a2 <- a0
+; CHECK-NEXT:#NO_APP
+; CHECK-NEXT:mv a0, a2
+; CHECK-NEXT:mv a1, a3
+; CHECK-NEXT:ret
+entry:
+  %1 = call i64 asm sideeffect "/* $0 <- $1 */", "=&^cR,^cR"(i64 %0)
+  ret i64 %1
+}
+
+define i32 @test_cR_wide_scalar_with_ops(i32 noundef %0) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_with_ops:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:mv a1, a0
+; CHECK-NEXT:#APP
+; CHECK-NEXT:# a2 <- a0
+; CHECK-NEXT:#NO_APP
+; CHECK-NEXT:or a0, a2, a3
+; CHECK-NEXT:ret
+entry:
+  %1 = zext i32 %0 to i64
+  %2 = shl i64 %1, 32
+  %3 = or i64 %1, %2
+  %4 = call i64 asm sideeffect "/* $0 <- $1 */", "=&^cR,^cR"(i64 %3)
+  %5 = trunc i64 %4 to i32
+  %6 = lshr i64 %4, 32
+  %7 = trunc i64 %6 to i32
+  %8 = or i32 %5, %7
+  ret i32 %8
+}
+
+define i64 @test_cR_wide_scalar_inout(ptr %0, i64 noundef %1) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_inout:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:addi sp, sp, -16
+; CHECK-NEXT:mv a3, a2
+; CHECK-NEXT:sw a0, 12(sp)
+; CHECK-NEXT:mv a2, a1
+; CHECK-NEXT:sw a1, 0(sp)
+; CHECK-NEXT:sw a3, 4(sp)
+; CHECK-NEXT:#APP
+; CHECK-NEXT:# a0; a2
+; CHECK-NEXT:#NO_APP
+; CHECK-NEXT:sw a0, 12(sp)
+; CHECK-NEXT:sw a2, 0(sp)
+; CHECK-NEXT:sw a3, 4(sp)
+; CHECK-NEXT:mv a0, a2
+; CHECK-NEXT:mv a1, a3
+; CHECK-N