Skip to content

Commit

Permalink
RISC-V: Add riscv_vector_cc function attribute
Browse files Browse the repository at this point in the history
Standard vector calling convention variant will only enabled when function
has vector argument or returning value by default, however user may also
want to invoke function without that during a vectorized loop at some situation,
but it will cause a huge performance penalty due to vector register store/restore.

So user can declare function with this riscv_vector_cc attribute like below, that could enforce
function will use standard vector calling convention variant.

void foo() __attribute__((riscv_vector_cc));
[[riscv::vector_cc]] void foo(); // For C++11 and C23

For more details please reference the below link.
riscv-non-isa/riscv-c-api-doc#67

gcc/ChangeLog:

	* config/riscv/riscv.cc (TARGET_GNU_ATTRIBUTES): Add riscv_vector_cc
	attribute to riscv_attribute_table.
	(riscv_vector_cc_function_p): Return true if FUNC is a riscv_vector_cc function.
	(riscv_fntype_abi): Add riscv_vector_cc attribute check.
	* doc/extend.texi: Add riscv_vector_cc attribute description.

gcc/testsuite/ChangeLog:

	* g++.target/riscv/rvv/base/attribute-riscv_vector_cc-error.C: New test.
	* gcc.target/riscv/rvv/base/attribute-riscv_vector_cc-callee-saved.c: New test.
	* gcc.target/riscv/rvv/base/attribute-riscv_vector_cc-error.c: New test.
  • Loading branch information
xuli authored and Liaoshihua committed Mar 11, 2024
1 parent 84b44ce commit 68cd5cb
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 8 deletions.
55 changes: 47 additions & 8 deletions gcc/config/riscv/riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -537,24 +537,52 @@ static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *);

/* Defining target-specific uses of __attribute__. */
TARGET_GNU_ATTRIBUTES (riscv_attribute_table,
static const attribute_spec riscv_gnu_attributes[] =
{
/* Syntax: { name, min_len, max_len, decl_required, type_required,
function_type_required, affects_type_identity, handler,
exclude } */

/* The attribute telling no prologue/epilogue. */
{ "naked", 0, 0, true, false, false, false,
riscv_handle_fndecl_attribute, NULL },
{"naked", 0, 0, true, false, false, false, riscv_handle_fndecl_attribute,
NULL},
/* This attribute generates prologue/epilogue for interrupt handlers. */
{ "interrupt", 0, 1, false, true, true, false,
riscv_handle_type_attribute, NULL },
{"interrupt", 0, 1, false, true, true, false, riscv_handle_type_attribute,
NULL},

/* The following two are used for the built-in properties of the Vector type
and are not used externally */
{"RVV sizeless type", 4, 4, false, true, false, true, NULL, NULL},
{"RVV type", 0, 0, false, true, false, true, NULL, NULL}
});
{"RVV type", 0, 0, false, true, false, true, NULL, NULL},
/* This attribute is used to declare a function, forcing it to use the
standard vector calling convention variant. Syntax:
__attribute__((riscv_vector_cc)). */
{"riscv_vector_cc", 0, 0, false, true, true, true, NULL, NULL}
};

static const scoped_attribute_specs riscv_gnu_attribute_table =
{
"gnu", {riscv_gnu_attributes}
};

static const attribute_spec riscv_attributes[] =
{
/* This attribute is used to declare a function, forcing it to use the
standard vector calling convention variant. Syntax:
[[riscv::vector_cc]]. */
{"vector_cc", 0, 0, false, true, true, true, NULL, NULL}
};

static const scoped_attribute_specs riscv_nongnu_attribute_table =
{
"riscv", {riscv_attributes}
};

static const scoped_attribute_specs *const riscv_attribute_table[] =
{
&riscv_gnu_attribute_table,
&riscv_nongnu_attribute_table
};

/* Order for the CLOBBERs/USEs of gpr_save. */
static const unsigned gpr_save_reg_order[] = {
Expand Down Expand Up @@ -5425,6 +5453,16 @@ riscv_arguments_is_vector_type_p (const_tree fntype)
return false;
}

/* Return true if FUNC is a riscv_vector_cc function.
For more details please reference the below link.
https://github.com/riscv-non-isa/riscv-c-api-doc/pull/67 */
static bool
riscv_vector_cc_function_p (const_tree fntype)
{
return lookup_attribute ("vector_cc", TYPE_ATTRIBUTES (fntype)) != NULL_TREE
|| lookup_attribute ("riscv_vector_cc", TYPE_ATTRIBUTES (fntype)) != NULL_TREE;
}

/* Implement TARGET_FNTYPE_ABI. */

static const predefined_function_abi &
Expand All @@ -5434,7 +5472,8 @@ riscv_fntype_abi (const_tree fntype)
reference the below link.
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/389 */
if (riscv_return_value_is_vector_type_p (fntype)
|| riscv_arguments_is_vector_type_p (fntype))
|| riscv_arguments_is_vector_type_p (fntype)
|| riscv_vector_cc_function_p (fntype))
return riscv_v_abi ();

return default_function_abi;
Expand Down
10 changes: 10 additions & 0 deletions gcc/doc/extend.texi
Original file line number Diff line number Diff line change
Expand Up @@ -6303,6 +6303,16 @@ Permissible values for this parameter are @code{user}, @code{supervisor},
and @code{machine}. If there is no parameter, then it defaults to
@code{machine}.

@cindex @code{riscv_vector_cc} function attribute, RISC-V
@item riscv_vector_cc
Use this attribute to force the function to use the vector calling
convention variant.

@smallexample
void foo() __attribute__((riscv_vector_cc));
[[riscv::vector_cc]] void foo(); // For C++11 and C23
@end smallexample

@end table

The following target-specific function attributes are available for the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* { dg-do compile } */
/* { dg-options "-march=rv64gcv -mabi=lp64d -O1" } */

[[riscv::vector_cc]] void foo();// For C++11 and C23

[[riscv::vector_cc]] int var; /* { dg-warning "'vector_cc' attribute only applies to function types" } */

void __attribute__((riscv_vector_cc)) func();
void __attribute__((riscv_vector_cc(1))) func_invalid(); /* { dg-error "wrong number of arguments specified for 'riscv_vector_cc' attribute" } */

void test_no_attribute(int);
void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { }

class test_cc {
__attribute__((riscv_vector_cc)) void member_func();
};

void test_lambda() {
__attribute__((riscv_vector_cc)) auto lambda = []() { /* { dg-warning "'riscv_vector_cc' attribute only applies to function types" } */
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* { dg-do compile } */
/* { dg-options "-march=rv64gcv -mabi=lp64d" } */

void __attribute__((riscv_vector_cc)) bar1 (int a);
void bar2 ();

void __attribute__((riscv_vector_cc))
foo1 (int a)
{
bar1 (a);
}

void __attribute__((riscv_vector_cc))
foo2 (int a)
{
char data[1024];
bar2 ();
}

void
foo3 (int *a)
{
bar1 (*a);
}

/* { dg-final { scan-assembler-not {\.variant_cc\tbar2} } } */
/* { dg-final { scan-assembler-not {\.variant_cc\tfoo3} } } */
/* { dg-final { scan-assembler-times {\.variant_cc\tbar1} 1 } } */
/* { dg-final { scan-assembler-times {\.variant_cc\tfoo1} 1 } } */
/* { dg-final { scan-assembler-times {\.variant_cc\tfoo2} 1 } } */
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-march=rv64gcv -mabi=lp64d -O1" } */

__attribute__((riscv_vector_cc)) int var; /* { dg-warning "'riscv_vector_cc' attribute only applies to function types" } */
[[riscv::vector_cc]] int var1; /* { dg-warning "'vector_cc' attribute only applies to function types" } */

void __attribute__((riscv_vector_cc)) func();
void __attribute__((riscv_vector_cc(1))) func_invalid(); /* { dg-error "wrong number of arguments specified for 'riscv_vector_cc' attribute" } */

void test_no_attribute(int);
void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { }

0 comments on commit 68cd5cb

Please sign in to comment.