Skip to content

Commit 21b0d42

Browse files
committed
[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). Differential Revision: https://reviews.llvm.org/D154576
1 parent 90c46be commit 21b0d42

File tree

23 files changed

+320
-24
lines changed

23 files changed

+320
-24
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2980,6 +2980,11 @@ def PreserveNone : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86> {
29802980
let Documentation = [PreserveNoneDocs];
29812981
}
29822982

2983+
def RISCVVectorCC: DeclOrTypeAttr {
2984+
let Spellings = [Clang<"riscv_vector_cc">];
2985+
let Documentation = [RISCVVectorCCDocs];
2986+
}
2987+
29832988
def Target : InheritableAttr {
29842989
let Spellings = [GCC<"target">];
29852990
let Args = [StringArgument<"featuresStr">];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5434,6 +5434,16 @@ for clang builtin functions.
54345434
}];
54355435
}
54365436

5437+
def RISCVVectorCCDocs : Documentation {
5438+
let Category = DocCatCallingConvs;
5439+
let Content = [{
5440+
The ``riscv_vector_cc`` attribute can be applied to a function. It preserves 15
5441+
registers namely, v1-v7 and v24-v31 as callee-saved. Callers thus don't need
5442+
to save these registers before function calls, and callees only need to save
5443+
them only if they use them.
5444+
}];
5445+
}
5446+
54375447
def PreferredNameDocs : Documentation {
54385448
let Category = DocCatDecl;
54395449
let Content = [{

clang/include/clang/Basic/Specifiers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ namespace clang {
296296
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
297297
CC_M68kRTD, // __attribute__((m68k_rtd))
298298
CC_PreserveNone, // __attribute__((preserve_none))
299+
CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
299300
};
300301

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

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3444,6 +3444,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
34443444
case CC_PreserveAll:
34453445
case CC_M68kRTD:
34463446
case CC_PreserveNone:
3447+
case CC_RISCVVectorCall:
34473448
// FIXME: we should be mangling all of the above.
34483449
return "";
34493450

clang/lib/AST/Type.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3439,6 +3439,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
34393439
case CC_PreserveAll: return "preserve_all";
34403440
case CC_M68kRTD: return "m68k_rtd";
34413441
case CC_PreserveNone: return "preserve_none";
3442+
case CC_RISCVVectorCall: return "riscv_vector_cc";
34423443
}
34433444

34443445
llvm_unreachable("Invalid calling convention.");
@@ -3992,6 +3993,7 @@ bool AttributedType::isCallingConv() const {
39923993
case attr::PreserveAll:
39933994
case attr::M68kRTD:
39943995
case attr::PreserveNone:
3996+
case attr::RISCVVectorCC:
39953997
return true;
39963998
}
39973999
llvm_unreachable("invalid attr kind");

clang/lib/AST/TypePrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
10701070
case CC_PreserveNone:
10711071
OS << " __attribute__((preserve_none))";
10721072
break;
1073+
case CC_RISCVVectorCall:
1074+
OS << "__attribute__((riscv_vector_cc))";
1075+
break;
10731076
}
10741077
}
10751078

@@ -1917,6 +1920,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
19171920
case attr::PreserveNone:
19181921
OS << "preserve_none";
19191922
break;
1923+
case attr::RISCVVectorCC:
1924+
OS << "riscv_vector_cc";
1925+
break;
19201926
case attr::NoDeref:
19211927
OS << "noderef";
19221928
break;

clang/lib/Basic/Targets/RISCV.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,14 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
467467
}
468468
return Ret;
469469
}
470+
471+
TargetInfo::CallingConvCheckResult
472+
RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
473+
switch (CC) {
474+
default:
475+
return CCCR_Warning;
476+
case CC_C:
477+
case CC_RISCVVectorCall:
478+
return CCCR_OK;
479+
}
480+
}

clang/lib/Basic/Targets/RISCV.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class RISCVTargetInfo : public TargetInfo {
110110

111111
bool hasBFloat16Type() const override { return true; }
112112

113+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
114+
113115
bool useFP16ConversionIntrinsics() const override {
114116
return false;
115117
}

clang/lib/CodeGen/CGCall.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
7474
case CC_SwiftAsync: return llvm::CallingConv::SwiftTail;
7575
case CC_M68kRTD: return llvm::CallingConv::M68k_RTD;
7676
case CC_PreserveNone: return llvm::CallingConv::PreserveNone;
77+
case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
7778
}
7879
}
7980

@@ -260,6 +261,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
260261
if (D->hasAttr<PreserveNoneAttr>())
261262
return CC_PreserveNone;
262263

264+
if (D->hasAttr<RISCVVectorCCAttr>())
265+
return CC_RISCVVectorCall;
266+
263267
return CC_C;
264268
}
265269

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5250,6 +5250,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
52505250
case ParsedAttr::AT_PreserveNone:
52515251
D->addAttr(::new (S.Context) PreserveNoneAttr(S.Context, AL));
52525252
return;
5253+
case ParsedAttr::AT_RISCVVectorCC:
5254+
D->addAttr(::new (S.Context) RISCVVectorCCAttr(S.Context, AL));
5255+
return;
52535256
default:
52545257
llvm_unreachable("unexpected attribute kind");
52555258
}
@@ -5454,6 +5457,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
54545457
case ParsedAttr::AT_PreserveNone:
54555458
CC = CC_PreserveNone;
54565459
break;
5460+
case ParsedAttr::AT_RISCVVectorCC:
5461+
CC = CC_RISCVVectorCall;
5462+
break;
54575463
default: llvm_unreachable("unexpected attribute kind");
54585464
}
54595465

@@ -9573,6 +9579,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
95739579
case ParsedAttr::AT_AMDGPUKernelCall:
95749580
case ParsedAttr::AT_M68kRTD:
95759581
case ParsedAttr::AT_PreserveNone:
9582+
case ParsedAttr::AT_RISCVVectorCC:
95769583
handleCallConvAttr(S, D, AL);
95779584
break;
95789585
case ParsedAttr::AT_Suppress:

clang/lib/Sema/SemaType.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
138138
case ParsedAttr::AT_PreserveMost: \
139139
case ParsedAttr::AT_PreserveAll: \
140140
case ParsedAttr::AT_M68kRTD: \
141-
case ParsedAttr::AT_PreserveNone
141+
case ParsedAttr::AT_PreserveNone: \
142+
case ParsedAttr::AT_RISCVVectorCC
142143

143144
// Function type attributes.
144145
#define FUNCTION_TYPE_ATTRS_CASELIST \
@@ -7922,6 +7923,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
79227923
return createSimpleAttr<M68kRTDAttr>(Ctx, Attr);
79237924
case ParsedAttr::AT_PreserveNone:
79247925
return createSimpleAttr<PreserveNoneAttr>(Ctx, Attr);
7926+
case ParsedAttr::AT_RISCVVectorCC:
7927+
return createSimpleAttr<RISCVVectorCCAttr>(Ctx, Attr);
79257928
}
79267929
llvm_unreachable("unexpected attribute kind!");
79277930
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// REQUIRES: riscv-registered-target
2+
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
3+
// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
4+
5+
#include <riscv_vector.h>
6+
7+
// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar
8+
vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input);
9+
vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
10+
vint32m1_t ret;
11+
vint32m1_t val;
12+
val = __riscv_vle32_v_i32m1(base, vl);
13+
ret = bar(input);
14+
__riscv_vse32_v_i32m1(base, val, vl);
15+
return ret;
16+
}
17+
18+
// CHECK-LLVM: call <vscale x 2 x i32> @baz
19+
vint32m1_t baz(vint32m1_t input);
20+
vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
21+
vint32m1_t ret;
22+
vint32m1_t val;
23+
val = __riscv_vle32_v_i32m1(base, vl);
24+
ret = baz(input);
25+
__riscv_vse32_v_i32m1(base, val, vl);
26+
return ret;
27+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// REQUIRES: riscv-registered-target
2+
// RUN: %clang_cc1 %s -triple riscv64 -target-feature +v -verify
3+
4+
__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}}
5+
6+
__attribute__((riscv_vector_cc)) void func();
7+
__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}}
8+
9+
void test_no_attribute(int); // expected-note {{previous declaration is here}}
10+
void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}}
11+
12+
class test_cc {
13+
__attribute__((riscv_vector_cc)) void member_func();
14+
};
15+
16+
void test_lambda() {
17+
__attribute__((riscv_vector_cc)) auto lambda = []() { // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'auto'}}
18+
};
19+
}

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ enum Kind {
180180
kw_tailcc,
181181
kw_m68k_rtdcc,
182182
kw_graalcc,
183+
kw_riscv_vector_cc,
183184

184185
// Attributes:
185186
kw_attributes,

llvm/include/llvm/IR/CallingConv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ namespace CallingConv {
264264
/// except that the first parameter is mapped to x9.
265265
ARM64EC_Thunk_Native = 109,
266266

267+
/// Calling convention used for RISC-V V-extension.
268+
RISCV_VectorCall = 110,
269+
267270
/// The highest possible ID. Must be some 2^k - 1.
268271
MaxID = 1023
269272
};

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ lltok::Kind LLLexer::LexIdentifier() {
637637
KEYWORD(tailcc);
638638
KEYWORD(m68k_rtdcc);
639639
KEYWORD(graalcc);
640+
KEYWORD(riscv_vector_cc);
640641

641642
KEYWORD(cc);
642643
KEYWORD(c);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) {
21302130
/// ::= 'tailcc'
21312131
/// ::= 'm68k_rtdcc'
21322132
/// ::= 'graalcc'
2133+
/// ::= 'riscv_vector_cc'
21332134
/// ::= 'cc' UINT
21342135
///
21352136
bool LLParser::parseOptionalCallingConv(unsigned &CC) {
@@ -2200,6 +2201,7 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
22002201
case lltok::kw_tailcc: CC = CallingConv::Tail; break;
22012202
case lltok::kw_m68k_rtdcc: CC = CallingConv::M68k_RTD; break;
22022203
case lltok::kw_graalcc: CC = CallingConv::GRAAL; break;
2204+
case lltok::kw_riscv_vector_cc:CC = CallingConv::RISCV_VectorCall; break;
22032205
case lltok::kw_cc: {
22042206
Lex.Lex();
22052207
return parseUInt32(CC);

llvm/lib/IR/AsmWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
363363
case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break;
364364
case CallingConv::AMDGPU_Gfx: Out << "amdgpu_gfx"; break;
365365
case CallingConv::M68k_RTD: Out << "m68k_rtdcc"; break;
366+
case CallingConv::RISCV_VectorCall: Out << "riscv_vector_cc"; break;
366367
}
367368
}
368369

llvm/lib/Target/RISCV/RISCVCallingConv.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ def CSR_ILP32D_LP64D
2626
: CalleeSavedRegs<(add CSR_ILP32_LP64,
2727
F8_D, F9_D, (sequence "F%u_D", 18, 27))>;
2828

29+
defvar CSR_V = (add (sequence "V%u", 1, 7), (sequence "V%u", 24, 31),
30+
V2M2, V4M2, V6M2, V24M2, V26M2, V28M2, V30M2,
31+
V4M4, V24M4, V28M4, V24M8);
32+
33+
def CSR_ILP32_LP64_V
34+
: CalleeSavedRegs<(add CSR_ILP32_LP64, CSR_V)>;
35+
36+
def CSR_ILP32F_LP64F_V
37+
: CalleeSavedRegs<(add CSR_ILP32F_LP64F, CSR_V)>;
38+
39+
def CSR_ILP32D_LP64D_V
40+
: CalleeSavedRegs<(add CSR_ILP32D_LP64D, CSR_V)>;
41+
2942
// Needed for implementation of RISCVRegisterInfo::getNoPreservedMask()
3043
def CSR_NoRegs : CalleeSavedRegs<(add)>;
3144

0 commit comments

Comments
 (0)