llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-risc-v Author: Brandon Wu (4vtomat) <details> <summary>Changes</summary> [RISCV] RISCV vector calling convention (1/2) This is the vector calling convention based on https://github.com/riscv-non-isa/riscv-elf-psabi-doc, the idea is to split between "scalar" callee-saved registers and "vector" callee-saved registers. "scalar" ones remain the original strategy, however, "vector" ones are handled together with RVV objects. The stack layout would be: |--------------------------| <-- FP | callee-allocated save | | area for register varargs| |--------------------------| | callee-saved registers | <-- scalar callee-saved | (scalar) | |--------------------------| | RVV alignment padding | |--------------------------| | callee-saved registers | <-- vector callee-saved | (vector) | |--------------------------| | RVV objects | |--------------------------| | padding before RVV | |--------------------------| | scalar local variables | |--------------------------| <-- BP | variable size objects | |--------------------------| <-- SP Note: This patch doesn't contain "tuple" type, e.g. vint32m1x2. It will be handled in https://github.com/riscv-non-isa/riscv-elf-psabi-doc (2/2). [RISCV] Add CFI information for vector callee-saved registers Currently the CFI offset for RVV registers are not handled entirely, this patch add those information for either stack unwinding or debugger to work correctly on RVV callee-saved stack object. --- Patch is 176.82 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/77560.diff 137 Files Affected: - (modified) clang/include/clang/Basic/Attr.td (+5) - (modified) clang/include/clang/Basic/AttrDocs.td (+10) - (modified) clang/include/clang/Basic/Specifiers.h (+1) - (modified) clang/lib/AST/ItaniumMangle.cpp (+1) - (modified) clang/lib/AST/Type.cpp (+2) - (modified) clang/lib/AST/TypePrinter.cpp (+6) - (modified) clang/lib/Basic/Targets/RISCV.cpp (+11) - (modified) clang/lib/Basic/Targets/RISCV.h (+2) - (modified) clang/lib/CodeGen/CGCall.cpp (+4) - (modified) clang/lib/Sema/SemaDeclAttr.cpp (+7) - (modified) clang/lib/Sema/SemaType.cpp (+4-1) - (added) clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c (+27) - (added) clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp (+19) - (modified) llvm/include/llvm/AsmParser/LLToken.h (+1) - (modified) llvm/include/llvm/IR/CallingConv.h (+3) - (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) - (modified) llvm/lib/AsmParser/LLParser.cpp (+2) - (modified) llvm/lib/IR/AsmWriter.cpp (+1) - (modified) llvm/lib/Target/RISCV/RISCVCallingConv.td (+13) - (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.cpp (+215-39) - (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.h (+5) - (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+1) - (modified) llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp (+15) - (modified) llvm/test/CodeGen/RISCV/early-clobber-tied-def-subreg-liveness.ll (+1) - (modified) llvm/test/CodeGen/RISCV/intrinsic-cttz-elts-vscale.ll (+1) - (modified) llvm/test/CodeGen/RISCV/regalloc-last-chance-recoloring-failure.ll (+2) - (added) llvm/test/CodeGen/RISCV/rvv-cfi-info.ll (+119) - (modified) llvm/test/CodeGen/RISCV/rvv/abs-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/access-fixed-objects-by-rvv.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/addi-scalable-offset.mir (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/bitreverse-sdnode.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/bitreverse-vp.ll (+7) - (modified) llvm/test/CodeGen/RISCV/rvv/bswap-sdnode.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/bswap-vp.ll (+7) - (added) llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll (+95) - (modified) llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll (+8) - (modified) llvm/test/CodeGen/RISCV/rvv/calling-conv.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/ceil-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/ctlz-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/ctpop-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/cttz-vp.ll (+4) - (modified) llvm/test/CodeGen/RISCV/rvv/emergency-slot.mir (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/extractelt-fp.ll (+4) - (modified) llvm/test/CodeGen/RISCV/rvv/extractelt-int-rv32.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/extractelt-int-rv64.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-bitreverse-vp.ll (+7) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-bswap-vp.ll (+7) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-ceil-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-ctlz-vp.ll (+6) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-ctpop-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-cttz-vp.ll (+6) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-floor-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp-interleave.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fshr-fshl-vp.ll (+126) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert-subvector.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-interleave.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-interleaved-access.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-llrint.ll (+8) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-nearbyint-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-int.ll (+4) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-rint-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-round-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-roundeven-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-roundtozero-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-setcc-fp-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-setcc-int-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-trunc-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vcopysign-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfma-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfmax-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfmin-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfmuladd-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfwadd.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfwmul.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfwsub.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpmerge.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpscatter.ll (+4) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vscale-range.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect-vp.ll (+4) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmul.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulsu.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulu.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/floor-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fmaximum-sdnode.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fminimum-sdnode.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/fpclamptosat_vec.ll (+24) - (modified) llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll (+12) - (modified) llvm/test/CodeGen/RISCV/rvv/get-vlen-debugloc.mir (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/large-rvv-stack-size.mir (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/localvar.ll (+8) - (modified) llvm/test/CodeGen/RISCV/rvv/memory-args.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/mgather-sdnode.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/mscatter-sdnode.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/named-vector-shuffle-reverse.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/nearbyint-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/no-reserved-frame.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/reg-alloc-reserve-bp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/rint-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/round-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/roundeven-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/roundtozero-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/rvv-args-by-mem.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/setcc-fp-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/setcc-int-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/strided-vpstore.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vcopysign-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vector-interleave-store.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vector-interleave.ll (+4) - (modified) llvm/test/CodeGen/RISCV/rvv/vfadd-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfdiv-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfma-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfmadd-constrained-sdnode.ll (+4) - (modified) llvm/test/CodeGen/RISCV/rvv/vfmadd-sdnode.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/vfmax-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfmin-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfmsub-constrained-sdnode.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfmul-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfmuladd-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfnmadd-constrained-sdnode.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfnmsub-constrained-sdnode.ll (+4) - (modified) llvm/test/CodeGen/RISCV/rvv/vfptrunc-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfsub-vp.ll (+2) - (modified) llvm/test/CodeGen/RISCV/rvv/vfwmacc-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vfwnmacc-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vfwnmsac-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vp-reverse-int.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vpmerge-sdnode.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vpscatter-sdnode.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/vpstore.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vselect-fp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll (+3) - (modified) llvm/test/CodeGen/RISCV/rvv/vtrunc-vp.ll (+1) - (modified) llvm/test/CodeGen/RISCV/rvv/zvlsseg-spill.mir (+1) ``````````diff diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index d5eabaad488965..ea9f157df98373 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2891,6 +2891,11 @@ def M68kRTD: DeclOrTypeAttr { let Documentation = [M68kRTDDocs]; } +def RISCVVectorCC: DeclOrTypeAttr { + let Spellings = [Clang<"riscv_vector_cc">]; + let Documentation = [RISCVVectorCCDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 5416a0cbdd0757..75359c65004a97 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5400,6 +5400,16 @@ for clang builtin functions. }]; } +def RISCVVectorCCDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +The ``riscv_vector_cc`` attribute can be applied to a function. It preserves 15 +registers namely, v1-v7 and v24-v31 as callee-saved. Callers thus don't need +to save these registers before function calls, and callees only need to save +them only if they use them. + }]; +} + def PreferredNameDocs : Documentation { let Category = DocCatDecl; let Content = [{ diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 87f29c8ae10bd9..72a10e25c923e9 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -293,6 +293,7 @@ namespace clang { CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) CC_M68kRTD, // __attribute__((m68k_rtd)) + CC_RISCVVectorCall, // __attribute__((riscv_vector_cc)) }; /// Checks whether the given calling convention supports variadic diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index b1678479888eb7..6af83a83c22fc7 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3442,6 +3442,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_PreserveMost: case CC_PreserveAll: case CC_M68kRTD: + case CC_RISCVVectorCall: // FIXME: we should be mangling all of the above. return ""; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index a894d3289eb185..8895a1065d949b 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3409,6 +3409,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_PreserveMost: return "preserve_most"; case CC_PreserveAll: return "preserve_all"; case CC_M68kRTD: return "m68k_rtd"; + case CC_RISCVVectorCall: return "riscv_vector_cc"; } llvm_unreachable("Invalid calling convention."); @@ -3896,6 +3897,7 @@ bool AttributedType::isCallingConv() const { case attr::PreserveMost: case attr::PreserveAll: case attr::M68kRTD: + case attr::RISCVVectorCC: return true; } llvm_unreachable("invalid attr kind"); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index f6941242927367..6138ea47941c7e 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1047,6 +1047,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, case CC_M68kRTD: OS << " __attribute__((m68k_rtd))"; break; + case CC_RISCVVectorCall: + OS << "__attribute__((riscv_vector_cc))"; + break; } } @@ -1885,6 +1888,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::M68kRTD: OS << "m68k_rtd"; break; + case attr::RISCVVectorCC: + OS << "riscv_vector_cc"; + break; case attr::NoDeref: OS << "noderef"; break; diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index daaa8639ae8358..0a5cf09040eedf 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -480,3 +480,14 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { } return Ret; } + +TargetInfo::CallingConvCheckResult +RISCVTargetInfo::checkCallingConvention(CallingConv CC) const { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_RISCVVectorCall: + return CCCR_OK; + } +} diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index f98c88cd45f831..e65a6a1f127e8d 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -110,6 +110,8 @@ class RISCVTargetInfo : public TargetInfo { bool hasBFloat16Type() const override { return true; } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; + bool useFP16ConversionIntrinsics() const override { return false; } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 51a43b5f85b3cc..a099bb0efd73f6 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -73,6 +73,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { case CC_Swift: return llvm::CallingConv::Swift; case CC_SwiftAsync: return llvm::CallingConv::SwiftTail; case CC_M68kRTD: return llvm::CallingConv::M68k_RTD; + case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall; } } @@ -256,6 +257,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D, if (D->hasAttr<M68kRTDAttr>()) return CC_M68kRTD; + if (D->hasAttr<RISCVVectorCCAttr>()) + return CC_RISCVVectorCall; + return CC_C; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d059b406ef86e0..4322d2106737e8 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5235,6 +5235,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { case ParsedAttr::AT_M68kRTD: D->addAttr(::new (S.Context) M68kRTDAttr(S.Context, AL)); return; + case ParsedAttr::AT_RISCVVectorCC: + D->addAttr(::new (S.Context) RISCVVectorCCAttr(S.Context, AL)); + return; default: llvm_unreachable("unexpected attribute kind"); } @@ -5441,6 +5444,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, case ParsedAttr::AT_M68kRTD: CC = CC_M68kRTD; break; + case ParsedAttr::AT_RISCVVectorCC: + CC = CC_RISCVVectorCall; + break; default: llvm_unreachable("unexpected attribute kind"); } @@ -9373,6 +9379,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_AArch64SVEPcs: case ParsedAttr::AT_AMDGPUKernelCall: case ParsedAttr::AT_M68kRTD: + case ParsedAttr::AT_RISCVVectorCC: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index a376f20fa4f4e0..03695c907bdcd5 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -137,7 +137,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, case ParsedAttr::AT_IntelOclBicc: \ case ParsedAttr::AT_PreserveMost: \ case ParsedAttr::AT_PreserveAll: \ - case ParsedAttr::AT_M68kRTD + case ParsedAttr::AT_M68kRTD: \ + case ParsedAttr::AT_RISCVVectorCC // Function type attributes. #define FUNCTION_TYPE_ATTRS_CASELIST \ @@ -7852,6 +7853,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { return createSimpleAttr<PreserveAllAttr>(Ctx, Attr); case ParsedAttr::AT_M68kRTD: return createSimpleAttr<M68kRTDAttr>(Ctx, Attr); + case ParsedAttr::AT_RISCVVectorCC: + return createSimpleAttr<RISCVVectorCCAttr>(Ctx, Attr); } llvm_unreachable("unexpected attribute kind!"); } diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c new file mode 100644 index 00000000000000..a5b59306223dfb --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c @@ -0,0 +1,27 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s + +#include <riscv_vector.h> + +// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar +vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t ret; + vint32m1_t val; + val = __riscv_vle32_v_i32m1(base, vl); + ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call <vscale x 2 x i32> @baz +vint32m1_t baz(vint32m1_t input); +vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t ret; + vint32m1_t val; + val = __riscv_vle32_v_i32m1(base, vl); + ret = baz(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp new file mode 100644 index 00000000000000..22761146093fde --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp @@ -0,0 +1,19 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 %s -triple riscv64 -target-feature +v -verify + +__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}} + +__attribute__((riscv_vector_cc)) void func(); +__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}} + +void test_no_attribute(int); // expected-note {{previous declaration is here}} +void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +class test_cc { + __attribute__((riscv_vector_cc)) void member_func(); +}; + +void test_lambda() { + __attribute__((riscv_vector_cc)) auto lambda = []() { // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'auto'}} + }; +} diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index 147cf56c821aa1..f6c2e7339fb1b2 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -179,6 +179,7 @@ enum Kind { kw_tailcc, kw_m68k_rtdcc, kw_graalcc, + kw_riscv_vector_cc, // Attributes: kw_attributes, diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h index 3a522c239ad59e..f20f2c4ccb781b 100644 --- a/llvm/include/llvm/IR/CallingConv.h +++ b/llvm/include/llvm/IR/CallingConv.h @@ -251,6 +251,9 @@ namespace CallingConv { /// Used by GraalVM. Two additional registers are reserved. GRAAL = 107, + /// Calling convention used for RISC-V V-extension. + RISCV_VectorCall = 108, + /// The highest possible ID. Must be some 2^k - 1. MaxID = 1023 }; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index c8da3efbb68aff..b4ddecf02d265b 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -636,6 +636,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(tailcc); KEYWORD(m68k_rtdcc); KEYWORD(graalcc); + KEYWORD(riscv_vector_cc); KEYWORD(cc); KEYWORD(c); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index fb9e1ba875e1fa..bcdbb75abdd7c0 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -2005,6 +2005,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) { /// ::= 'tailcc' /// ::= 'm68k_rtdcc' /// ::= 'graalcc' +/// ::= 'riscv_vector_cc' /// ::= 'cc' UINT /// bool LLParser::parseOptionalCallingConv(unsigned &CC) { @@ -2074,6 +2075,7 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) { case lltok::kw_tailcc: CC = CallingConv::Tail; break; case lltok::kw_m68k_rtdcc: CC = CallingConv::M68k_RTD; break; case lltok::kw_graalcc: CC = CallingConv::GRAAL; break; + case lltok::kw_riscv_vector_cc:CC = CallingConv::RISCV_VectorCall; break; case lltok::kw_cc: { Lex.Lex(); return parseUInt32(CC); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 278cdfce411050..119092e5c61081 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -362,6 +362,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) { case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break; case CallingConv::AMDGPU_Gfx: Out << "amdgpu_gfx"; break; case CallingConv::M68k_RTD: Out << "m68k_rtdcc"; break; + case CallingConv::RISCV_VectorCall: Out << "riscv_vector_cc"; break; } } diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.td b/llvm/lib/Target/RISCV/RISCVCallingConv.td index 3dd0b372382865..25e54044aa6d61 100644 --- a/llvm/lib/Target/RISCV/RISCVCallingConv.td +++ b/llvm/lib/Target/RISCV/RISCVCallingConv.td @@ -24,6 +24,19 @@ def CSR_ILP32D_LP64D : CalleeSavedRegs<(add CSR_ILP32_LP64, F8_D, F9_D, (sequence "F%u_D", 18, 27))>; +defvar CSR_V = (add (sequence "V%u", 1, 7), (sequence "V%u", 24, 31), + V2M2, V4M2, V6M2, V24M2, V26M2, V28M2, V30M2, + V4M4, V24M4, V28M4, V24M8); + +def CSR_ILP32_LP64_V + : CalleeSavedRegs<(add CSR_ILP32_LP64, CSR_V)>; + +def CSR_ILP32F_LP64F_V + : CalleeSavedRegs<(add CSR_ILP32F_LP64F, CSR_V)>; + +def CSR_ILP32D_LP64D_V + : CalleeSavedRegs<(add CSR_ILP32D_LP64D, CSR_V)>; + // Needed for implementation of RISCVRegisterInfo::getNoPreservedMask() def CSR_NoRegs : CalleeSavedRegs<(add)>; diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 8dfea6d3862057..ae51dbdb92ad3e 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -365,6 +365,21 @@ getUnmanagedCSI(const MachineFunction &MF, return NonLibcallCSI; } +static SmallVector<CalleeSavedInfo, 8> +getRVVCalleeSavedInfo(const MachineFunction &MF, + const std::vector<CalleeSavedInfo> &CSI) { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + SmallVector<CalleeSavedInfo, 8> RVVCSI; + + for (auto &CS : CSI) { + int FI = CS.getFrameIdx(); + if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) + RVVCSI.push_back(CS); + } + + return RVVCSI; +} + void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, @@ -397,6 +412,32 @@ void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF, Flag, getStackAlign()); } +static void appendScalableVectorExpression(SmallVectorImpl<char> &Expr, + int FixedOffset, int ScalableOffset, + unsigned DwarfVlenb, + llvm::raw_string_ostream &Comment) { + uint8_t buffer[16]; + if (FixedOffset) { + Expr.push_back(dwarf::DW_OP_consts); + Expr.append(buffer, buffer + encodeSLEB128(FixedOffset, buffer)); + Expr.push_back((uint8_t)dwarf::DW_OP_plus); + Comment << (FixedOffset < 0 ? " - " : " + ") << std::abs(FixedOffset); + } + + Expr.push_back((uint8_t)dwarf::DW_OP_consts); + Expr.append(buffer, buffer + encodeSLEB128(ScalableOffset, buffer)); + + Expr.push_back((uint8_t)dwarf::DW_OP_bregx); + Expr.append(buffer, buffer + encodeULEB128(DwarfVlenb, buffer)); + Expr.push_back(0); + + Expr.push_back((uint8_t)dwarf::DW_OP_mul); + Expr.push_back((uint8_t)dwarf::DW_OP_plus); + + Comment << (ScalableOffset < 0 ? " - " : " + ") << std::abs(ScalableOffset) + << " * vlenb"; +} + static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, Register Reg, uint64_t FixedOffset, @@ -414,29 +455,40 @@ static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, else Comment << printReg(Reg, &TRI); - uint8_t buffer[16]; - if (FixedOffset) { - Expr.push_back(dwarf::DW_OP_consts); - Expr.append(buffer, buffer + encodeSLEB128(FixedOffset, buffer)); - Expr.push_back((uint8_t)dwarf::DW_OP_plus); - Comment << " + " << FixedOffset; - } + appendScalableVectorExpression( + Expr, FixedOffset, ScalableOffset, + TRI.getDwarfRegNum(RISCV::VLENB, true), Comment); - Expr.push_back((uint8_t)dwarf::DW_OP_consts); - Expr.append(buffer, buffer + encodeSLEB128(ScalableOffset, buffer)); + SmallString<64> DefCfaExpr; + uint8_t buffer[16]; + DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression); + DefCfaExpr.append(buffer, buffer + encodeULEB128(Expr.size(), buffer)); + DefCfaExpr.append(Expr.str()); - unsigned DwarfVlenb = TRI.getDwarfRegNum(RISCV::VLENB, true); - Expr.push_back((uint8_t)dwarf::DW_OP_bregx); - Expr.append(buffer, buffer + encodeULEB128(DwarfVlenb, buffer)); - Expr.push_back(0); + return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(), + Comment.str()); +} - Expr.push_back((uint8_t)dwarf::DW_OP_mul); - Expr.push_back((uint8_t)dwarf::DW_OP_plus); +static MCCFIInstruction createDefCFAOffset(const TargetRegisterInfo &TRI, + Register Reg, + uint64_t FixedOffset, + uint64_t ScalableOffset) { + assert(ScalableOffset != 0 && "Did not need to adjust CFA for RVV"); + SmallString<64> Expr; + std::string CommentBuffer; + llvm::raw_string_ostream Comment(CommentBuffer); + Comment << printReg(Reg, &TRI) << " @ cfa"; - Comment << " + " << ScalableOffset << " * vlenb"; + // Build up the expression (FixedOffset + ScalableOffset * VLENB). + appendScalableVectorExpression( + Expr, FixedOffset, ScalableOffset, + TRI.getDwarfRegNum(RISCV::VLENB, true), Comment); SmallString<64> DefCfaExpr; - DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression); + uint8_t buffer[16]; + unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true); + DefCfaExpr.push_back(dwarf::DW_CFA_expression); + DefCfaExpr.append(buffer, buffer + encodeULEB128(DwarfReg, buffer)); DefCfaExpr.append(buffer, buffer + encodeULEB128(Expr.size(), buffer)); DefCfaExpr.append(Expr.str()); @@ -563,6 +615,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, // directives. for (const auto &Entry : CSI) { int FrameIdx = Entry.getFrameIdx(); + if (FrameIdx >=0 && + MFI.getStackID(FrameIdx) == TargetStackID::ScalableVector) + continue; + int64_t Offset; // Offsets for objects with fixed locations (IE: those saved by libcall) are // simply calculated from the frame index. @@ -638,6 +694,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, .addCFIIndex(CFIIndex) .setMIFlag(MachineInstr::FrameSetup); } + + std::advance(MBBI, getRVVCalleeSavedInfo(MF, CSI).size()); + emitCalleeSavedRVVPrologCFI(MBB, MBBI, hasFP(MF)); } if (hasFP(MF)) { @@ -712,7 +771,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, const auto &CSI = getUnmanagedCSI(MF, MFI.getCalleeSavedInfo()); - // Skip to before the restores of callee-saved registers + // Skip to before the restores of scalar callee-saved registers // FIXME: assumes exactly one instruction is used to restore each // callee-saved register. auto LastFrameDestroy = MBBI; @@ -724,6 +783,9 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize(); uint64_t RVVStackSize = RVFI->getRVVStackSize(); + if (RVVStackSize) + emitCalleeSavedRVVEpilogCFI(MBB, LastFrameDestroy); + // Restore the stack pointer using the value of the frame pointer. Only // necessary if the stack pointer was modified, me... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/77560 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits