Skip to content

Commit 1c8201d

Browse files
committed
[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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 21 additions & 5 deletions
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

Lines changed: 5 additions & 2 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 11 additions & 0 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 8 additions & 1 deletion
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

Lines changed: 4 additions & 1 deletion
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

Lines changed: 2 additions & 0 deletions
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

0 commit comments

Comments
 (0)