[llvm] [RISC-V] Support fixed vector type for inline asm (#117098) (PR #117100)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 20 18:22:46 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-selectiondag
Author: Zhijin Zeng (zengdage)
<details>
<summary>Changes</summary>
1. risc-v target don't support fixed vector types like v32i8 by isTypeLegalForClass, because those types don't be added into RCVTLists by RISCVRegisterInfo.td, so we need to use it's container value type to get it's RegisterClass.
2. We also need to fix the error between scalable vector type and fixed vector type. Take v32i8 to nxv8i8 as example,if don't apply this patch, the type become as follow in turn:
'v32i8 -> i256 -> i128 -> i64 -> nxv8i8'
SelectionDAG don't support translate i64 into nxv8i8, and it will get a fatal error. In order to fix this error, I check their vector type and RegisterClass, and if eligible, use insert_subvector to translate v32i8 into nxv8i8.
---
Full diff: https://github.com/llvm/llvm-project/pull/117100.diff
4 Files Affected:
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+5)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+3)
- (added) llvm/test/CodeGen/RISCV/inline-asm-fixed-v-constraint.ll (+72)
- (added) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-inlineasm.ll (+28)
``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 9d729d448502d8..d2559f13ba1e66 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -721,6 +721,11 @@ static void getCopyToPartsVector(SelectionDAG &DAG, const SDLoc &DL,
PartVT.getVectorElementCount());
SDValue Widened = widenVectorToPartType(DAG, Val, DL, WidenVT);
Val = DAG.getAnyExtOrTrunc(Widened, DL, PartVT);
+ } else if (PartVT.isScalableVector() && ValueVT.isFixedLengthVector() &&
+ TLI.getRegClassFor(PartVT) ==
+ TLI.getRegClassFor(ValueVT.getSimpleVT())) {
+ Val = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, PartVT, DAG.getUNDEF(PartVT),
+ Val, DAG.getVectorIdxConstant(0, DL));
} else {
// Don't extract an integer from a float vector. This can happen if the
// FP type gets softened to integer and then promoted. The promotion
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 976b2478b433e5..0191cbfb898472 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20494,6 +20494,9 @@ std::pair<unsigned, const TargetRegisterClass *>
RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
StringRef Constraint,
MVT VT) const {
+ if (Subtarget.useRVVForFixedLengthVectors() && VT.isFixedLengthVector() &&
+ useRVVForFixedLengthVectorVT(VT))
+ VT = getContainerForFixedLengthVector(VT);
// First, see if this is a constraint that directly corresponds to a RISC-V
// register class.
if (Constraint.size() == 1) {
diff --git a/llvm/test/CodeGen/RISCV/inline-asm-fixed-v-constraint.ll b/llvm/test/CodeGen/RISCV/inline-asm-fixed-v-constraint.ll
new file mode 100644
index 00000000000000..f92a3957398c41
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/inline-asm-fixed-v-constraint.ll
@@ -0,0 +1,72 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=RV32I %s
+; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=RV64I %s
+
+define <16 x i8> @constraint_vr(<16 x i8> %0, <16 x i8> %1) nounwind {
+; RV32I-LABEL: constraint_vr:
+; RV32I: # %bb.0:
+; RV32I-NEXT: #APP
+; RV32I-NEXT: vadd.vv v8, v8, v9
+; RV32I-NEXT: #NO_APP
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: constraint_vr:
+; RV64I: # %bb.0:
+; RV64I-NEXT: #APP
+; RV64I-NEXT: vadd.vv v8, v8, v9
+; RV64I-NEXT: #NO_APP
+; RV64I-NEXT: ret
+ %a = tail call <16 x i8> asm "vadd.vv $0, $1, $2", "=^vr,^vr,^vr"(
+ <16 x i8> %0, <16 x i8> %1)
+ ret <16 x i8> %a
+}
+
+define <16 x i8> @constraint_vd(<16 x i8> %0, <16 x i8> %1) nounwind {
+; RV32I-LABEL: constraint_vd:
+; RV32I: # %bb.0:
+; RV32I-NEXT: #APP
+; RV32I-NEXT: vadd.vv v8, v8, v9
+; RV32I-NEXT: #NO_APP
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: constraint_vd:
+; RV64I: # %bb.0:
+; RV64I-NEXT: #APP
+; RV64I-NEXT: vadd.vv v8, v8, v9
+; RV64I-NEXT: #NO_APP
+; RV64I-NEXT: ret
+ %a = tail call <16 x i8> asm "vadd.vv $0, $1, $2", "=^vd,^vr,^vr"(
+ <16 x i8> %0, <16 x i8> %1)
+ ret <16 x i8> %a
+}
+
+define <16 x i1> @constraint_vm(<16 x i1> %0, <16 x i1> %1) nounwind {
+; RV32I-LABEL: constraint_vm:
+; RV32I: # %bb.0:
+; RV32I-NEXT: vmv1r.v v9, v0
+; RV32I-NEXT: vmv1r.v v0, v8
+; RV32I-NEXT: #APP
+; RV32I-NEXT: vadd.vv v8, v9, v0
+; RV32I-NEXT: #NO_APP
+; RV32I-NEXT: vsetivli zero, 16, e8, m1, ta, ma
+; RV32I-NEXT: vand.vi v8, v8, 1
+; RV32I-NEXT: vmsne.vi v0, v8, 0
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: constraint_vm:
+; RV64I: # %bb.0:
+; RV64I-NEXT: vmv1r.v v9, v0
+; RV64I-NEXT: vmv1r.v v0, v8
+; RV64I-NEXT: #APP
+; RV64I-NEXT: vadd.vv v8, v9, v0
+; RV64I-NEXT: #NO_APP
+; RV64I-NEXT: vsetivli zero, 16, e8, m1, ta, ma
+; RV64I-NEXT: vand.vi v8, v8, 1
+; RV64I-NEXT: vmsne.vi v0, v8, 0
+; RV64I-NEXT: ret
+ %a = tail call <16 x i1> asm "vadd.vv $0, $1, $2", "=^vr,^vr,^vm"(
+ <16 x i1> %0, <16 x i1> %1)
+ ret <16 x i1> %a
+}
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-inlineasm.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-inlineasm.ll
new file mode 100644
index 00000000000000..fda1ea686a5edc
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-inlineasm.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,RV32
+; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,RV64
+
+declare <32 x i8> @llvm.vector.extract.v32i8.nxv8i8(<vscale x 8 x i8>, i64 immarg)
+
+declare <vscale x 8 x i8> @llvm.vector.insert.nxv8i8.v32i8(<vscale x 8 x i8>, <32 x i8>, i64 immarg)
+
+define <vscale x 8 x i8> @test(<vscale x 8 x i8> %0, <vscale x 8 x i8> %1, <vscale x 8 x i8> %2) {
+; CHECK-LABEL: test:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vmv1r.v v12, v9
+; CHECK-NEXT: #APP
+; CHECK-NEXT: vmacc.vv v10, v8, v12
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: vmv1r.v v8, v10
+; CHECK-NEXT: ret
+ %4 = tail call <32 x i8> @llvm.vector.extract.v32i8.nxv8i8(<vscale x 8 x i8> %0, i64 0)
+ %5 = tail call <32 x i8> @llvm.vector.extract.v32i8.nxv8i8(<vscale x 8 x i8> %1, i64 0)
+ %6 = tail call <32 x i8> @llvm.vector.extract.v32i8.nxv8i8(<vscale x 8 x i8> %2, i64 0)
+ %7 = tail call <32 x i8> asm sideeffect "vmacc.vv $0, $1, $2\0A\09", "=&^vr,^vr,^vr,0,~{memory}"(<32 x i8> %4, <32 x i8> %5, <32 x i8> %6)
+ %8 = tail call <vscale x 8 x i8> @llvm.vector.insert.nxv8i8.v32i8(<vscale x 8 x i8> undef, <32 x i8> %7, i64 0)
+ ret <vscale x 8 x i8> %8
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; RV32: {{.*}}
+; RV64: {{.*}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/117100
More information about the llvm-commits
mailing list