aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
authorBrandon Wu <brandon.wu@sifive.com>2025-03-03 12:39:35 +0800
committerGitHub <noreply@github.com>2025-03-03 12:39:35 +0800
commitc804e86f558a42f328946331af391d700747fa90 (patch)
treecd539e6a9b1029c5cb12bd692a34bc881f1c517a /clang/lib/CodeGen/CGCall.cpp
parent98a640a2faf4d5557e3a949dd87a01ba900745d6 (diff)
downloadllvm-c804e86f558a42f328946331af391d700747fa90.zip
llvm-c804e86f558a42f328946331af391d700747fa90.tar.gz
llvm-c804e86f558a42f328946331af391d700747fa90.tar.bz2
[RISCV][VLS] Support RISCV VLS calling convention (#100346)
This patch adds a function attribute `riscv_vls_cc` for RISCV VLS calling convention which takes 0 or 1 argument, the argument is the `ABI_VLEN` which is the `VLEN` for passing the fixed-vector arguments, it wraps the argument as a scalable vector(VLA) using the `ABI_VLEN` and uses the corresponding mechanism to handle it. The range of `ABI_VLEN` is [32, 65536], if not specified, the default value is 128. Here is an example of VLS argument passing: Non-VLS call: ``` void original_call(__attribute__((vector_size(16))) int arg) {} => define void @original_call(i128 noundef %arg) { entry: ... ret void } ``` VLS call: ``` void __attribute__((riscv_vls_cc(256))) vls_call(__attribute__((vector_size(16))) int arg) {} => define riscv_vls_cc void @vls_call(<vscale x 1 x i32> %arg) { entry: ... ret void } } ``` The first Non-VLS call passes generic vector argument of 16 bytes by flattened integer. On the contrary, the VLS call uses `ABI_VLEN=256` which wraps the vector to <vscale x 1 x i32> where the number of scalable vector elements is calaulated by: `ORIG_ELTS * RVV_BITS_PER_BLOCK / ABI_VLEN`. Note: ORIG_ELTS = Vector Size / Type Size = 128 / 32 = 4. PsABI PR: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/418 C-API PR: https://github.com/riscv-non-isa/riscv-c-api-doc/pull/68
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 916455b..bfcbc27 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -77,6 +77,22 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
// clang-format off
case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
// clang-format on
+#define CC_VLS_CASE(ABI_VLEN) \
+ case CC_RISCVVLSCall_##ABI_VLEN: \
+ return llvm::CallingConv::RISCV_VLSCall_##ABI_VLEN;
+ 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
}
}
@@ -266,6 +282,29 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
if (D->hasAttr<RISCVVectorCCAttr>())
return CC_RISCVVectorCall;
+ if (RISCVVLSCCAttr *PCS = D->getAttr<RISCVVLSCCAttr>()) {
+ switch (PCS->getVectorWidth()) {
+ default:
+ llvm_unreachable("Invalid RISC-V VLS ABI VLEN");
+#define CC_VLS_CASE(ABI_VLEN) \
+ case ABI_VLEN: \
+ return CC_RISCVVLSCall_##ABI_VLEN;
+ 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
+ }
+ }
+
return CC_C;
}
@@ -3234,6 +3273,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
}
}
+ // Struct of fixed-length vectors and struct of array of fixed-length
+ // vector in VLS calling convention are coerced to vector tuple
+ // type(represented as TargetExtType) and scalable vector type
+ // respectively, they're no longer handled as struct.
+ if (ArgI.isDirect() && isa<llvm::StructType>(ConvertType(Ty)) &&
+ (isa<llvm::TargetExtType>(ArgI.getCoerceToType()) ||
+ isa<llvm::ScalableVectorType>(ArgI.getCoerceToType()))) {
+ ArgVals.push_back(ParamValue::forDirect(AI));
+ break;
+ }
+
llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg),