Skip to content

Commit 48bf19c

Browse files
committed
[RISCV][llvm] Support fixed-length vector inline assembly constraints
1 parent 69e4514 commit 48bf19c

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// REQUIRES: riscv-registered-target
2+
3+
// RUN: %clang_cc1 -triple riscv32 -target-feature +v \
4+
// RUN: -mvscale-min=2 -mvscale-max=2 -O2 -emit-llvm %s -o - \
5+
// RUN: | FileCheck %s
6+
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
7+
// RUN: -mvscale-min=2 -mvscale-max=2 -O2 -emit-llvm %s -o - \
8+
// RUN: | FileCheck %s
9+
10+
// Test RISC-V V-extension fixed-length vector inline assembly constraints.
11+
#include <riscv_vector.h>
12+
13+
typedef vbool1_t fixed_bool1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
14+
typedef vint32m1_t fixed_i32m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
15+
typedef vint8mf2_t fixed_i8mf2_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen / 2)));
16+
17+
fixed_i32m1_t test_vr(fixed_i32m1_t a) {
18+
// CHECK-LABEL: define{{.*}} @test_vr
19+
// 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)
20+
fixed_i32m1_t ret;
21+
asm volatile ("vadd.vv %0, %1, %2" : "=vr"(ret) : "vr"(a), "vr"(a));
22+
return ret;
23+
}
24+
25+
fixed_i8mf2_t test_vd(fixed_i8mf2_t a) {
26+
// CHECK-LABEL: define{{.*}} @test_vd
27+
// 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)
28+
fixed_i8mf2_t ret;
29+
asm volatile ("vadd.vv %0, %1, %2" : "=vd"(ret) : "vr"(a), "vr"(a));
30+
return ret;
31+
}
32+
33+
fixed_bool1_t test_vm(fixed_bool1_t a) {
34+
// CHECK-LABEL: define{{.*}} @test_vm
35+
// 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)
36+
fixed_bool1_t ret;
37+
asm volatile ("vmand.mm %0, %1, %2" : "=vm"(ret) : "vm"(a), "vm"(a));
38+
return ret;
39+
}

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23408,6 +23408,12 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2340823408
&RISCV::VRN2M4RegClass}) {
2340923409
if (TRI->isTypeLegalForClass(*RC, VT.SimpleTy))
2341023410
return std::make_pair(0U, RC);
23411+
23412+
if (VT.isFixedLengthVector() && Subtarget.useRVVForFixedLengthVectors()) {
23413+
MVT ContainerVT = getContainerForFixedLengthVector(VT);
23414+
if (TRI->isTypeLegalForClass(*RC, ContainerVT))
23415+
return std::make_pair(0U, RC);
23416+
}
2341123417
}
2341223418
} else if (Constraint == "vd") {
2341323419
for (const auto *RC :
@@ -23421,10 +23427,24 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2342123427
&RISCV::VRN2M4NoV0RegClass}) {
2342223428
if (TRI->isTypeLegalForClass(*RC, VT.SimpleTy))
2342323429
return std::make_pair(0U, RC);
23430+
23431+
if (VT.isFixedLengthVector() && Subtarget.useRVVForFixedLengthVectors()) {
23432+
MVT ContainerVT = getContainerForFixedLengthVector(VT);
23433+
if (TRI->isTypeLegalForClass(*RC, ContainerVT))
23434+
return std::make_pair(0U, RC);
23435+
}
2342423436
}
2342523437
} else if (Constraint == "vm") {
2342623438
if (TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.SimpleTy))
2342723439
return std::make_pair(0U, &RISCV::VMV0RegClass);
23440+
23441+
if (VT.isFixedLengthVector() && Subtarget.useRVVForFixedLengthVectors()) {
23442+
MVT ContainerVT = getContainerForFixedLengthVector(VT);
23443+
// VT here is coerced to vector with i8 elements, so we need to check if
23444+
// this is a M1 register here instead of checking VMV0RegClass.
23445+
if (TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23446+
return std::make_pair(0U, &RISCV::VMV0RegClass);
23447+
}
2342823448
} else if (Constraint == "cr") {
2342923449
if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
2343023450
return std::make_pair(0U, &RISCV::GPRF16CRegClass);
@@ -24302,7 +24322,12 @@ bool RISCVTargetLowering::splitValueIntoRegisterParts(
2430224322
return true;
2430324323
}
2430424324

24305-
if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
24325+
if ((ValueVT.isScalableVector() || ValueVT.isFixedLengthVector()) &&
24326+
PartVT.isScalableVector()) {
24327+
if (ValueVT.isFixedLengthVector()) {
24328+
ValueVT = getContainerForFixedLengthVector(ValueVT.getSimpleVT());
24329+
Val = convertToScalableVector(ValueVT, Val, DAG, Subtarget);
24330+
}
2430624331
LLVMContext &Context = *DAG.getContext();
2430724332
EVT ValueEltVT = ValueVT.getVectorElementType();
2430824333
EVT PartEltVT = PartVT.getVectorElementType();
@@ -24372,12 +24397,17 @@ SDValue RISCVTargetLowering::joinRegisterPartsIntoValue(
2437224397
return Val;
2437324398
}
2437424399

24375-
if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
24400+
if ((ValueVT.isScalableVector() || ValueVT.isFixedLengthVector()) &&
24401+
PartVT.isScalableVector()) {
2437624402
LLVMContext &Context = *DAG.getContext();
2437724403
SDValue Val = Parts[0];
2437824404
EVT ValueEltVT = ValueVT.getVectorElementType();
2437924405
EVT PartEltVT = PartVT.getVectorElementType();
2438024406
unsigned ValueVTBitSize = ValueVT.getSizeInBits().getKnownMinValue();
24407+
if (ValueVT.isFixedLengthVector())
24408+
ValueVTBitSize = getContainerForFixedLengthVector(ValueVT.getSimpleVT())
24409+
.getSizeInBits()
24410+
.getKnownMinValue();
2438124411
unsigned PartVTBitSize = PartVT.getSizeInBits().getKnownMinValue();
2438224412
if (PartVTBitSize % ValueVTBitSize == 0) {
2438324413
assert(PartVTBitSize >= ValueVTBitSize);

0 commit comments

Comments
 (0)