Skip to content

Commit 8a4257e

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. 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 8a4257e

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)