-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[RISCV][llvm] Support fixed-length vector inline assembly constraints #150724
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-backend-risc-v @llvm/pr-subscribers-clang Author: Brandon Wu (4vtomat) ChangesFull diff: https://github.com/llvm/llvm-project/pull/150724.diff 2 Files Affected:
diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm-fixed-length-vector.c b/clang/test/CodeGen/RISCV/riscv-inline-asm-fixed-length-vector.c
new file mode 100644
index 0000000000000..0bfd9d6f158c6
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-inline-asm-fixed-length-vector.c
@@ -0,0 +1,39 @@
+// REQUIRES: riscv-registered-target
+
+// RUN: %clang_cc1 -triple riscv32 -target-feature +v \
+// RUN: -mvscale-min=2 -mvscale-max=2 -O2 -emit-llvm %s -o - \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
+// RUN: -mvscale-min=2 -mvscale-max=2 -O2 -emit-llvm %s -o - \
+// RUN: | FileCheck %s
+
+// Test RISC-V V-extension fixed-length vector inline assembly constraints.
+#include <riscv_vector.h>
+
+typedef vbool1_t fixed_bool1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
+typedef vint32m1_t fixed_i32m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
+typedef vint8mf2_t fixed_i8mf2_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen / 2)));
+
+fixed_i32m1_t test_vr(fixed_i32m1_t a) {
+// CHECK-LABEL: define{{.*}} @test_vr
+// CHECK: %0 = tail call <4 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vr,^vr,^vr"(<4 x i32> %a, <4 x i32> %a)
+ fixed_i32m1_t ret;
+ asm volatile ("vadd.vv %0, %1, %2" : "=vr"(ret) : "vr"(a), "vr"(a));
+ return ret;
+}
+
+fixed_i8mf2_t test_vd(fixed_i8mf2_t a) {
+// CHECK-LABEL: define{{.*}} @test_vd
+// CHECK: %0 = tail call <8 x i8> asm sideeffect "vadd.vv $0, $1, $2", "=^vd,^vr,^vr"(<8 x i8> %a, <8 x i8> %a)
+ fixed_i8mf2_t ret;
+ asm volatile ("vadd.vv %0, %1, %2" : "=vd"(ret) : "vr"(a), "vr"(a));
+ return ret;
+}
+
+fixed_bool1_t test_vm(fixed_bool1_t a) {
+// CHECK-LABEL: define{{.*}} @test_vm
+// CHECK: %1 = tail call <16 x i8> asm sideeffect "vmand.mm $0, $1, $2", "=^vm,^vm,^vm"(<16 x i8> %a, <16 x i8> %a)
+ fixed_bool1_t ret;
+ asm volatile ("vmand.mm %0, %1, %2" : "=vm"(ret) : "vm"(a), "vm"(a));
+ return ret;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 809fbc8926e35..53550e69e4c6d 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -23133,6 +23133,12 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
&RISCV::VRN2M4RegClass}) {
if (TRI->isTypeLegalForClass(*RC, VT.SimpleTy))
return std::make_pair(0U, RC);
+
+ if (VT.isFixedLengthVector() && Subtarget.useRVVForFixedLengthVectors()) {
+ MVT ContainerVT = getContainerForFixedLengthVector(VT);
+ if (TRI->isTypeLegalForClass(*RC, ContainerVT))
+ return std::make_pair(0U, RC);
+ }
}
} else if (Constraint == "vd") {
for (const auto *RC :
@@ -23146,10 +23152,24 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
&RISCV::VRN2M4NoV0RegClass}) {
if (TRI->isTypeLegalForClass(*RC, VT.SimpleTy))
return std::make_pair(0U, RC);
+
+ if (VT.isFixedLengthVector() && Subtarget.useRVVForFixedLengthVectors()) {
+ MVT ContainerVT = getContainerForFixedLengthVector(VT);
+ if (TRI->isTypeLegalForClass(*RC, ContainerVT))
+ return std::make_pair(0U, RC);
+ }
}
} else if (Constraint == "vm") {
if (TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.SimpleTy))
return std::make_pair(0U, &RISCV::VMV0RegClass);
+
+ if (VT.isFixedLengthVector() && Subtarget.useRVVForFixedLengthVectors()) {
+ MVT ContainerVT = getContainerForFixedLengthVector(VT);
+ // VT here is coerced to vector with i8 elements, so we need to check if
+ // this is a M1 register here instead of checking VMV0RegClass.
+ if (TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
+ return std::make_pair(0U, &RISCV::VMV0RegClass);
+ }
} else if (Constraint == "cr") {
if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
return std::make_pair(0U, &RISCV::GPRF16CRegClass);
@@ -24027,7 +24047,12 @@ bool RISCVTargetLowering::splitValueIntoRegisterParts(
return true;
}
- if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
+ if ((ValueVT.isScalableVector() || ValueVT.isFixedLengthVector()) &&
+ PartVT.isScalableVector()) {
+ if (ValueVT.isFixedLengthVector()) {
+ ValueVT = getContainerForFixedLengthVector(ValueVT.getSimpleVT());
+ Val = convertToScalableVector(ValueVT, Val, DAG, Subtarget);
+ }
LLVMContext &Context = *DAG.getContext();
EVT ValueEltVT = ValueVT.getVectorElementType();
EVT PartEltVT = PartVT.getVectorElementType();
@@ -24097,12 +24122,17 @@ SDValue RISCVTargetLowering::joinRegisterPartsIntoValue(
return Val;
}
- if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
+ if ((ValueVT.isScalableVector() || ValueVT.isFixedLengthVector()) &&
+ PartVT.isScalableVector()) {
LLVMContext &Context = *DAG.getContext();
SDValue Val = Parts[0];
EVT ValueEltVT = ValueVT.getVectorElementType();
EVT PartEltVT = PartVT.getVectorElementType();
unsigned ValueVTBitSize = ValueVT.getSizeInBits().getKnownMinValue();
+ if (ValueVT.isFixedLengthVector())
+ ValueVTBitSize = getContainerForFixedLengthVector(ValueVT.getSimpleVT())
+ .getSizeInBits()
+ .getKnownMinValue();
unsigned PartVTBitSize = PartVT.getSizeInBits().getKnownMinValue();
if (PartVTBitSize % ValueVTBitSize == 0) {
assert(PartVTBitSize >= ValueVTBitSize);
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this comment. Where is it coerced?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see. You tested riscv_rvv_vector_bits but this should also work without riscv_rvv_vector_bits.
clang/test/CodeGen/RISCV/riscv-inline-asm-fixed-length-vector.c
Outdated
Show resolved
Hide resolved
lenary
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please can you add a LLVM IR test for llc?
I don't think I know enough about the "fixed vectors in scalable vectors" lowering to know if splitValueIntoRegisterParts and joinRegisterPartsIntoValue are correct but they don't seem so wrong at a glance. I might have expected to see a call to convertFromScalableVector (as join and split tend to be symmetric) but I see there's a getExtractSubvector already.
Yeah sure!
The reason I didn't use |
|
Gentle ping~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to use useRVVForFixedLengthVectorVT(VT) instead of Subtarget.useRVVForFixedLengthVectors()? getContainerForFixedLengthVector expects only legal VTs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah right, we should use useRVVForFixedLengthVectorVT
9ab4f5f to
1fcc25d
Compare
|
rebase |
topperc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
1fcc25d to
6d39385
Compare
No description provided.