Skip to content

[RISCV][VLS] Support RISCV VLS calling convention #100346

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

Merged
merged 12 commits into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 40 additions & 49 deletions clang/lib/CodeGen/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,42 +120,23 @@ void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
default:
ABIVLen = 0;
break;
case CallingConv::CC_RISCVVLSCall_32:
ABIVLen = 32;
break;
case CallingConv::CC_RISCVVLSCall_64:
ABIVLen = 64;
break;
case CallingConv::CC_RISCVVLSCall_128:
ABIVLen = 128;
break;
case CallingConv::CC_RISCVVLSCall_256:
ABIVLen = 256;
break;
case CallingConv::CC_RISCVVLSCall_512:
ABIVLen = 512;
break;
case CallingConv::CC_RISCVVLSCall_1024:
ABIVLen = 1024;
break;
case CallingConv::CC_RISCVVLSCall_2048:
ABIVLen = 2048;
break;
case CallingConv::CC_RISCVVLSCall_4096:
ABIVLen = 4096;
break;
case CallingConv::CC_RISCVVLSCall_8192:
ABIVLen = 8192;
break;
case CallingConv::CC_RISCVVLSCall_16384:
ABIVLen = 16384;
break;
case CallingConv::CC_RISCVVLSCall_32768:
ABIVLen = 32768;
break;
case CallingConv::CC_RISCVVLSCall_65536:
ABIVLen = 65536;
#define CC_VLS_CASE(ABI_VLEN) \
case CallingConv::CC_RISCVVLSCall_##ABI_VLEN: \
ABIVLen = ABI_VLEN; \
break;
CC_VLS_CASE(32)
CC_VLS_CASE(64)
CC_VLS_CASE(128)
CC_VLS_CASE(256)
CC_VLS_CASE(512)
CC_VLS_CASE(1024)
CC_VLS_CASE(2048)
CC_VLS_CASE(4096)
CC_VLS_CASE(8192)
CC_VLS_CASE(16384)
CC_VLS_CASE(32768)
CC_VLS_CASE(65536)
#undef CC_VLS_CASE
}
QualType RetTy = FI.getReturnType();
if (!getCXXABI().classifyReturnType(FI))
Expand Down Expand Up @@ -466,7 +447,7 @@ bool RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty, unsigned ABIVLen,
// Otherwise, pass the struct indirectly.

if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty))) {
int NumElts = STy->getStructNumElements();
unsigned NumElts = STy->getStructNumElements();
if (NumElts > 8)
return false;

Expand Down Expand Up @@ -522,7 +503,7 @@ bool RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty, unsigned ABIVLen,
// Check array of fixed-length vector and turn it into scalable vector type
// if legal.
if (auto *ArrTy = dyn_cast<llvm::ArrayType>(FirstEltTy)) {
int NumArrElt = ArrTy->getNumElements();
unsigned NumArrElt = ArrTy->getNumElements();
if (NumArrElt > 8)
return false;

Expand Down Expand Up @@ -595,17 +576,6 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty, unsigned ABIVLen) const {
// * (RVVBitsPerBlock / EltSize)
ResType = llvm::ScalableVectorType::get(EltType, NumElts / VScale->first);
} else {
// If the corresponding extension is not supported, just make it an i32
// vector.
const TargetInfo &TI = getContext().getTargetInfo();
if ((EltType->isHalfTy() && !TI.hasFeature("zvfhmin")) ||
(EltType->isBFloatTy() && !TI.hasFeature("zvfbfmin")) ||
(EltType->isFloatTy() && !TI.hasFeature("zve32f")) ||
(EltType->isDoubleTy() && !TI.hasFeature("zve64d")) ||
EltType->isIntegerTy(128))
EltType =
llvm::Type::getIntNTy(getVMContext(), EltType->getScalarSizeInBits());

// Check registers needed <= 8.
if ((EltType->getScalarSizeInBits() * NumElts / ABIVLen) > 8)
return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
Expand All @@ -615,6 +585,23 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty, unsigned ABIVLen) const {
ResType = llvm::ScalableVectorType::get(
EltType,
llvm::divideCeil(NumElts * llvm::RISCV::RVVBitsPerBlock, ABIVLen));

// If the corresponding extension is not supported, just make it an i8
// vector with same LMUL.
const TargetInfo &TI = getContext().getTargetInfo();
if ((EltType->isHalfTy() && !TI.hasFeature("zvfhmin")) ||
(EltType->isBFloatTy() && !TI.hasFeature("zvfbfmin")) ||
(EltType->isFloatTy() && !TI.hasFeature("zve32f")) ||
(EltType->isDoubleTy() && !TI.hasFeature("zve64d")) ||
(EltType->isIntegerTy(64) && !TI.hasFeature("zve64x")) ||
EltType->isIntegerTy(128)) {
// The number of elements needs to be at least 1.
ResType = llvm::ScalableVectorType::get(
llvm::Type::getInt8Ty(getVMContext()),
llvm::divideCeil(EltType->getScalarSizeInBits() * NumElts *
llvm::RISCV::RVVBitsPerBlock,
8 * ABIVLen));
}
}

return ABIArgInfo::getDirect(ResType);
Expand Down Expand Up @@ -726,7 +713,11 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
return ABIArgInfo::getDirect();
}

if (const VectorType *VT = Ty->getAs<VectorType>()) {
// TODO: _BitInt is not handled yet in VLS calling convention since _BitInt
// ABI is also not merged yet in RISCV:
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/419
if (const VectorType *VT = Ty->getAs<VectorType>();
VT && !VT->getElementType()->isBitIntType()) {
if (VT->getVectorKind() == VectorKind::RVVFixedLengthData ||
VT->getVectorKind() == VectorKind::RVVFixedLengthMask ||
VT->getVectorKind() == VectorKind::RVVFixedLengthMask_1 ||
Expand Down
14 changes: 10 additions & 4 deletions clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,24 @@ void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen(__attribute__((vect
// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)
[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}

// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 8 x i8> noundef %arg.coerce)
void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}

// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 4 x i16> noundef %arg.coerce)
// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 8 x i8> noundef %arg.coerce)
[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}

// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 8 x i8> noundef %arg.coerce)
void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}

// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 2 x i32> noundef %arg.coerce)
// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 8 x i8> noundef %arg.coerce)
[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}

// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature_no_zve64x(<vscale x 8 x i8> noundef %arg.coerce)
void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature_no_zve64x(__attribute__((vector_size(16))) uint64_t arg) {}

// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature_no_zve64x(<vscale x 8 x i8> noundef %arg.coerce)
[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature_no_zve64x(__attribute__((vector_size(16))) uint64_t arg) {}

// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)
void __attribute__((riscv_vls_cc(256))) test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}

Expand Down
7 changes: 5 additions & 2 deletions clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,15 @@ void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}
// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce)
[[riscv::vls_cc]] void test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}

// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 4 x i16> noundef %arg.coerce)
// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 8 x i8> noundef %arg.coerce)
[[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}

// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 2 x i32> noundef %arg.coerce)
// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 8 x i8> noundef %arg.coerce)
[[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}

// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @_Z55test_vls_default_abi_vlen_unsupported_feature_no_zve64xDv2_m(<vscale x 8 x i8> noundef %arg.coerce)
[[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature_no_zve64x(__attribute__((vector_size(16))) uint64_t arg) {}

// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce)
[[riscv::vls_cc(256)]] void test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}

Expand Down
Loading