Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1c8201d

Browse files
committedNov 5, 2024
[RISCV][VLS] Support RISCV VLS calling convention
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. An option `-mriscv-abi-vlen=N` is also added to specify the `ABI_VLEN` globally, it's used for every functions are being compiled, however if both function attribute and option are specified, the function attribute has higher priority than the option which means the function attribute overwrites the `ABI_VLEN` specified by the option. 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.
1 parent bf01bb8 commit 1c8201d

37 files changed

+358
-42
lines changed
 

‎clang/include/clang-c/Index.h

+1
Original file line numberDiff line numberDiff line change
@@ -3013,6 +3013,7 @@ enum CXCallingConv {
30133013
CXCallingConv_M68kRTD = 19,
30143014
CXCallingConv_PreserveNone = 20,
30153015
CXCallingConv_RISCVVectorCall = 21,
3016+
CXCallingConv_RISCVVLSCall = 22,
30163017

30173018
CXCallingConv_Invalid = 100,
30183019
CXCallingConv_Unexposed = 200

‎clang/include/clang/AST/Type.h

+21-5
Original file line numberDiff line numberDiff line change
@@ -1953,7 +1953,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
19531953
/// Extra information which affects how the function is called, like
19541954
/// regparm and the calling convention.
19551955
LLVM_PREFERRED_TYPE(CallingConv)
1956-
unsigned ExtInfo : 13;
1956+
unsigned ExtInfo : 18;
19571957

19581958
/// The ref-qualifier associated with a \c FunctionProtoType.
19591959
///
@@ -4440,6 +4440,8 @@ class FunctionType : public Type {
44404440

44414441
// | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck|cmsenscall|
44424442
// |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 | 12 |
4443+
// |RISCV-ABI-VLEN|
4444+
// |13 .. 17|
44434445
//
44444446
// regparm is either 0 (no regparm attribute) or the regparm value+1.
44454447
enum { CallConvMask = 0x1F };
@@ -4452,23 +4454,25 @@ class FunctionType : public Type {
44524454
};
44534455
enum { NoCfCheckMask = 0x800 };
44544456
enum { CmseNSCallMask = 0x1000 };
4455-
uint16_t Bits = CC_C;
4457+
enum { Log2RISCVABIVLenMask = 0x3E000, Log2RISCVABIVLenOffset = 13 };
4458+
uint32_t Bits = CC_C;
44564459

4457-
ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
4460+
ExtInfo(unsigned Bits) : Bits(static_cast<uint32_t>(Bits)) {}
44584461

44594462
public:
44604463
// Constructor with no defaults. Use this when you know that you
44614464
// have all the elements (when reading an AST file for example).
44624465
ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
44634466
bool producesResult, bool noCallerSavedRegs, bool NoCfCheck,
4464-
bool cmseNSCall) {
4467+
bool cmseNSCall, unsigned Log2RISCVABIVLen) {
44654468
assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
44664469
Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) |
44674470
(producesResult ? ProducesResultMask : 0) |
44684471
(noCallerSavedRegs ? NoCallerSavedRegsMask : 0) |
44694472
(hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) |
44704473
(NoCfCheck ? NoCfCheckMask : 0) |
4471-
(cmseNSCall ? CmseNSCallMask : 0);
4474+
(cmseNSCall ? CmseNSCallMask : 0) |
4475+
(Log2RISCVABIVLen << Log2RISCVABIVLenOffset);
44724476
}
44734477

44744478
// Constructor with all defaults. Use when for example creating a
@@ -4495,6 +4499,10 @@ class FunctionType : public Type {
44954499

44964500
CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
44974501

4502+
unsigned getLog2RISCVABIVLen() const {
4503+
return (Bits & Log2RISCVABIVLenMask) >> Log2RISCVABIVLenOffset;
4504+
}
4505+
44984506
bool operator==(ExtInfo Other) const {
44994507
return Bits == Other.Bits;
45004508
}
@@ -4550,6 +4558,11 @@ class FunctionType : public Type {
45504558
return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc);
45514559
}
45524560

4561+
ExtInfo withLog2RISCVABIVLen(unsigned Log2RISCVABIVLen) const {
4562+
return ExtInfo((Bits & ~Log2RISCVABIVLenMask) |
4563+
(Log2RISCVABIVLen << Log2RISCVABIVLenOffset));
4564+
}
4565+
45534566
void Profile(llvm::FoldingSetNodeID &ID) const {
45544567
ID.AddInteger(Bits);
45554568
}
@@ -4654,6 +4667,9 @@ class FunctionType : public Type {
46544667

46554668
bool getCmseNSCallAttr() const { return getExtInfo().getCmseNSCall(); }
46564669
CallingConv getCallConv() const { return getExtInfo().getCC(); }
4670+
unsigned getLog2RISCVABIVLen() const {
4671+
return getExtInfo().getLog2RISCVABIVLen();
4672+
}
46574673
ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
46584674

46594675
static_assert((~Qualifiers::FastMask & Qualifiers::CVRMask) == 0,

‎clang/include/clang/AST/TypeProperties.td

+5-2
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,17 @@ let Class = FunctionType in {
313313
def : Property<"cmseNSCall", Bool> {
314314
let Read = [{ node->getExtInfo().getCmseNSCall() }];
315315
}
316+
def : Property<"Log2RISCVABIVLen", UInt32> {
317+
let Read = [{ node->getExtInfo().getLog2RISCVABIVLen() }];
318+
}
316319
}
317320

318321
let Class = FunctionNoProtoType in {
319322
def : Creator<[{
320323
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
321324
callingConvention, producesResult,
322325
noCallerSavedRegs, noCfCheck,
323-
cmseNSCall);
326+
cmseNSCall, Log2RISCVABIVLen);
324327
return ctx.getFunctionNoProtoType(returnType, extInfo);
325328
}]>;
326329
}
@@ -363,7 +366,7 @@ let Class = FunctionProtoType in {
363366
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
364367
callingConvention, producesResult,
365368
noCallerSavedRegs, noCfCheck,
366-
cmseNSCall);
369+
cmseNSCall, Log2RISCVABIVLen);
367370
FunctionProtoType::ExtProtoInfo epi;
368371
epi.ExtInfo = extInfo;
369372
epi.Variadic = variadic;

‎clang/include/clang/Basic/Attr.td

+8
Original file line numberDiff line numberDiff line change
@@ -3204,6 +3204,14 @@ def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
32043204
let Documentation = [RISCVVectorCCDocs];
32053205
}
32063206

3207+
def RISCVVLSCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
3208+
let Spellings = [CXX11<"riscv", "vls_cc">,
3209+
C23<"riscv", "vls_cc">,
3210+
Clang<"riscv_vls_cc">];
3211+
let Args = [UnsignedArgument<"VectorWidth", /*opt*/1>];
3212+
let Documentation = [RISCVVLSCCDocs];
3213+
}
3214+
32073215
def Target : InheritableAttr {
32083216
let Spellings = [GCC<"target">];
32093217
let Args = [StringArgument<"featuresStr">];

‎clang/include/clang/Basic/AttrDocs.td

+11
Original file line numberDiff line numberDiff line change
@@ -5645,6 +5645,17 @@ them if they use them.
56455645
}];
56465646
}
56475647

5648+
def RISCVVLSCCDocs : Documentation {
5649+
let Category = DocCatCallingConvs;
5650+
let Heading = "riscv::vls_cc, riscv_vls_cc, clang::riscv_vls_cc";
5651+
let Content = [{
5652+
The ``riscv_vls_cc`` attribute can be applied to a function. Functions
5653+
declared with this attribute will utilize the standard fixed-length vector
5654+
calling convention variant instead of the default calling convention defined by
5655+
the ABI. This variant aims to pass fixed-length vectors via vector registers,
5656+
if possible, rather than through general-purpose registers.}];
5657+
}
5658+
56485659
def PreferredNameDocs : Documentation {
56495660
let Category = DocCatDecl;
56505661
let Content = [{

‎clang/include/clang/Basic/CodeGenOptions.def

+3
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,9 @@ ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind,
464464
/// non-deleting destructors. (No effect on Microsoft ABI.)
465465
CODEGENOPT(CtorDtorReturnThis, 1, 0)
466466

467+
/// Specify the VLEN for VLS calling convention.
468+
CODEGENOPT(RISCVABIVLen, 17, 0)
469+
467470
/// FIXME: Make DebugOptions its own top-level .def file.
468471
#include "DebugOptions.def"
469472

‎clang/include/clang/Basic/Specifiers.h

+1
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ namespace clang {
300300
CC_M68kRTD, // __attribute__((m68k_rtd))
301301
CC_PreserveNone, // __attribute__((preserve_none))
302302
CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
303+
CC_RISCVVLSCall, // __attribute__((riscv_vls_cc))
303304
};
304305

305306
/// Checks whether the given calling convention supports variadic

‎clang/include/clang/CodeGen/CGFunctionInfo.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,9 @@ class CGFunctionInfo final
625625
/// Log 2 of the maximum vector width.
626626
unsigned MaxVectorWidth : 4;
627627

628+
/// Log2 of ABI_VLEN used in RISCV VLS calling convention.
629+
unsigned Log2RISCVABIVLen : 5;
630+
628631
RequiredArgs Required;
629632

630633
/// The struct representing all arguments passed in memory. Only used when
@@ -735,11 +738,13 @@ class CGFunctionInfo final
735738
bool getHasRegParm() const { return HasRegParm; }
736739
unsigned getRegParm() const { return RegParm; }
737740

741+
unsigned getLog2RISCVABIVLen() const { return Log2RISCVABIVLen; }
742+
738743
FunctionType::ExtInfo getExtInfo() const {
739744
return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
740745
getASTCallingConvention(), isReturnsRetained(),
741746
isNoCallerSavedRegs(), isNoCfCheck(),
742-
isCmseNSCall());
747+
isCmseNSCall(), getLog2RISCVABIVLen());
743748
}
744749

745750
CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
@@ -793,6 +798,7 @@ class CGFunctionInfo final
793798
ID.AddInteger(RegParm);
794799
ID.AddBoolean(NoCfCheck);
795800
ID.AddBoolean(CmseNSCall);
801+
ID.AddInteger(Log2RISCVABIVLen);
796802
ID.AddInteger(Required.getOpaqueData());
797803
ID.AddBoolean(HasExtParameterInfos);
798804
if (HasExtParameterInfos) {
@@ -820,6 +826,7 @@ class CGFunctionInfo final
820826
ID.AddInteger(info.getRegParm());
821827
ID.AddBoolean(info.getNoCfCheck());
822828
ID.AddBoolean(info.getCmseNSCall());
829+
ID.AddInteger(info.getLog2RISCVABIVLen());
823830
ID.AddInteger(required.getOpaqueData());
824831
ID.AddBoolean(!paramInfos.empty());
825832
if (!paramInfos.empty()) {

‎clang/include/clang/Driver/Options.td

+4-1
Original file line numberDiff line numberDiff line change
@@ -4950,7 +4950,10 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group<m_Group>,
49504950
!eq(GlobalDocumentation.Program, "Flang") : "",
49514951
true: " The value will be reflected in __riscv_v_fixed_vlen preprocessor define"),
49524952
" (RISC-V only)")>;
4953-
4953+
def mriscv_abi_vlen_EQ : Joined<["-"], "mriscv-abi-vlen=">, Group<m_Group>,
4954+
Visibility<[ClangOption, CC1Option]>,
4955+
HelpText<"Specify the VLEN for VLS calling convention.">,
4956+
MarshallingInfoInt<CodeGenOpts<"RISCVABIVLen">>;
49544957
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>,
49554958
HelpText<"Allow memory accesses to be unaligned (AArch32/MIPSr6 only)">;
49564959
def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_Group>,

‎clang/lib/AST/ASTContext.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -11046,6 +11046,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
1104611046
return {};
1104711047
if (lbaseInfo.getNoCfCheck() != rbaseInfo.getNoCfCheck())
1104811048
return {};
11049+
if (lbaseInfo.getLog2RISCVABIVLen() != rbaseInfo.getLog2RISCVABIVLen())
11050+
return {};
1104911051

1105011052
// When merging declarations, it's common for supplemental information like
1105111053
// attributes to only be present in one of the declarations, and we generally

‎clang/lib/AST/ItaniumMangle.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -3490,6 +3490,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
34903490
case CC_M68kRTD:
34913491
case CC_PreserveNone:
34923492
case CC_RISCVVectorCall:
3493+
case CC_RISCVVLSCall:
34933494
// FIXME: we should be mangling all of the above.
34943495
return "";
34953496

‎clang/lib/AST/Type.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -3529,6 +3529,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
35293529
case CC_PreserveNone: return "preserve_none";
35303530
// clang-format off
35313531
case CC_RISCVVectorCall: return "riscv_vector_cc";
3532+
case CC_RISCVVLSCall: return "riscv_vls_cc";
35323533
// clang-format on
35333534
}
35343535

@@ -4196,6 +4197,7 @@ bool AttributedType::isCallingConv() const {
41964197
case attr::M68kRTD:
41974198
case attr::PreserveNone:
41984199
case attr::RISCVVectorCC:
4200+
case attr::RISCVVLSCC:
41994201
return true;
42004202
}
42014203
llvm_unreachable("invalid attr kind");

‎clang/lib/AST/TypePrinter.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
11351135
case CC_RISCVVectorCall:
11361136
OS << "__attribute__((riscv_vector_cc))";
11371137
break;
1138+
case CC_RISCVVLSCall:
1139+
OS << "__attribute__((riscv_vls_cc))";
1140+
break;
11381141
}
11391142
}
11401143

@@ -2053,6 +2056,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
20532056
case attr::RISCVVectorCC:
20542057
OS << "riscv_vector_cc";
20552058
break;
2059+
case attr::RISCVVLSCC:
2060+
OS << "riscv_vls_cc";
2061+
break;
20562062
case attr::NoDeref:
20572063
OS << "noderef";
20582064
break;

‎clang/lib/Basic/Targets/RISCV.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
483483
return CCCR_Warning;
484484
case CC_C:
485485
case CC_RISCVVectorCall:
486+
case CC_RISCVVLSCall:
486487
return CCCR_OK;
487488
}
488489
}

‎clang/lib/CodeGen/CGCall.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
7777
case CC_PreserveNone: return llvm::CallingConv::PreserveNone;
7878
// clang-format off
7979
case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
80+
case CC_RISCVVLSCall: return llvm::CallingConv::RISCV_VLSCall;
8081
// clang-format on
8182
}
8283
}
@@ -267,6 +268,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
267268
if (D->hasAttr<RISCVVectorCCAttr>())
268269
return CC_RISCVVectorCall;
269270

271+
if (D->hasAttr<RISCVVLSCCAttr>())
272+
return CC_RISCVVLSCall;
273+
270274
return CC_C;
271275
}
272276

@@ -862,6 +866,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod,
862866
FI->HasExtParameterInfos = !paramInfos.empty();
863867
FI->getArgsBuffer()[0].type = resultType;
864868
FI->MaxVectorWidth = 0;
869+
FI->Log2RISCVABIVLen = info.getLog2RISCVABIVLen();
865870
for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
866871
FI->getArgsBuffer()[i + 1].type = argTypes[i];
867872
for (unsigned i = 0, e = paramInfos.size(); i != e; ++i)

‎clang/lib/CodeGen/CGDebugInfo.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,8 @@ static unsigned getDwarfCC(CallingConv CC) {
15951595
return llvm::dwarf::DW_CC_LLVM_PreserveNone;
15961596
case CC_RISCVVectorCall:
15971597
return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
1598+
case CC_RISCVVLSCall:
1599+
return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
15981600
}
15991601
return 0;
16001602
}

‎clang/lib/CodeGen/CodeGenModule.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
234234
else if (ABIStr.ends_with("d"))
235235
ABIFLen = 64;
236236
bool EABI = ABIStr.ends_with("e");
237-
return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
237+
return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen,
238+
CodeGenOpts.RISCVABIVLen, EABI);
238239
}
239240

240241
case llvm::Triple::systemz: {

‎clang/lib/CodeGen/TargetInfo.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ createPPC64_SVR4_TargetCodeGenInfo(CodeGenModule &CGM, PPC64_SVR4_ABIKind Kind,
533533

534534
std::unique_ptr<TargetCodeGenInfo>
535535
createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen, unsigned FLen,
536-
bool EABI);
536+
unsigned ABIVLen, bool EABI);
537537

538538
std::unique_ptr<TargetCodeGenInfo>
539539
createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM);

0 commit comments

Comments
 (0)
Please sign in to comment.