[llvm] 33c4407 - [RISCV] Support cR Inline Asm Constraint (#124174)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 23 16:19:24 PST 2025
Author: Sam Elliott
Date: 2025-01-23T16:19:19-08:00
New Revision: 33c44074714d1d2f3d5f65c3fb842cddb6b689ac
URL: https://github.com/llvm/llvm-project/commit/33c44074714d1d2f3d5f65c3fb842cddb6b689ac
DIFF: https://github.com/llvm/llvm-project/commit/33c44074714d1d2f3d5f65c3fb842cddb6b689ac.diff
LOG: [RISCV] Support cR Inline Asm Constraint (#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
Added:
Modified:
clang/lib/Basic/Targets/RISCV.cpp
clang/test/CodeGen/RISCV/riscv-inline-asm.c
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/rv32-inline-asm-pairs.ll
llvm/test/CodeGen/RISCV/rv64-inline-asm-pairs.ll
llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll
Removed:
################################################################################
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 295fd315c56daf..324b13ab164d34 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -21087,7 +21087,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);
@@ -21176,6 +21176,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-NEXT: addi sp, sp, 16
+; CHECK-NEXT: ret
+entry:
+ %2 = alloca ptr, align 4
+ %3 = alloca i64, align 8
+ store ptr %0, ptr %2, align 4
+ store i64 %1, ptr %3, align 8
+ %4 = load ptr, ptr %2, align 4
+ %5 = load i64, ptr %3, align 8
+ %6 = call { ptr, i64 } asm sideeffect "/* $0; $1 */", "=r,=^cR,0,1"(ptr %4, i64 %5)
+ %7 = extractvalue { ptr, i64} %6, 0
+ %8 = extractvalue { ptr, i64 } %6, 1
+ store ptr %7, ptr %2, align 4
+ store i64 %8, ptr %3, align 8
+ %9 = load i64, ptr %3, align 8
+ ret i64 %9
+}
diff --git a/llvm/test/CodeGen/RISCV/rv64-inline-asm-pairs.ll b/llvm/test/CodeGen/RISCV/rv64-inline-asm-pairs.ll
index 41f353d0781aed..ac455b7fac8827 100644
--- a/llvm/test/CodeGen/RISCV/rv64-inline-asm-pairs.ll
+++ b/llvm/test/CodeGen/RISCV/rv64-inline-asm-pairs.ll
@@ -71,3 +71,73 @@ entry:
%9 = load i128, ptr %3, align 16
ret i128 %9
}
+
+define i128 @test_cR_wide_scalar_simple(i128 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 i128 asm sideeffect "/* $0 <- $1 */", "=&^cR,^cR"(i128 %0)
+ ret i128 %1
+}
+
+define i64 @test_cR_wide_scalar_with_ops(i64 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 i64 %0 to i128
+ %2 = shl i128 %1, 64
+ %3 = or i128 %1, %2
+ %4 = call i128 asm sideeffect "/* $0 <- $1 */", "=&^cR,^cR"(i128 %3)
+ %5 = trunc i128 %4 to i64
+ %6 = lshr i128 %4, 64
+ %7 = trunc i128 %6 to i64
+ %8 = or i64 %5, %7
+ ret i64 %8
+}
+
+define i128 @test_cR_wide_scalar_inout(ptr %0, i128 noundef %1) nounwind {
+; CHECK-LABEL: test_cR_wide_scalar_inout:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: mv a3, a2
+; CHECK-NEXT: sd a0, 24(sp)
+; CHECK-NEXT: mv a2, a1
+; CHECK-NEXT: sd a1, 0(sp)
+; CHECK-NEXT: sd a3, 8(sp)
+; CHECK-NEXT: #APP
+; CHECK-NEXT: # a0; a2
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: sd a0, 24(sp)
+; CHECK-NEXT: sd a2, 0(sp)
+; CHECK-NEXT: sd a3, 8(sp)
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: mv a1, a3
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: ret
+entry:
+ %2 = alloca ptr, align 8
+ %3 = alloca i128, align 16
+ store ptr %0, ptr %2, align 8
+ store i128 %1, ptr %3, align 16
+ %4 = load ptr, ptr %2, align 8
+ %5 = load i128, ptr %3, align 16
+ %6 = call { ptr, i128 } asm sideeffect "/* $0; $1 */", "=r,=^cR,0,1"(ptr %4, i128 %5)
+ %7 = extractvalue { ptr, i128} %6, 0
+ %8 = extractvalue { ptr, i128 } %6, 1
+ store ptr %7, ptr %2, align 8
+ store i128 %8, ptr %3, align 16
+ %9 = load i128, ptr %3, align 16
+ ret i128 %9
+}
diff --git a/llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll b/llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll
index 81a8a8065e6b61..b7d7d4c0945b60 100644
--- a/llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll
+++ b/llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll
@@ -82,6 +82,24 @@ entry:
ret void
}
+define dso_local void @zdinx_asm_cR_inout(ptr nocapture noundef writeonly %a, double noundef %b) nounwind {
+; CHECK-LABEL: zdinx_asm_cR_inout:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mv a3, a2
+; CHECK-NEXT: mv a2, a1
+; CHECK-NEXT: #APP
+; CHECK-NEXT: fabs.d a2, a2
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: sw a2, 8(a0)
+; CHECK-NEXT: sw a3, 12(a0)
+; CHECK-NEXT: ret
+entry:
+ %arrayidx = getelementptr inbounds double, ptr %a, i32 1
+ %0 = tail call double asm "fsgnjx.d $0, $1, $1", "=^cR,0"(double %b)
+ store double %0, ptr %arrayidx, align 8
+ ret void
+}
+
define dso_local void @zfinx_asm(ptr nocapture noundef writeonly %a, float noundef %b, float noundef %c) nounwind {
; CHECK-LABEL: zfinx_asm:
; CHECK: # %bb.0: # %entry
@@ -167,3 +185,29 @@ entry:
store half %0, ptr %arrayidx, align 8
ret void
}
+
+define dso_local void @zdinx_asm_cR(ptr nocapture noundef writeonly %a, double noundef %b, double noundef %c) nounwind {
+; CHECK-LABEL: zdinx_asm_cR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: addi sp, sp, -16
+; CHECK-NEXT: sw s0, 12(sp) # 4-byte Folded Spill
+; CHECK-NEXT: sw s1, 8(sp) # 4-byte Folded Spill
+; CHECK-NEXT: mv a5, a4
+; CHECK-NEXT: mv s1, a2
+; CHECK-NEXT: mv a4, a3
+; CHECK-NEXT: mv s0, a1
+; CHECK-NEXT: #APP
+; CHECK-NEXT: fsgnjx.d a2, s0, a4
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: sw a2, 8(a0)
+; CHECK-NEXT: sw a3, 12(a0)
+; CHECK-NEXT: lw s0, 12(sp) # 4-byte Folded Reload
+; CHECK-NEXT: lw s1, 8(sp) # 4-byte Folded Reload
+; CHECK-NEXT: addi sp, sp, 16
+; CHECK-NEXT: ret
+entry:
+ %arrayidx = getelementptr inbounds double, ptr %a, i32 1
+ %0 = tail call double asm "fsgnjx.d $0, $1, $2", "=^cR,^cR,^cR"(double %b, double %c)
+ store double %0, ptr %arrayidx, align 8
+ ret void
+}
More information about the llvm-commits
mailing list