From c23c899aedf11069e992eed7358802b262d62f98 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 7 Apr 2020 21:30:12 +0200 Subject: combine: Fix split_i2i3 ICE [PR94291] The following testcase ICEs on armv7hl-linux-gnueabi. try_combine is called on: (gdb) p debug_rtx (i3) (insn 20 12 22 2 (set (mem/c:SI (plus:SI (reg/f:SI 102 sfp) (const_int -4 [0xfffffffffffffffc])) [1 x+0 S4 A32]) (reg:SI 125)) "pr94291.c":7:8 241 {*arm_movsi_insn} (expr_list:REG_DEAD (reg:SI 125) (nil))) (gdb) p debug_rtx (i2) (insn 12 7 20 2 (parallel [ (set (reg:CC 100 cc) (compare:CC (reg:SI 121 [ ]) (const_int 0 [0]))) (set (reg:SI 125) (reg:SI 121 [ ])) ]) "pr94291.c":7:8 248 {*movsi_compare0} (expr_list:REG_UNUSED (reg:CC 100 cc) (nil))) and tries to recognize cc = r121 cmp 0; [sfp-4] = r121 parallel, but that isn't recognized, so it splits it into two: split_i2i3 [sfp-4] = r121 followed by cc = r121 cmp 0 which is recognized, but ICEs because the code below insist that the SET_DEST of newi2pat (or first set in PARALLEL thereof) must be a REG or SUBREG of REG, but it is a MEM in this case. I don't see any condition that would guarantee that, perhaps for the swap_i2i3 case it was somehow guaranteed. As the code just wants to update LOG_LINKS and LOG_LINKS are only for registers, not for MEM or anything else, the patch just doesn't update those if it isn't a REG or SUBREG of REG. 2020-04-07 Jakub Jelinek PR rtl-optimization/94291 PR rtl-optimization/84169 * combine.c (try_combine): For split_i2i3, don't assume SET_DEST must be a REG or SUBREG of REG; if it is not one of these, don't update LOG_LINKs. * gcc.dg/pr94291.c: New test. --- gcc/ChangeLog | 8 ++++++++ gcc/combine.c | 42 +++++++++++++++++++++++------------------- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.dg/pr94291.c | 14 ++++++++++++++ 4 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr94291.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a1ab9fb..12803e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2020-04-07 Jakub Jelinek + + PR rtl-optimization/94291 + PR rtl-optimization/84169 + * combine.c (try_combine): For split_i2i3, don't assume SET_DEST + must be a REG or SUBREG of REG; if it is not one of these, don't + update LOG_LINKs. + 2020-04-07 Richard Biener PR middle-end/94479 diff --git a/gcc/combine.c b/gcc/combine.c index 58366a6..cff76cd 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -4351,25 +4351,29 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, if (GET_CODE (x) == PARALLEL) x = XVECEXP (newi2pat, 0, 0); - /* It can only be a SET of a REG or of a SUBREG of a REG. */ - unsigned int regno = reg_or_subregno (SET_DEST (x)); - - bool done = false; - for (rtx_insn *insn = NEXT_INSN (i3); - !done - && insn - && NONDEBUG_INSN_P (insn) - && BLOCK_FOR_INSN (insn) == this_basic_block; - insn = NEXT_INSN (insn)) - { - struct insn_link *link; - FOR_EACH_LOG_LINK (link, insn) - if (link->insn == i3 && link->regno == regno) - { - link->insn = i2; - done = true; - break; - } + if (REG_P (SET_DEST (x)) + || (GET_CODE (SET_DEST (x)) == SUBREG + && REG_P (SUBREG_REG (SET_DEST (x))))) + { + unsigned int regno = reg_or_subregno (SET_DEST (x)); + + bool done = false; + for (rtx_insn *insn = NEXT_INSN (i3); + !done + && insn + && NONDEBUG_INSN_P (insn) + && BLOCK_FOR_INSN (insn) == this_basic_block; + insn = NEXT_INSN (insn)) + { + struct insn_link *link; + FOR_EACH_LOG_LINK (link, insn) + if (link->insn == i3 && link->regno == regno) + { + link->insn = i2; + done = true; + break; + } + } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 71b5a14..3cbf891 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-07 Jakub Jelinek + + PR rtl-optimization/94291 + PR rtl-optimization/84169 + * gcc.dg/pr94291.c: New test. + 2020-04-07 Richard Biener PR middle-end/94479 diff --git a/gcc/testsuite/gcc.dg/pr94291.c b/gcc/testsuite/gcc.dg/pr94291.c new file mode 100644 index 0000000..7daa2b0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94291.c @@ -0,0 +1,14 @@ +/* PR rtl-optimization/94291 */ +/* { dg-do compile } */ +/* { dg-options "-Og" } */ + +unsigned a; + +unsigned +foo (void) +{ + unsigned x + = (__builtin_sub_overflow ((long long) a, 0, &x) + ? 1 : (__INTPTR_TYPE__) __builtin_memmove (&x, foo, 1)); + return a; +} -- cgit v1.1 From 31449cf8e119bbe172a68689068591827472da5c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 7 Apr 2020 00:22:55 -0400 Subject: c++: ICE on invalid concept placeholder [PR94481]. Here the 'decltype' is missing '(auto)', so open_paren was NULL, and trying to get its location is a SEGV. Using matching_parens avoids that problem. gcc/cp/ChangeLog 2020-04-07 Jason Merrill PR c++/94481 * parser.c (cp_parser_placeholder_type_specifier): Use matching_parens. --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/parser.c | 12 +++++------- gcc/testsuite/g++.dg/cpp2a/concepts-placeholder2.C | 9 +++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder2.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 60d9279..8227f28 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-04-07 Jason Merrill + + PR c++/94481 + * parser.c (cp_parser_placeholder_type_specifier): Use + matching_parens. + 2020-04-07 Iain Sandoe * coroutines.cc (maybe_promote_captured_temps): Ensure that diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index fbcdc9b..2c33ca4 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -18367,7 +18367,7 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, /* As per the standard, require auto or decltype(auto), except in some cases (template parameter lists, -fconcepts-ts enabled). */ - cp_token *placeholder = NULL, *open_paren = NULL, *close_paren = NULL; + cp_token *placeholder = NULL, *close_paren = NULL; if (cxx_dialect >= cxx2a) { if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO)) @@ -18375,12 +18375,10 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DECLTYPE)) { placeholder = cp_lexer_consume_token (parser->lexer); - open_paren = cp_parser_require (parser, CPP_OPEN_PAREN, - RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); cp_parser_require_keyword (parser, RID_AUTO, RT_AUTO); - close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN, - RT_CLOSE_PAREN, - open_paren->location); + close_paren = parens.require_close (parser); } } @@ -18429,7 +18427,7 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, results in an invented template parameter. */ if (parser->auto_is_implicit_function_template_parm_p) { - if (placeholder && token_is_decltype (placeholder)) + if (close_paren) { location_t loc = make_location (placeholder->location, placeholder->location, diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder2.C new file mode 100644 index 0000000..b04354c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder2.C @@ -0,0 +1,9 @@ +// PR c++/94481 +// { dg-do compile { target c++2a } } + +template +concept C = true; + +void foo() { + C decltype c = 1; // { dg-error "" } +} -- cgit v1.1 From 14162197fd4cf0e3a848d32bd9385876e1b1f249 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Tue, 7 Apr 2020 17:55:00 -0600 Subject: Fix a variety of testsuite failures on the H8 after recent cselib changes PR rtl-optimization/92264 * config/h8300/h8300.md (mov;add peephole2): Avoid applying when the destination is the stack pointer. --- gcc/ChangeLog | 6 ++++++ gcc/config/h8300/h8300.md | 1 + 2 files changed, 7 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 12803e9..6f2dcfb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-04-07 Jeff Law + + PR rtl-optimization/92264 + * config/h8300/h8300.md (mov;add peephole2): Avoid applying when + the destination is the stack pointer. + 2020-04-07 Jakub Jelinek PR rtl-optimization/94291 diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index bcc78a4..fdd2d8b 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -4299,6 +4299,7 @@ (plus:SI (match_dup 0) (match_operand:SI 2 "const_int_operand" "")))] "(TARGET_H8300H || TARGET_H8300S) + && operands[0] != stack_pointer_rtx && REG_P (operands[0]) && REG_P (operands[1]) && REGNO (operands[0]) != REGNO (operands[1]) && !satisfies_constraint_L (operands[2]) -- cgit v1.1 From 7e5367f34d7b6fbc0dc4e499653cd3564465f45e Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 8 Apr 2020 00:16:24 +0000 Subject: Daily bump. --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ea8a4ef..24b62cf 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20200407 +20200408 -- cgit v1.1 From 845d451e1f73d8a9a84382c3c6d4fca9c8220403 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 7 Apr 2020 00:45:26 -0400 Subject: c++: requires-expression and tentative parse [PR94480] The problem here was that cp_parser_requires_expression committing to a tentative parse confused cp_parser_decltype_expr, which needs to still be tentative. The only reason to commit here is to get syntax errors within the requires-expression, which we can still do when the commit is firewalled from the enclosing context. gcc/cp/ChangeLog 2020-04-07 Jason Merrill PR c++/94480 * parser.c (cp_parser_requires_expression): Use tentative_firewall. --- gcc/cp/ChangeLog | 3 +++ gcc/cp/parser.c | 3 +++ gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C | 7 +++++++ 3 files changed, 13 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8227f28..31f1fc4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2020-04-07 Jason Merrill + PR c++/94480 + * parser.c (cp_parser_requires_expression): Use tentative_firewall. + PR c++/94481 * parser.c (cp_parser_placeholder_type_specifier): Use matching_parens. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 2c33ca4..a95d431 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -27740,6 +27740,9 @@ cp_parser_requires_expression (cp_parser *parser) gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_REQUIRES)); location_t loc = cp_lexer_consume_token (parser->lexer)->location; + /* Avoid committing to outer tentative parse. */ + tentative_firewall firewall (parser); + /* This is definitely a requires-expression. */ cp_parser_commit_to_tentative_parse (parser); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C new file mode 100644 index 0000000..1d21cce7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C @@ -0,0 +1,7 @@ +// PR c++/94480 +// { dg-do compile { target c++2a } } + +template +constexpr bool is_same_v = __is_same (T, U); + +static_assert(is_same_v); -- cgit v1.1 From 13e41d8b9d3d7598c72c38acc86a3d97046c8373 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Wed, 8 Apr 2020 09:39:43 +0200 Subject: [C/C++, OpenACC] Reject vars of different scope in acc declare (PR94120) gcc/c/ PR middle-end/94120 * c-decl.c (c_check_in_current_scope): New function. * c-tree.h (c_check_in_current_scope): Declare it. * c-parser.c (c_parser_oacc_declare): Add check that variables are declared in the same scope as the directive. Fix handling of namespace vars. gcc/cp/ PR middle-end/94120 * paser.c (cp_parser_oacc_declare): Add check that variables are declared in the same scope as the directive. gcc/testsuite/ PR middle-end/94120 * c-c++-common/goacc/declare-pr94120.c: New. * g++.dg/declare-pr94120.C: New. libgomp/testsuite/ PR middle-end/94120 * libgomp.oacc-c++/declare-pr94120.C: New. --- gcc/c/ChangeLog | 9 +++++++ gcc/c/c-decl.c | 8 ++++++ gcc/c/c-parser.c | 9 +++++++ gcc/c/c-tree.h | 1 + gcc/cp/ChangeLog | 6 +++++ gcc/cp/parser.c | 21 +++++++++++++-- gcc/omp-grid.c | 2 +- gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/c-c++-common/goacc/declare-pr94120.c | 23 +++++++++++++++++ gcc/testsuite/g++.dg/declare-pr94120.C | 30 ++++++++++++++++++++++ 10 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/goacc/declare-pr94120.c create mode 100644 gcc/testsuite/g++.dg/declare-pr94120.C (limited to 'gcc') diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index d30d2b0..482a01b 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,12 @@ +2020-04-08 Tobias Burnus + + PR middle-end/94120 + * c-decl.c (c_check_in_current_scope): New function. + * c-tree.h (c_check_in_current_scope): Declare it. + * c-parser.c (c_parser_oacc_declare): Add check that variables + are declared in the same scope as the directive. Fix handling + of namespace vars. + 2020-04-07 Jakub Jelinek PR c++/94512 diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index b31d99f..0b7f437 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -12041,4 +12041,12 @@ c_check_omp_declare_reduction_r (tree *tp, int *, void *data) return NULL_TREE; } + +bool +c_check_in_current_scope (tree decl) +{ + struct c_binding *b = I_SYMBOL_BINDING (DECL_NAME (decl)); + return b != NULL && B_IN_CURRENT_SCOPE (b); +} + #include "gt-c-c-decl.h" diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 17a28e9..d1c954c 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -16580,6 +16580,15 @@ c_parser_oacc_declare (c_parser *parser) break; } + if (!c_check_in_current_scope (decl)) + { + error_at (loc, + "%qD must be a variable declared in the same scope as " + "%<#pragma acc declare%>", decl); + error = true; + continue; + } + if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)) || lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (decl))) diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 2015827..9466886 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -793,6 +793,7 @@ extern tree c_omp_reduction_id (enum tree_code, tree); extern tree c_omp_reduction_decl (tree); extern tree c_omp_reduction_lookup (tree, tree); extern tree c_check_omp_declare_reduction_r (tree *, int *, void *); +extern bool c_check_in_current_scope (tree); extern void c_pushtag (location_t, tree, tree); extern void c_bind (location_t, tree, bool); extern bool tag_exists_p (enum tree_code, tree); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 31f1fc4..561eb4e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Tobias Burnus + + PR middle-end/94120 + * paser.c (cp_parser_oacc_declare): Add check that variables + are declared in the same scope as the directive. + 2020-04-07 Jason Merrill PR c++/94480 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a95d431..fec5203 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -40906,6 +40906,7 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok) { tree clauses, stmt; bool error = false; + bool found_in_scope = global_bindings_p (); clauses = cp_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK, "#pragma acc declare", pragma_tok, true); @@ -40978,6 +40979,22 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok) break; } + if (!found_in_scope) + for (tree d = current_binding_level->names; d; d = TREE_CHAIN (d)) + if (d == decl) + { + found_in_scope = true; + break; + } + if (!found_in_scope) + { + error_at (loc, + "%qD must be a variable declared in the same scope as " + "%<#pragma acc declare%>", decl); + error = true; + continue; + } + if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)) || lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (decl))) @@ -40999,7 +41016,7 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok) DECL_ATTRIBUTES (decl) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl)); - if (global_bindings_p ()) + if (current_binding_level->kind == sk_namespace) { symtab_node *node = symtab_node::get (decl); if (node != NULL) @@ -41016,7 +41033,7 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok) } } - if (error || global_bindings_p ()) + if (error || current_binding_level->kind == sk_namespace) return NULL_TREE; stmt = make_node (OACC_DECLARE); diff --git a/gcc/omp-grid.c b/gcc/omp-grid.c index b98e45d..ba635fd 100644 --- a/gcc/omp-grid.c +++ b/gcc/omp-grid.c @@ -1065,7 +1065,7 @@ grid_eliminate_combined_simd_part (gomp_for *parloop) while (*pc) { tree c = *pc; - switch (TREE_CODE (c)) + switch (OMP_CLAUSE_CODE (c)) { case OMP_CLAUSE_LINEAR: { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3cbf891..e4e6ecf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Tobias Burnus + + PR middle-end/94120 + * c-c++-common/goacc/declare-pr94120.c: New. + * g++.dg/declare-pr94120.C: New. + 2020-04-07 Jakub Jelinek PR rtl-optimization/94291 diff --git a/gcc/testsuite/c-c++-common/goacc/declare-pr94120.c b/gcc/testsuite/c-c++-common/goacc/declare-pr94120.c new file mode 100644 index 0000000..21b2cc1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/goacc/declare-pr94120.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ + +/* PR middle-end/94120 */ + +void foo() +{ + int foo; + { + #pragma acc declare copy(foo) /* { dg-error "'foo' must be a variable declared in the same scope as '#pragma acc declare'" } */ + } +} + +void +f_data (void) +{ + int B[10]; +#pragma acc data + { +# pragma acc declare copy(B) /* { dg-error "'B' must be a variable declared in the same scope as '#pragma acc declare'" } */ + for (int i = 0; i < 10; i++) + B[i] = -i; + } +} diff --git a/gcc/testsuite/g++.dg/declare-pr94120.C b/gcc/testsuite/g++.dg/declare-pr94120.C new file mode 100644 index 0000000..8515c4f --- /dev/null +++ b/gcc/testsuite/g++.dg/declare-pr94120.C @@ -0,0 +1,30 @@ +/* { dg-do compile } */ + +/* PR middle-end/94120 */ + +int b[8]; +#pragma acc declare create (b) + +namespace my { + int d[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + #pragma acc declare copyin (d) +}; + +namespace outer { + namespace inner { + int e[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + #pragma acc declare copyin (e) + }; +}; + +int f[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; +namespace my { + #pragma acc declare copyin (f) +}; + +namespace outer { + int g[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + namespace inner { + #pragma acc declare copyin (g) + }; +}; -- cgit v1.1 From 54cb3baa82da64608ccb9a85b362b9c119c6247b Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Wed, 8 Apr 2020 10:04:30 +0200 Subject: Undo accidental commit to omp-grid.c The following change accidentally got committed in the previous commit, r10-7614-g13e41d8b9d3d7598c72c38acc86a3d97046c8373, among the intended changes. Hence: Revert: gcc/ * omp-grid.c (grid_eliminate_combined_simd_part): Use OMP_CLAUSE_CODE to access the omp clause code. --- gcc/omp-grid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/omp-grid.c b/gcc/omp-grid.c index ba635fd..b98e45d 100644 --- a/gcc/omp-grid.c +++ b/gcc/omp-grid.c @@ -1065,7 +1065,7 @@ grid_eliminate_combined_simd_part (gomp_for *parloop) while (*pc) { tree c = *pc; - switch (OMP_CLAUSE_CODE (c)) + switch (TREE_CODE (c)) { case OMP_CLAUSE_LINEAR: { -- cgit v1.1 From 4ed1ff7ecbfbaef0a6dfd116f562192f08c50bb7 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Wed, 8 Apr 2020 11:54:29 +0200 Subject: =?UTF-8?q?HSA:=20omp-grid.c=20=E2=80=93=20access=20proper=20claus?= =?UTF-8?q?e=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * omp-grid.c (grid_eliminate_combined_simd_part): Use OMP_CLAUSE_CODE to access the omp clause code. --- gcc/ChangeLog | 5 +++++ gcc/omp-grid.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6f2dcfb..07fff87 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2020-04-08 Tobias Burnus + + * omp-grid.c (grid_eliminate_combined_simd_part): Use + OMP_CLAUSE_CODE to access the omp clause code. + 2020-04-07 Jeff Law PR rtl-optimization/92264 diff --git a/gcc/omp-grid.c b/gcc/omp-grid.c index b98e45d..ba635fd 100644 --- a/gcc/omp-grid.c +++ b/gcc/omp-grid.c @@ -1065,7 +1065,7 @@ grid_eliminate_combined_simd_part (gomp_for *parloop) while (*pc) { tree c = *pc; - switch (TREE_CODE (c)) + switch (OMP_CLAUSE_CODE (c)) { case OMP_CLAUSE_LINEAR: { -- cgit v1.1 From 70b55b25aa14b60f0e0f0193f7178bae756076ad Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Apr 2020 12:04:46 +0200 Subject: postreload: Fix autoinc handling in reload_cse_move2add [PR94516] The following testcase shows two separate issues caused by the cselib changes. One is that through the cselib sp tracking improvements on ... r12 = rsp; rsp -= 8; push cst1; push cst2; push cst3; call rsp += 32; rsp -= 8; push cst4; push cst5; push cst6; call rsp += 32; rsp -= 8; push cst7; push cst8; push cst9; call rsp += 32 reload_cse_simplify_set decides to optimize the rsp += 32 insns into rsp = r12 because cselib figures that the r12 register holds the right value. From the pure cost perspective that seems like a win and on its own at least for -Os that would be beneficial, except that there are those rsp -= 8 stack adjustments after it, where rsp += 32; rsp -= 8; is optimized into rsp += 24; by the csa pass, but rsp = r12; rsp -= 8 can't. Dunno what to do about this part, the PR has a hack in a comment. Anyway, the following patch fixes the other part, which isn't a missed optimization, but a wrong-code issue. The problem is that the pushes of constant are on x86 represented through PRE_MODIFY and while move2add_note_store has some code to handle {PRE,POST}_{INC,DEC} without REG_INC note, it doesn't handle {PRE,POST}_MODIFY (that would be enough to fix this testcase). But additionally it looks misplaced, because move2add_note_store is only called on the rtxes that are stored into, while RTX_AUTOINC can happen not just in those, but anywhere else in the instruction (e.g. pop insn can have autoinc in the SET_SRC MEM). REG_INC note seems to be required for any autoinc except for stack pointer autoinc which doesn't have those notes, so this patch just handles the sp autoinc after the REG_INC note handling loop. 2020-04-08 Jakub Jelinek PR rtl-optimization/94516 * postreload.c: Include rtl-iter.h. (reload_cse_move2add): Handle SP autoinc here by FOR_EACH_SUBRTX_VAR looking for all MEMs with RTX_AUTOINC operand. (move2add_note_store): Remove {PRE,POST}_{INC,DEC} handling. * gcc.dg/torture/pr94516.c: New test. --- gcc/ChangeLog | 8 ++++++++ gcc/postreload.c | 27 ++++++++++++++++----------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr94516.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr94516.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 07fff87..d432912 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2020-04-08 Jakub Jelinek + + PR rtl-optimization/94516 + * postreload.c: Include rtl-iter.h. + (reload_cse_move2add): Handle SP autoinc here by FOR_EACH_SUBRTX_VAR + looking for all MEMs with RTX_AUTOINC operand. + (move2add_note_store): Remove {PRE,POST}_{INC,DEC} handling. + 2020-04-08 Tobias Burnus * omp-grid.c (grid_eliminate_combined_simd_part): Use diff --git a/gcc/postreload.c b/gcc/postreload.c index 7cd5c7f..8849679 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "dbgcnt.h" #include "function-abi.h" +#include "rtl-iter.h" static int reload_cse_noop_set_p (rtx); static bool reload_cse_simplify (rtx_insn *, rtx); @@ -2090,6 +2091,21 @@ reload_cse_move2add (rtx_insn *first) } } } + + /* There are no REG_INC notes for SP autoinc. */ + subrtx_var_iterator::array_type array; + FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (insn), NONCONST) + { + rtx mem = *iter; + if (mem + && MEM_P (mem) + && GET_RTX_CLASS (GET_CODE (XEXP (mem, 0))) == RTX_AUTOINC) + { + if (XEXP (XEXP (mem, 0), 0) == stack_pointer_rtx) + reg_mode[STACK_POINTER_REGNUM] = VOIDmode; + } + } + note_stores (insn, move2add_note_store, insn); /* If INSN is a conditional branch, we try to extract an @@ -2144,17 +2160,6 @@ move2add_note_store (rtx dst, const_rtx set, void *data) unsigned int regno = 0; scalar_int_mode mode; - /* Some targets do argument pushes without adding REG_INC notes. */ - - if (MEM_P (dst)) - { - dst = XEXP (dst, 0); - if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC - || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC) - reg_mode[REGNO (XEXP (dst, 0))] = VOIDmode; - return; - } - if (GET_CODE (dst) == SUBREG) regno = subreg_regno (dst); else if (REG_P (dst)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e4e6ecf..f0d7dae 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-08 Jakub Jelinek + + PR rtl-optimization/94516 + * gcc.dg/torture/pr94516.c: New test. + 2020-04-08 Tobias Burnus PR middle-end/94120 diff --git a/gcc/testsuite/gcc.dg/torture/pr94516.c b/gcc/testsuite/gcc.dg/torture/pr94516.c new file mode 100644 index 0000000..b1b68ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr94516.c @@ -0,0 +1,31 @@ +/* PR rtl-optimization/94516 */ +/* { dg-do run } */ +/* { dg-additional-options "-fpie" { target pie } } */ + +struct S { unsigned char *a; unsigned int b; }; +typedef int V __attribute__((vector_size (sizeof (int) * 4))); + +__attribute__((noipa)) void +foo (const char *a, const char *b, const char *c, const struct S *d, int e, int f, int g, int h, int i) +{ + V v = { 1, 2, 3, 4 }; + asm volatile ("" : : "g" (&v) : "memory"); + v += (V) { 5, 6, 7, 8 }; + asm volatile ("" : : "g" (&v) : "memory"); +} + +__attribute__((noipa)) void +bar (void) +{ + const struct S s = { "foobarbaz", 9 }; + foo ("foo", (const char *) 0, "corge", &s, 0, 1, 0, -12, -31); + foo ("bar", "quux", "qux", &s, 0, 0, 9, 0, 0); + foo ("baz", (const char *) 0, "qux", &s, 1, 0, 0, -12, -32); +} + +int +main () +{ + bar (); + return 0; +} -- cgit v1.1 From 542f73539db1433303a4dd16bd2cfc5e7e12eda8 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 8 Apr 2020 09:09:20 -0300 Subject: update polytypes.c -flax-vector-conversions msg Since commit 2f6d557ff82876432be76b1892c6c3783c0095f4 AKA SVN-r269586, the inform() message suggesting the use of -flax-vector-conversions has had quotes around the option name, but the testcase still expected the message without the quotes. This patch adds to the expected compiler output the quotes that are now issues. for gcc/testsuite/ChangeLog * gcc.target/arm/polytypes.c: Add quotes around -flax-vector-conversions. --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/arm/polytypes.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f0d7dae..3913d21 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-08 Alexandre Oliva + + * gcc.target/arm/polytypes.c: Add quotes around + -flax-vector-conversions. + 2020-04-08 Jakub Jelinek PR rtl-optimization/94516 diff --git a/gcc/testsuite/gcc.target/arm/polytypes.c b/gcc/testsuite/gcc.target/arm/polytypes.c index 110d62a..3753466 100644 --- a/gcc/testsuite/gcc.target/arm/polytypes.c +++ b/gcc/testsuite/gcc.target/arm/polytypes.c @@ -28,7 +28,7 @@ void foo () poly8x16_t v128_8; poly16x8_t v128_16; - s64_8 (v64_8); /* { dg-message "use -flax-vector-conversions" } */ + s64_8 (v64_8); /* { dg-message "use '-flax-vector-conversions'" } */ /* { dg-error "incompatible type for argument 1 of 's64_8'" "" { target *-*-* } .-1 } */ u64_8 (v64_8); /* { dg-error "incompatible type for argument 1 of 'u64_8'" } */ p64_8 (v64_8); -- cgit v1.1 From a6479aa4c0532ee9ad1f098b4e82de9dc684e036 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Tue, 7 Apr 2020 14:24:52 -0400 Subject: c++: ICE with defaulted comparison operator [PR94478] Here we ICE because early_check_defaulted_comparison passed a null ctx to same_type_p. The attached test is ill-formed according to [class.compare.default]/1, so fixed by detecting this case early. PR c++/94478 - ICE with defaulted comparison operator * method.c (early_check_defaulted_comparison): Give an error when the context is null. * g++.dg/cpp2a/spaceship-err4.C: New test. --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/method.c | 11 +++++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C | 7 +++++++ 4 files changed, 29 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 561eb4e..3fb9100 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Marek Polacek + + PR c++/94478 - ICE with defaulted comparison operator + * method.c (early_check_defaulted_comparison): Give an error when the + context is null. + 2020-04-08 Tobias Burnus PR middle-end/94120 diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 41b9ff8..9a21bfc 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1102,6 +1102,17 @@ early_check_defaulted_comparison (tree fn) return false; } + if (!ctx) + { + if (DECL_OVERLOADED_OPERATOR_IS (fn, SPACESHIP_EXPR)) + error_at (loc, "three-way comparison operator can only be defaulted " + "in a class definition"); + else + error_at (loc, "equality comparison operator can only be defaulted " + "in a class definition"); + return false; + } + if (!DECL_OVERLOADED_OPERATOR_IS (fn, SPACESHIP_EXPR) && !same_type_p (TREE_TYPE (TREE_TYPE (fn)), boolean_type_node)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3913d21..278330f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-08 Marek Polacek + + PR c++/94478 - ICE with defaulted comparison operator + * g++.dg/cpp2a/spaceship-err4.C: New test. + 2020-04-08 Alexandre Oliva * gcc.target/arm/polytypes.c: Add quotes around diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C new file mode 100644 index 0000000..00f90ce --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C @@ -0,0 +1,7 @@ +// PR c++/94478 - ICE with defaulted comparison operator. +// { dg-do compile { target c++2a } } + +struct B {}; +bool operator!=(const B&, const B&) = default; // { dg-error "equality comparison operator can only be defaulted in a class definition" } +bool operator==(const B&, const B&) = default; // { dg-error "equality comparison operator can only be defaulted in a class definition" } +bool operator<=>(const B&, const B&) = default; // { dg-error "three-way comparison operator can only be defaulted in a class definition" } -- cgit v1.1 From 4cf6b06cb5b02c053738e2975e3b7a4b3c577401 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Apr 2020 15:30:16 +0200 Subject: c++: Further fix for -fsanitize=vptr [PR94325] For -fsanitize=vptr, we insert a NULL store into the vptr instead of just adding a CLOBBER of this. build_clobber_this makes the CLOBBER conditional on in_charge (implicit) parameter whenever CLASSTYPE_VBASECLASSES, but when adding this conditionalization to the -fsanitize=vptr code in PR87095, I wanted it to catch some more cases when the class has CLASSTYPE_VBASECLASSES, but the vptr is still not shared with something else, otherwise the sanitization would be less effective. The following testcase shows that the chosen test that CLASSTYPE_PRIMARY_BINFO is non-NULL and has BINFO_VIRTUAL_P set wasn't sufficient, the D class has still sizeof(D) == sizeof(void*) and thus contains just a single vptr, but while in B::~B() this results in the vptr not being cleared, in C::~C() this condition isn't true, as CLASSTYPE_PRIMARY_BINFO in that case is B and is not BINFO_VIRTUAL_P, so it clears the vptr, but the D::~D() dtor after invoking C::~C() invokes A::~A() with an already cleared vptr, which is then reported. The following patch is just a shot in the dark, keep looking through CLASSTYPE_PRIMARY_BINFO until we find BINFO_VIRTUAL_P, but it works on the existing testcase as well as this new one. 2020-04-08 Jakub Jelinek PR c++/94325 * decl.c (begin_destructor_body): For CLASSTYPE_VBASECLASSES class dtors, if CLASSTYPE_PRIMARY_BINFO is non-NULL, but not BINFO_VIRTUAL_P, look at CLASSTYPE_PRIMARY_BINFO of its BINFO_TYPE if it is not BINFO_VIRTUAL_P, and so on. * g++.dg/ubsan/vptr-15.C: New test. --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/decl.c | 20 +++++++++++++------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/ubsan/vptr-15.C | 14 ++++++++++++++ 4 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ubsan/vptr-15.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3fb9100..23fb6ad 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2020-04-08 Jakub Jelinek + + PR c++/94325 + * decl.c (begin_destructor_body): For CLASSTYPE_VBASECLASSES class + dtors, if CLASSTYPE_PRIMARY_BINFO is non-NULL, but not BINFO_VIRTUAL_P, + look at CLASSTYPE_PRIMARY_BINFO of its BINFO_TYPE if it is not + BINFO_VIRTUAL_P, and so on. + 2020-04-08 Marek Polacek PR c++/94478 - ICE with defaulted comparison operator diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a127734..0ea4b320 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -16663,14 +16663,20 @@ begin_destructor_body (void) /* If the vptr is shared with some virtual nearly empty base, don't clear it if not in charge, the dtor of the virtual nearly empty base will do that later. */ - if (CLASSTYPE_VBASECLASSES (current_class_type) - && CLASSTYPE_PRIMARY_BINFO (current_class_type) - && BINFO_VIRTUAL_P - (CLASSTYPE_PRIMARY_BINFO (current_class_type))) + if (CLASSTYPE_VBASECLASSES (current_class_type)) { - stmt = convert_to_void (stmt, ICV_STATEMENT, - tf_warning_or_error); - stmt = build_if_in_charge (stmt); + tree c = current_class_type; + while (CLASSTYPE_PRIMARY_BINFO (c)) + { + if (BINFO_VIRTUAL_P (CLASSTYPE_PRIMARY_BINFO (c))) + { + stmt = convert_to_void (stmt, ICV_STATEMENT, + tf_warning_or_error); + stmt = build_if_in_charge (stmt); + break; + } + c = BINFO_TYPE (CLASSTYPE_PRIMARY_BINFO (c)); + } } finish_decl_cleanup (NULL_TREE, stmt); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 278330f..9627b29 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-08 Jakub Jelinek + + PR c++/94325 + * g++.dg/ubsan/vptr-15.C: New test. + 2020-04-08 Marek Polacek PR c++/94478 - ICE with defaulted comparison operator diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-15.C b/gcc/testsuite/g++.dg/ubsan/vptr-15.C new file mode 100644 index 0000000..f6f36a5 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/vptr-15.C @@ -0,0 +1,14 @@ +// PR c++/94325 +// { dg-do run { target c++11 } } +// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" } + +struct A { virtual ~A () = default; }; +struct B : public virtual A {}; +struct C : public B {}; +struct D : public C {}; + +int +main () +{ + D a; +} -- cgit v1.1 From 975e6670c428b032aa6ec600f57082d3cfb57393 Mon Sep 17 00:00:00 2001 From: Dennis Zhang Date: Wed, 8 Apr 2020 15:06:31 +0100 Subject: arm: CLI for Custom Datapath Extension (CDE) This patch is part of a series that adds support for the Arm Custom Datapath Extension. It defines the options cdecp0-cdecp7 for CLI to enable the CDE on corresponding coprocessor 0-7. It also adds new target supports for CDE feature testsuite. gcc/ChangeLog: 2020-04-08 Dennis Zhang * config.gcc: Add arm_cde.h. * config/arm/arm-c.c (arm_cpu_builtins): Define or undefine __ARM_FEATURE_CDE and __ARM_FEATURE_CDE_COPROC. * config/arm/arm-cpus.in (cdecp0, cdecp1, ..., cdecp7): New options. * config/arm/arm.c (arm_option_reconfigure_globals): Configure arm_arch_cde and arm_arch_cde_coproc to store the feature bits. * config/arm/arm.h (TARGET_CDE): New macro. * config/arm/arm_cde.h: New file. * doc/invoke.texi: Document CDE options +cdecp[0-7]. * doc/sourcebuild.texi (arm_v8m_main_cde_ok): Document new target supports option. (arm_v8m_main_cde_fp, arm_v8_1m_main_cde_mve): Likewise. gcc/testsuite/ChangeLog: 2020-04-08 Dennis Zhang * gcc.target/arm/pragma_cde.c: New test. * lib/target-supports.exp (arm_v8m_main_cde_ok): New target support option. (arm_v8m_main_cde_fp, arm_v8_1m_main_cde_mve): Likewise. --- gcc/ChangeLog | 15 +++++ gcc/config.gcc | 2 +- gcc/config/arm/arm-c.c | 6 ++ gcc/config/arm/arm-cpus.in | 26 ++++++++ gcc/config/arm/arm.c | 22 +++++++ gcc/config/arm/arm.h | 8 +++ gcc/config/arm/arm_cde.h | 40 +++++++++++++ gcc/doc/invoke.texi | 8 +++ gcc/doc/sourcebuild.texi | 15 +++++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.target/arm/pragma_cde.c | 98 +++++++++++++++++++++++++++++++ gcc/testsuite/lib/target-supports.exp | 59 +++++++++++++++++++ 12 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 gcc/config/arm/arm_cde.h create mode 100644 gcc/testsuite/gcc.target/arm/pragma_cde.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d432912..ff5c1c5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2020-04-08 Dennis Zhang + + * config.gcc: Add arm_cde.h. + * config/arm/arm-c.c (arm_cpu_builtins): Define or undefine + __ARM_FEATURE_CDE and __ARM_FEATURE_CDE_COPROC. + * config/arm/arm-cpus.in (cdecp0, cdecp1, ..., cdecp7): New options. + * config/arm/arm.c (arm_option_reconfigure_globals): Configure + arm_arch_cde and arm_arch_cde_coproc to store the feature bits. + * config/arm/arm.h (TARGET_CDE): New macro. + * config/arm/arm_cde.h: New file. + * doc/invoke.texi: Document CDE options +cdecp[0-7]. + * doc/sourcebuild.texi (arm_v8m_main_cde_ok): Document new target + supports option. + (arm_v8m_main_cde_fp, arm_v8_1m_main_cde_mve): Likewise. + 2020-04-08 Jakub Jelinek PR rtl-optimization/94516 diff --git a/gcc/config.gcc b/gcc/config.gcc index 13e3cb7..7624c65 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -346,7 +346,7 @@ arc*-*-*) arm*-*-*) cpu_type=arm extra_objs="arm-builtins.o aarch-common.o" - extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve.h" + extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve.h arm_cde.h" target_type_format_char='%' c_target_objs="arm-c.o" cxx_target_objs="arm-c.o" diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c index 73bdb9c..7e92e8a 100644 --- a/gcc/config/arm/arm-c.c +++ b/gcc/config/arm/arm-c.c @@ -237,6 +237,12 @@ arm_cpu_builtins (struct cpp_reader* pfile) builtin_define_with_int_value ("__ARM_FEATURE_COPROC", coproc_level); } + def_or_undef_macro (pfile, "__ARM_FEATURE_CDE", TARGET_CDE); + cpp_undef (pfile, "__ARM_FEATURE_CDE_COPROC"); + if (TARGET_CDE) + builtin_define_with_int_value ("__ARM_FEATURE_CDE_COPROC", + arm_arch_cde_coproc); + def_or_undef_macro (pfile, "__ARM_FEATURE_MATMUL_INT8", TARGET_I8MM); def_or_undef_macro (pfile, "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", TARGET_BF16_FP); diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in index 77b4309..fba34e5 100644 --- a/gcc/config/arm/arm-cpus.in +++ b/gcc/config/arm/arm-cpus.in @@ -211,6 +211,16 @@ define feature i8mm # Brain half-precision floating-point extension. Optional from v8.2-A. define feature bf16 +# Arm Custom Datapath Extension (CDE). +define feature cdecp0 +define feature cdecp1 +define feature cdecp2 +define feature cdecp3 +define feature cdecp4 +define feature cdecp5 +define feature cdecp6 +define feature cdecp7 + # Feature groups. Conventionally all (or mostly) upper case. # ALL_FPU lists all the feature bits associated with the floating-point # unit; these will all be removed if the floating-point unit is disabled @@ -676,6 +686,14 @@ begin arch armv8-m.main option fp.dp add FPv5 FP_DBL option nofp remove ALL_FP option nodsp remove armv7em + option cdecp0 add cdecp0 + option cdecp1 add cdecp1 + option cdecp2 add cdecp2 + option cdecp3 add cdecp3 + option cdecp4 add cdecp4 + option cdecp5 add cdecp5 + option cdecp6 add cdecp6 + option cdecp7 add cdecp7 end arch armv8-m.main begin arch armv8-r @@ -707,6 +725,14 @@ begin arch armv8.1-m.main option nofp remove ALL_FP option mve add MVE option mve.fp add MVE_FP + option cdecp0 add cdecp0 + option cdecp1 add cdecp1 + option cdecp2 add cdecp2 + option cdecp3 add cdecp3 + option cdecp4 add cdecp4 + option cdecp5 add cdecp5 + option cdecp6 add cdecp6 + option cdecp7 add cdecp7 end arch armv8.1-m.main begin arch iwmmxt diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index cd0a49c..da0bfbc 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1021,6 +1021,13 @@ int arm_arch_i8mm = 0; /* Nonzero if chip supports the BFloat16 instructions. */ int arm_arch_bf16 = 0; +/* Nonzero if chip supports the Custom Datapath Extension. */ +int arm_arch_cde = 0; +int arm_arch_cde_coproc = 0; +const int arm_arch_cde_coproc_bits[] = { + 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 +}; + /* The condition codes of the ARM, and the inverse function. */ static const char * const arm_condition_codes[] = { @@ -3740,6 +3747,21 @@ arm_option_reconfigure_globals (void) arm_fp16_format = ARM_FP16_FORMAT_IEEE; } + arm_arch_cde = 0; + arm_arch_cde_coproc = 0; + int cde_bits[] = {isa_bit_cdecp0, isa_bit_cdecp1, isa_bit_cdecp2, + isa_bit_cdecp3, isa_bit_cdecp4, isa_bit_cdecp5, + isa_bit_cdecp6, isa_bit_cdecp7}; + for (int i = 0, e = ARRAY_SIZE (cde_bits); i < e; i++) + { + int cde_bit = bitmap_bit_p (arm_active_target.isa, cde_bits[i]); + if (cde_bit) + { + arm_arch_cde |= cde_bit; + arm_arch_cde_coproc |= arm_arch_cde_coproc_bits[i]; + } + } + /* And finally, set up some quirks. */ arm_arch_no_volatile_ce = bitmap_bit_p (arm_active_target.isa, isa_bit_quirk_no_volatile_ce); diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index fb55f73..343235d 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -354,6 +354,9 @@ emission of floating point pcs attributes. */ /* Nonzero if disallow volatile memory access in IT block. */ #define TARGET_NO_VOLATILE_CE (arm_arch_no_volatile_ce) +/* Nonzero if chip supports the Custom Datapath Extension. */ +#define TARGET_CDE (arm_arch_cde && arm_arch8 && !arm_arch_notm) + /* Should constant I be slplit for OP. */ #define DONT_EARLY_SPLIT_CONSTANT(i, op) \ ((optimize >= 2) \ @@ -568,6 +571,11 @@ extern int arm_arch_i8mm; /* Nonzero if chip supports the BFloat16 instructions. */ extern int arm_arch_bf16; +/* Nonzero if chip supports the Custom Datapath Extension. */ +extern int arm_arch_cde; +extern int arm_arch_cde_coproc; +extern const int arm_arch_cde_coproc_bits[]; + #ifndef TARGET_DEFAULT #define TARGET_DEFAULT (MASK_APCS_FRAME) #endif diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h new file mode 100644 index 0000000..f975754 --- /dev/null +++ b/gcc/config/arm/arm_cde.h @@ -0,0 +1,40 @@ +/* Arm Custom Datapath Extension (CDE) intrinsics include file. + + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by Arm Ltd. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _GCC_ARM_CDE_H +#define _GCC_ARM_CDE_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index e3e652f..be7b5bb 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -18679,6 +18679,10 @@ The single- and double-precision floating-point instructions. @item +nofp Disable the floating-point extension. + +@item +cdecp0, +cdecp1, ... , +cdecp7 +Enable the Custom Datapath Extension (CDE) on selected coprocessors according +to the numbers given in the options in the range 0 to 7. @end table @item armv8-m.main @@ -18697,6 +18701,10 @@ The single- and double-precision floating-point instructions. @item +nofp Disable the floating-point extension. + +@item +cdecp0, +cdecp1, ... , +cdecp7 +Enable the Custom Datapath Extension (CDE) on selected coprocessors according +to the numbers given in the options in the range 0 to 7. @end table @item armv8-r diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 91b46cc..26a57e3 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1904,6 +1904,21 @@ ARM target supports options to generate instructions from ARMv8.1-M with the M-Profile Vector Extension (MVE). Some multilibs may be incompatible with these options. +@item arm_v8m_main_cde +ARM target supports options to generate instructions from ARMv8-M with +the Custom Datapath Extension (CDE). Some multilibs may be incompatible +with these options. + +@item arm_v8m_main_cde_fp +ARM target supports options to generate instructions from ARMv8-M with +the Custom Datapath Extension (CDE) and floating-point (VFP). +Some multilibs may be incompatible with these options. + +@item arm_v8_1m_main_cde_mve +ARM target supports options to generate instructions from ARMv8.1-M with +the Custom Datapath Extension (CDE) and M-Profile Vector Extension (MVE). +Some multilibs may be incompatible with these options. + @item arm_prefer_ldrd_strd ARM target prefers @code{LDRD} and @code{STRD} instructions over @code{LDM} and @code{STM} instructions. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9627b29..c69c8ce 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-04-08 Dennis Zhang + + * gcc.target/arm/pragma_cde.c: New test. + * lib/target-supports.exp (arm_v8m_main_cde_ok): New target support + option. + (arm_v8m_main_cde_fp, arm_v8_1m_main_cde_mve): Likewise. + 2020-04-08 Jakub Jelinek PR c++/94325 diff --git a/gcc/testsuite/gcc.target/arm/pragma_cde.c b/gcc/testsuite/gcc.target/arm/pragma_cde.c new file mode 100644 index 0000000..b66e22d --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pragma_cde.c @@ -0,0 +1,98 @@ +/* Test for CDE #pragma target macros. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8m_main_cde_ok } */ +/* { dg-add-options arm_v8m_main_cde } */ + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main") +#ifdef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is defined but should not be" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp0") +#ifndef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is not defined but should be" +#endif +#if __ARM_FEATURE_CDE_COPROC != 0x1 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp1") +#ifndef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is not defined but should be" +#endif +#if __ARM_FEATURE_CDE_COPROC != 0x2 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp2") +#ifndef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is not defined but should be" +#endif +#if __ARM_FEATURE_CDE_COPROC != 0x4 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp3") +#ifndef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is not defined but should be" +#endif +#if __ARM_FEATURE_CDE_COPROC != 0x8 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp4") +#ifndef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is not defined but should be" +#endif +#if __ARM_FEATURE_CDE_COPROC != 0x10 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp5") +#ifndef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is not defined but should be" +#endif +#if __ARM_FEATURE_CDE_COPROC != 0x20 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp6") +#ifndef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is not defined but should be" +#endif +#if __ARM_FEATURE_CDE_COPROC != 0x40 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp7") +#ifndef __ARM_FEATURE_CDE +#error "__ARM_FEATURE_CDE is not defined but should be" +#endif +#if __ARM_FEATURE_CDE_COPROC != 0x80 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp0+cdecp1") +#if __ARM_FEATURE_CDE_COPROC != 0x3 +#error "__ARM_FEATURE_CDE_COPROC is not defined as configured" +#endif +#pragma GCC pop_options diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 0dfe3ae..050b4ba 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -5103,6 +5103,65 @@ proc add_options_for_arm_v8_2a_bf16_neon { flags } { return "$flags $et_arm_v8_2a_bf16_neon_flags" } +# A series of routines are created to 1) check if a given architecture is +# effective (check_effective_target_*_ok) and then 2) give the corresponding +# flags that enable the architecture (add_options_for_*). +# The series includes: +# arm_v8m_main_cde: Armv8-m CDE (Custom Datapath Extension). +# arm_v8m_main_cde_fp: Armv8-m CDE with FP registers. +# arm_v8_1m_main_cde_mve: Armv8.1-m CDE with MVE. +# Usage: +# /* { dg-require-effective-target arm_v8m_main_cde_ok } */ +# /* { dg-add-options arm_v8m_main_cde } */ +# The tests are valid for Arm. + +foreach { armfunc armflag armdef } { + arm_v8m_main_cde + "-march=armv8-m.main+cdecp0 -mthumb" + "defined (__ARM_FEATURE_CDE)" + arm_v8m_main_cde_fp + "-march=armv8-m.main+fp+cdecp0 -mthumb" + "defined (__ARM_FEATURE_CDE) && defined (__ARM_FP)" + arm_v8_1m_main_cde_mve + "-march=armv8.1-m.main+mve+cdecp0 -mthumb" + "defined (__ARM_FEATURE_CDE) && defined (__ARM_FEATURE_MVE)" + } { + eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef ] { + proc check_effective_target_FUNC_ok_nocache { } { + global et_FUNC_flags + set et_FUNC_flags "" + + if { ![istarget arm*-*-*] } { + return 0; + } + + if { [check_no_compiler_messages_nocache FUNC_ok assembly { + #if !(DEF) + #error "DEF failed" + #endif + } "FLAG"] } { + set et_FUNC_flags "FLAG" + return 1 + } + + return 0; + } + + proc check_effective_target_FUNC_ok { } { + return [check_cached_effective_target FUNC_ok \ + check_effective_target_FUNC_ok_nocache] + } + + proc add_options_for_FUNC { flags } { + if { ! [check_effective_target_FUNC_ok] } { + return "$flags" + } + global et_FUNC_flags + return "$flags $et_FUNC_flags" + } + }] +} + # Return 1 if the target supports executing ARMv8 NEON instructions, 0 # otherwise. -- cgit v1.1 From 12f55e030ed068d5c7b14c65a74d102db925dab2 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Mon, 30 Mar 2020 19:55:03 -0400 Subject: c++: Function type and parameter type disagreements [PR92010] This resolves parts of Core issues 1001/1322 by rebuilding the function type of an instantiated function template in terms of its formal parameter types whenever the original function type and formal parameter types disagree about the type of a parameter after substitution. gcc/cp/ChangeLog: Core issues 1001 and 1322 PR c++/92010 * pt.c (rebuild_function_or_method_type): Split function out from ... (tsubst_function_type): ... here. (maybe_rebuild_function_decl_type): New function. (tsubst_function_decl): Use it. gcc/testsuite/ChangeLog: Core issues 1001 and 1322 PR c++/92010 * g++.dg/cpp2a/lambda-uneval11.c: New test. * g++.dg/template/array33.C: New test. * g++.dg/template/array34.C: New test. * g++.dg/template/defarg22.C: New test. --- gcc/cp/ChangeLog | 9 ++ gcc/cp/pt.c | 151 ++++++++++++++++++++------- gcc/testsuite/ChangeLog | 9 ++ gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C | 10 ++ gcc/testsuite/g++.dg/template/array33.C | 63 +++++++++++ gcc/testsuite/g++.dg/template/array34.C | 63 +++++++++++ gcc/testsuite/g++.dg/template/defarg22.C | 13 +++ 7 files changed, 281 insertions(+), 37 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C create mode 100644 gcc/testsuite/g++.dg/template/array33.C create mode 100644 gcc/testsuite/g++.dg/template/array34.C create mode 100644 gcc/testsuite/g++.dg/template/defarg22.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 23fb6ad..cedd157 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2020-04-08 Patrick Palka + + Core issues 1001 and 1322 + PR c++/92010 + * pt.c (rebuild_function_or_method_type): Split function out from ... + (tsubst_function_type): ... here. + (maybe_rebuild_function_decl_type): New function. + (tsubst_function_decl): Use it. + 2020-04-08 Jakub Jelinek PR c++/94325 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6122227..256a937 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13475,6 +13475,116 @@ lookup_explicit_specifier (tree v) return *explicit_specifier_map->get (v); } +/* Given T, a FUNCTION_TYPE or METHOD_TYPE, construct and return a corresponding + FUNCTION_TYPE or METHOD_TYPE whose return type is RETURN_TYPE, argument types + are ARG_TYPES, and exception specification is RAISES, and otherwise is + identical to T. */ + +static tree +rebuild_function_or_method_type (tree t, tree return_type, tree arg_types, + tree raises, tsubst_flags_t complain) +{ + gcc_assert (FUNC_OR_METHOD_TYPE_P (t)); + + tree new_type; + if (TREE_CODE (t) == FUNCTION_TYPE) + { + new_type = build_function_type (return_type, arg_types); + new_type = apply_memfn_quals (new_type, type_memfn_quals (t)); + } + else + { + tree r = TREE_TYPE (TREE_VALUE (arg_types)); + /* Don't pick up extra function qualifiers from the basetype. */ + r = cp_build_qualified_type_real (r, type_memfn_quals (t), complain); + if (! MAYBE_CLASS_TYPE_P (r)) + { + /* [temp.deduct] + + Type deduction may fail for any of the following + reasons: + + -- Attempting to create "pointer to member of T" when T + is not a class type. */ + if (complain & tf_error) + error ("creating pointer to member function of non-class type %qT", + r); + return error_mark_node; + } + + new_type = build_method_type_directly (r, return_type, + TREE_CHAIN (arg_types)); + } + new_type = cp_build_type_attribute_variant (new_type, TYPE_ATTRIBUTES (t)); + + cp_ref_qualifier rqual = type_memfn_rqual (t); + bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (t); + return build_cp_fntype_variant (new_type, rqual, raises, late_return_type_p); +} + +/* Check if the function type of DECL, a FUNCTION_DECL, agrees with the type of + each of its formal parameters. If there is a disagreement then rebuild + DECL's function type according to its formal parameter types, as part of a + resolution for Core issues 1001/1322. */ + +static void +maybe_rebuild_function_decl_type (tree decl) +{ + bool function_type_needs_rebuilding = false; + if (tree parm_list = FUNCTION_FIRST_USER_PARM (decl)) + { + tree parm_type_list = FUNCTION_FIRST_USER_PARMTYPE (decl); + while (parm_type_list && parm_type_list != void_list_node) + { + tree parm_type = TREE_VALUE (parm_type_list); + tree formal_parm_type_unqual = strip_top_quals (TREE_TYPE (parm_list)); + if (!same_type_p (parm_type, formal_parm_type_unqual)) + { + function_type_needs_rebuilding = true; + break; + } + + parm_list = DECL_CHAIN (parm_list); + parm_type_list = TREE_CHAIN (parm_type_list); + } + } + + if (!function_type_needs_rebuilding) + return; + + const tree fntype = TREE_TYPE (decl); + tree parm_list = DECL_ARGUMENTS (decl); + tree old_parm_type_list = TYPE_ARG_TYPES (fntype); + tree new_parm_type_list = NULL_TREE; + tree *q = &new_parm_type_list; + for (int skip = num_artificial_parms_for (decl); skip > 0; skip--) + { + *q = copy_node (old_parm_type_list); + parm_list = DECL_CHAIN (parm_list); + old_parm_type_list = TREE_CHAIN (old_parm_type_list); + q = &TREE_CHAIN (*q); + } + while (old_parm_type_list && old_parm_type_list != void_list_node) + { + *q = copy_node (old_parm_type_list); + tree *new_parm_type = &TREE_VALUE (*q); + tree formal_parm_type_unqual = strip_top_quals (TREE_TYPE (parm_list)); + if (!same_type_p (*new_parm_type, formal_parm_type_unqual)) + *new_parm_type = formal_parm_type_unqual; + + parm_list = DECL_CHAIN (parm_list); + old_parm_type_list = TREE_CHAIN (old_parm_type_list); + q = &TREE_CHAIN (*q); + } + if (old_parm_type_list == void_list_node) + *q = void_list_node; + + TREE_TYPE (decl) + = rebuild_function_or_method_type (fntype, + TREE_TYPE (fntype), new_parm_type_list, + TYPE_RAISES_EXCEPTIONS (fntype), tf_none); +} + /* Subroutine of tsubst_decl for the case when T is a FUNCTION_DECL. */ static tree @@ -13665,6 +13775,8 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, DECL_ARGUMENTS (r) = parms; DECL_RESULT (r) = NULL_TREE; + maybe_rebuild_function_decl_type (r); + TREE_STATIC (r) = 0; TREE_PUBLIC (r) = TREE_PUBLIC (t); DECL_EXTERNAL (r) = 1; @@ -14694,7 +14806,6 @@ tsubst_function_type (tree t, { tree return_type; tree arg_types = NULL_TREE; - tree fntype; /* The TYPE_CONTEXT is not used for function/method types. */ gcc_assert (TYPE_CONTEXT (t) == NULL_TREE); @@ -14765,42 +14876,8 @@ tsubst_function_type (tree t, } /* Construct a new type node and return it. */ - if (TREE_CODE (t) == FUNCTION_TYPE) - { - fntype = build_function_type (return_type, arg_types); - fntype = apply_memfn_quals (fntype, type_memfn_quals (t)); - } - else - { - tree r = TREE_TYPE (TREE_VALUE (arg_types)); - /* Don't pick up extra function qualifiers from the basetype. */ - r = cp_build_qualified_type_real (r, type_memfn_quals (t), complain); - if (! MAYBE_CLASS_TYPE_P (r)) - { - /* [temp.deduct] - - Type deduction may fail for any of the following - reasons: - - -- Attempting to create "pointer to member of T" when T - is not a class type. */ - if (complain & tf_error) - error ("creating pointer to member function of non-class type %qT", - r); - return error_mark_node; - } - - fntype = build_method_type_directly (r, return_type, - TREE_CHAIN (arg_types)); - } - fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t)); - - /* See comment above. */ - tree raises = NULL_TREE; - cp_ref_qualifier rqual = type_memfn_rqual (t); - fntype = build_cp_fntype_variant (fntype, rqual, raises, late_return_type_p); - - return fntype; + return rebuild_function_or_method_type (t, return_type, arg_types, + /*raises=*/NULL_TREE, complain); } /* FNTYPE is a FUNCTION_TYPE or METHOD_TYPE. Substitute the template diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c69c8ce..40597ed 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2020-04-08 Patrick Palka + + Core issues 1001 and 1322 + PR c++/92010 + * g++.dg/cpp2a/lambda-uneval11.c: New test. + * g++.dg/template/array33.C: New test. + * g++.dg/template/array34.C: New test. + * g++.dg/template/defarg22.C: New test. + 2020-04-08 Dennis Zhang * gcc.target/arm/pragma_cde.c: New test. diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C new file mode 100644 index 0000000..a042624 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval11.C @@ -0,0 +1,10 @@ +// PR c++/92010 +// { dg-do compile { target c++2a } } + +template void spam(decltype([]{}) (*s)[sizeof(T)] = nullptr) +{ } + +void foo() +{ + spam(); +} diff --git a/gcc/testsuite/g++.dg/template/array33.C b/gcc/testsuite/g++.dg/template/array33.C new file mode 100644 index 0000000..0aa5873 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/array33.C @@ -0,0 +1,63 @@ +// Verify that top-level cv-qualifiers on parameter types are considered +// when determining the function type of an instantiated function template. +// This resolves a part of Core issues 1001/1322. +// { dg-do compile } +// { dg-additional-options "-Wno-volatile" } + +template +void foo0(T t = 0); + +template +void foo1(const T = 0); + +template +void foo2(volatile T t = 0); + +template +void foo3(const volatile T t = 0); + +#if __cplusplus >= 201103L +#define SA(X) static_assert(X,#X) +SA(__is_same(decltype(foo0), void(char*))); +SA(__is_same(decltype(foo0), void(const char*))); +SA(__is_same(decltype(foo0), void(volatile char*))); +SA(__is_same(decltype(foo0), void(const volatile char*))); + +SA(__is_same(decltype(foo1), void(const char*))); +SA(__is_same(decltype(foo1), void(const char*))); +SA(__is_same(decltype(foo1), void(const volatile char*))); +SA(__is_same(decltype(foo1), void(const volatile char*))); + +SA(__is_same(decltype(foo2), void(volatile char*))); +SA(__is_same(decltype(foo2), void(const volatile char*))); +SA(__is_same(decltype(foo2), void(volatile char*))); +SA(__is_same(decltype(foo2), void(const volatile char*))); + +SA(__is_same(decltype(foo3), void(const volatile char*))); +SA(__is_same(decltype(foo3), void(const volatile char*))); +SA(__is_same(decltype(foo3), void(const volatile char*))); +SA(__is_same(decltype(foo3), void(const volatile char*))); +#endif + +int main() +{ + foo0(); + foo0(); + foo0(); + foo0(); + + foo1(); + foo1(); + foo1(); + foo1(); + + foo2(); + foo2(); + foo2(); + foo2(); + + foo3(); + foo3(); + foo3(); + foo3(); +} diff --git a/gcc/testsuite/g++.dg/template/array34.C b/gcc/testsuite/g++.dg/template/array34.C new file mode 100644 index 0000000..38c0640 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/array34.C @@ -0,0 +1,63 @@ +// Verify that top-level cv-qualifiers on parameter types are considered +// when determining the function type of an instantiated function template. +// This resolves a part of Core issues 1001/1322. +// { dg-do compile { target c++11 } } +// { dg-additional-options "-Wno-volatile" } + +template +void foo0(Ts... t); + +template +void foo1(const Ts... t); + +template +void foo2(volatile Ts... t); + +template +void foo3(const volatile Ts... t); + +#if __cplusplus >= 201103L +#define SA(X) static_assert(X,#X) +SA(__is_same(decltype(foo0), void(char*))); +SA(__is_same(decltype(foo0), void(const char*))); +SA(__is_same(decltype(foo0), void(volatile char*))); +SA(__is_same(decltype(foo0), void(const volatile char*))); + +SA(__is_same(decltype(foo1), void(const char*))); +SA(__is_same(decltype(foo1), void(const char*))); +SA(__is_same(decltype(foo1), void(const volatile char*))); +SA(__is_same(decltype(foo1), void(const volatile char*))); + +SA(__is_same(decltype(foo2), void(volatile char*))); +SA(__is_same(decltype(foo2), void(const volatile char*))); +SA(__is_same(decltype(foo2), void(volatile char*))); +SA(__is_same(decltype(foo2), void(const volatile char*))); + +SA(__is_same(decltype(foo3), void(const volatile char*))); +SA(__is_same(decltype(foo3), void(const volatile char*))); +SA(__is_same(decltype(foo3), void(const volatile char*))); +SA(__is_same(decltype(foo3), void(const volatile char*))); +#endif + +int main() +{ + foo0(0); + foo0(0); + foo0(0); + foo0(0); + + foo1(0); + foo1(0); + foo1(0); + foo1(0); + + foo2(0); + foo2(0); + foo2(0); + foo2(0); + + foo3(0); + foo3(0); + foo3(0); + foo3(0); +} diff --git a/gcc/testsuite/g++.dg/template/defarg22.C b/gcc/testsuite/g++.dg/template/defarg22.C new file mode 100644 index 0000000..599061c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/defarg22.C @@ -0,0 +1,13 @@ +// PR c++/92010 +// { dg-do compile { target c++11 } } + +template +void foo(const T t = "; ") +{ +} + +int main() +{ + foo (); +} + -- cgit v1.1 From 07b9bfd02b88cad2f6b3f50ad610dd75cb989ed3 Mon Sep 17 00:00:00 2001 From: Dennis Zhang Date: Wed, 8 Apr 2020 15:33:40 +0100 Subject: arm: CDE intrinsics using FPU/MVE S/D registers This patch enables the ACLE intrinsics calling VCX1, VCX2, and VCX3 instructions who work with FPU/MVE 32-bit/64-bit registers. This patch also enables DImode for VFP to support CDE with FPU. gcc/ChangeLog: 2020-04-08 Dennis Zhang Matthew Malcomson * config/arm/arm-builtins.c (CX_IMM_QUALIFIERS): New macro. (CX_UNARY_QUALIFIERS, CX_BINARY_QUALIFIERS): Likewise. (CX_TERNARY_QUALIFIERS): Likewise. (ARM_BUILTIN_CDE_PATTERN_START): Likewise. (ARM_BUILTIN_CDE_PATTERN_END): Likewise. (arm_init_acle_builtins): Initialize CDE builtins. (arm_expand_acle_builtin): Check CDE constant operands. * config/arm/arm.h (ARM_CDE_CONST_COPROC): New macro to set the range of CDE constant operand. * config/arm/arm.c (arm_hard_regno_mode_ok): Support DImode for TARGET_VFP_BASE. (ARM_VCDE_CONST_1, ARM_VCDE_CONST_2, ARM_VCDE_CONST_3): Likewise. * config/arm/arm_cde.h (__arm_vcx1_u32): New macro of ACLE interface. (__arm_vcx1a_u32, __arm_vcx2_u32, __arm_vcx2a_u32): Likewise. (__arm_vcx3_u32, __arm_vcx3a_u32, __arm_vcx1d_u64): Likewise. (__arm_vcx1da_u64, __arm_vcx2d_u64, __arm_vcx2da_u64): Likewise. (__arm_vcx3d_u64, __arm_vcx3da_u64): Likewise. * config/arm/arm_cde_builtins.def: New file. * config/arm/iterators.md (V_reg): New attribute of SI. * config/arm/predicates.md (const_int_coproc_operand): New. (const_int_vcde1_operand, const_int_vcde2_operand): New. (const_int_vcde3_operand): New. * config/arm/unspecs.md (UNSPEC_VCDE, UNSPEC_VCDEA): New. * config/arm/vfp.md (arm_vcx1): New entry. (arm_vcx1a, arm_vcx2, arm_vcx2a): Likewise. (arm_vcx3, arm_vcx3a): Likewise. gcc/testsuite/ChangeLog: 2020-04-08 Dennis Zhang * gcc.target/arm/acle/cde_v_1.c: New test. * gcc.target/arm/acle/cde_v_1_err.c: New test. * gcc.target/arm/acle/cde_v_1_mve.c: New test. --- gcc/ChangeLog | 30 ++++++ gcc/config/arm/arm-builtins.c | 99 +++++++++++++++++- gcc/config/arm/arm.c | 2 +- gcc/config/arm/arm.h | 4 + gcc/config/arm/arm_cde.h | 71 +++++++++++++ gcc/config/arm/arm_cde_builtins.def | 33 ++++++ gcc/config/arm/iterators.md | 2 +- gcc/config/arm/predicates.md | 17 ++++ gcc/config/arm/unspecs.md | 2 + gcc/config/arm/vfp.md | 71 +++++++++++++ gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.target/arm/acle/cde_v_1.c | 94 ++++++++++++++++++ gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c | 127 ++++++++++++++++++++++++ gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c | 56 +++++++++++ 14 files changed, 609 insertions(+), 5 deletions(-) create mode 100644 gcc/config/arm/arm_cde_builtins.def create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde_v_1.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff5c1c5..ffd4679 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,34 @@ 2020-04-08 Dennis Zhang + Matthew Malcomson + + * config/arm/arm-builtins.c (CX_IMM_QUALIFIERS): New macro. + (CX_UNARY_QUALIFIERS, CX_BINARY_QUALIFIERS): Likewise. + (CX_TERNARY_QUALIFIERS): Likewise. + (ARM_BUILTIN_CDE_PATTERN_START): Likewise. + (ARM_BUILTIN_CDE_PATTERN_END): Likewise. + (arm_init_acle_builtins): Initialize CDE builtins. + (arm_expand_acle_builtin): Check CDE constant operands. + * config/arm/arm.h (ARM_CDE_CONST_COPROC): New macro to set the range + of CDE constant operand. + * config/arm/arm.c (arm_hard_regno_mode_ok): Support DImode for + TARGET_VFP_BASE. + (ARM_VCDE_CONST_1, ARM_VCDE_CONST_2, ARM_VCDE_CONST_3): Likewise. + * config/arm/arm_cde.h (__arm_vcx1_u32): New macro of ACLE interface. + (__arm_vcx1a_u32, __arm_vcx2_u32, __arm_vcx2a_u32): Likewise. + (__arm_vcx3_u32, __arm_vcx3a_u32, __arm_vcx1d_u64): Likewise. + (__arm_vcx1da_u64, __arm_vcx2d_u64, __arm_vcx2da_u64): Likewise. + (__arm_vcx3d_u64, __arm_vcx3da_u64): Likewise. + * config/arm/arm_cde_builtins.def: New file. + * config/arm/iterators.md (V_reg): New attribute of SI. + * config/arm/predicates.md (const_int_coproc_operand): New. + (const_int_vcde1_operand, const_int_vcde2_operand): New. + (const_int_vcde3_operand): New. + * config/arm/unspecs.md (UNSPEC_VCDE, UNSPEC_VCDEA): New. + * config/arm/vfp.md (arm_vcx1): New entry. + (arm_vcx1a, arm_vcx2, arm_vcx2a): Likewise. + (arm_vcx3, arm_vcx3a): Likewise. + +2020-04-08 Dennis Zhang * config.gcc: Add arm_cde.h. * config/arm/arm-c.c (arm_cpu_builtins): Define or undefine diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index 832b910..a8bad7b 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -305,6 +305,35 @@ arm_mrrc_qualifiers[SIMD_MAX_BUILTIN_ARGS] #define MRRC_QUALIFIERS \ (arm_mrrc_qualifiers) +/* T (immediate, unsigned immediate). */ +static enum arm_type_qualifiers +arm_cx_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_immediate, qualifier_unsigned_immediate }; +#define CX_IMM_QUALIFIERS (arm_cx_imm_qualifiers) + +/* T (immediate, T, unsigned immediate). */ +static enum arm_type_qualifiers +arm_cx_unary_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_immediate, qualifier_none, + qualifier_unsigned_immediate }; +#define CX_UNARY_QUALIFIERS (arm_cx_unary_qualifiers) + +/* T (immediate, T, T, unsigned immediate). */ +static enum arm_type_qualifiers +arm_cx_binary_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_immediate, + qualifier_none, qualifier_none, + qualifier_unsigned_immediate }; +#define CX_BINARY_QUALIFIERS (arm_cx_binary_qualifiers) + +/* T (immediate, T, T, T, unsigned immediate). */ +static enum arm_type_qualifiers +arm_cx_ternary_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_immediate, + qualifier_none, qualifier_none, qualifier_none, + qualifier_unsigned_immediate }; +#define CX_TERNARY_QUALIFIERS (arm_cx_ternary_qualifiers) + /* The first argument (return type) of a store should be void type, which we represent with qualifier_void. Their first operand will be a DImode pointer to the location to store to, so we must use @@ -928,7 +957,23 @@ static arm_builtin_datum acle_builtin_data[] = }; #undef VAR1 +/* IMM_MAX sets the maximum valid value of the CDE immediate operand. + ECF_FLAG sets the flag used for set_call_expr_flags. */ +#define VAR1(T, N, A, IMM_MAX, ECF_FLAG) \ + {{#N #A, UP (A), CODE_FOR_arm_##N##A, 0, T##_QUALIFIERS}, IMM_MAX, ECF_FLAG}, + +typedef struct { + arm_builtin_datum base; + unsigned int imm_max; + int ecf_flag; +} arm_builtin_cde_datum; + +static arm_builtin_cde_datum cde_builtin_data[] = +{ +#include "arm_cde_builtins.def" +}; +#undef VAR1 #define VAR1(T, N, X) \ ARM_BUILTIN_NEON_##N##X, @@ -1224,6 +1269,14 @@ enum arm_builtins #include "arm_acle_builtins.def" +#undef VAR1 +#define VAR1(T, N, X, ... ) \ + ARM_BUILTIN_##N##X, + + ARM_BUILTIN_CDE_BASE, + +#include "arm_cde_builtins.def" + ARM_BUILTIN_MVE_BASE, #undef VAR1 @@ -1246,6 +1299,12 @@ enum arm_builtins #define ARM_BUILTIN_ACLE_PATTERN_START \ (ARM_BUILTIN_ACLE_BASE + 1) +#define ARM_BUILTIN_CDE_PATTERN_START \ + (ARM_BUILTIN_CDE_BASE + 1) + +#define ARM_BUILTIN_CDE_PATTERN_END \ + (ARM_BUILTIN_CDE_BASE + ARRAY_SIZE (cde_builtin_data)) + #undef CF #undef VAR1 #undef VAR2 @@ -1774,6 +1833,15 @@ arm_init_acle_builtins (void) arm_builtin_datum *d = &acle_builtin_data[i]; arm_init_builtin (fcode, d, "__builtin_arm"); } + + fcode = ARM_BUILTIN_CDE_PATTERN_START; + for (i = 0; i < ARRAY_SIZE (cde_builtin_data); i++, fcode++) + { + arm_builtin_cde_datum *cde = &cde_builtin_data[i]; + arm_builtin_datum *d = &cde->base; + arm_init_builtin (fcode, d, "__builtin_arm"); + set_call_expr_flags (arm_builtin_decls[fcode], cde->ecf_flag); + } } /* Set up all the MVE builtins mentioned in arm_mve_builtins.def file. */ @@ -2966,8 +3034,29 @@ constant_arg: if (!(*insn_data[icode].operand[opno].predicate) (op[argc], mode[argc])) { - error ("%Kargument %d must be a constant immediate", - exp, argc + 1); + if (IN_RANGE (fcode, ARM_BUILTIN_CDE_PATTERN_START, + ARM_BUILTIN_CDE_PATTERN_END)) + { + if (argc == 0) + { + unsigned int cp_bit = UINTVAL (op[argc]); + if (IN_RANGE (cp_bit, 0, ARM_CDE_CONST_COPROC)) + error ("%Kcoprocessor %d is not enabled " + "with +cdecp%d", exp, cp_bit, cp_bit); + else + error ("%Kcoproc must be a constant immediate in " + "range [0-%d] enabled with +cdecp", exp, + ARM_CDE_CONST_COPROC); + } + else + error ("%Kargument %d must be a constant immediate " + "in range [0-%d]", exp, argc + 1, + cde_builtin_data[fcode - + ARM_BUILTIN_CDE_PATTERN_START].imm_max); + } + else + error ("%Kargument %d must be a constant immediate", + exp, argc + 1); /* We have failed to expand the pattern, and are safely in to invalid code. But the mid-end will still try to build an assignment for this node while it expands, @@ -3192,8 +3281,12 @@ arm_expand_acle_builtin (int fcode, tree exp, rtx target) /* Don't generate any RTL. */ return const0_rtx; } + + gcc_assert (fcode != ARM_BUILTIN_CDE_BASE); arm_builtin_datum *d - = &acle_builtin_data[fcode - ARM_BUILTIN_ACLE_PATTERN_START]; + = (fcode < ARM_BUILTIN_CDE_BASE) + ? &acle_builtin_data[fcode - ARM_BUILTIN_ACLE_PATTERN_START] + : &cde_builtin_data[fcode - ARM_BUILTIN_CDE_PATTERN_START].base; return arm_expand_builtin_1 (fcode, exp, target, d); } diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index da0bfbc..4dada07 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -25013,7 +25013,7 @@ arm_hard_regno_mode_ok (unsigned int regno, machine_mode mode) if (TARGET_VFP_BASE && IS_VFP_REGNUM (regno)) { - if (mode == DFmode) + if (mode == DFmode || mode == DImode) return VFP_REGNO_OK_FOR_DOUBLE (regno); if (mode == HFmode || mode == BFmode || mode == HImode diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 343235d..ca36a74 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -575,6 +575,10 @@ extern int arm_arch_bf16; extern int arm_arch_cde; extern int arm_arch_cde_coproc; extern const int arm_arch_cde_coproc_bits[]; +#define ARM_CDE_CONST_COPROC 7 +#define ARM_VCDE_CONST_1 ((1 << 11) - 1) +#define ARM_VCDE_CONST_2 ((1 << 6 ) - 1) +#define ARM_VCDE_CONST_3 ((1 << 3 ) - 1) #ifndef TARGET_DEFAULT #define TARGET_DEFAULT (MASK_APCS_FRAME) diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h index f975754..4c9f7eb 100644 --- a/gcc/config/arm/arm_cde.h +++ b/gcc/config/arm/arm_cde.h @@ -33,6 +33,77 @@ extern "C" { #include +#if defined (__ARM_FEATURE_CDE) + +#if defined (__ARM_FP) || defined (__ARM_FEATURE_MVE) + +/* CDE builtins using FPU/MVE registers. */ + +/* uint32_t + __arm_vcx1_u32(int coproc, uint32_t imm); */ +#define __arm_vcx1_u32(coproc, imm) \ + __builtin_arm_vcx1si(coproc, imm) + +/* uint32_t + __arm_vcx1a_u32(int coproc, uint32_t acc, uint32_t imm); */ +#define __arm_vcx1a_u32(coproc, acc, imm) \ + __builtin_arm_vcx1asi(coproc, acc, imm) + +/* uint32_t + __arm_vcx2_u32(int coproc, uint32_t n, uint32_t imm); */ +#define __arm_vcx2_u32(coproc, n, imm) \ + __builtin_arm_vcx2si(coproc, n, imm) + +/* uint32_t + __arm_vcx2a_u32(int coproc, uint32_t acc, uint32_t n, uint32_t imm); */ +#define __arm_vcx2a_u32(coproc, acc, n, imm) \ + __builtin_arm_vcx2asi(coproc, acc, n, imm) + +/* uint32_t + __arm_vcx3_u32(int coproc, uint32_t n, uint32_t m, uint32_t imm); */ +#define __arm_vcx3_u32(coproc, n, m, imm) \ + __builtin_arm_vcx3si(coproc, n, m, imm) + +/* uint32_t + __arm_vcx3a_u32(int coproc, uint32_t acc, uint32_t n, uint32_t m, + uint32_t imm); */ +#define __arm_vcx3a_u32(coproc, acc, n, m, imm) \ + __builtin_arm_vcx3asi(coproc, acc, n, m, imm) + +/* uint64_t + __arm_vcx1d_u64(int coproc, uint32_t imm); */ +#define __arm_vcx1d_u64(coproc, imm) \ + __builtin_arm_vcx1di(coproc, imm) + +/* uint64_t + __arm_vcx1da_u64(int coproc, uint64_t acc, uint32_t imm); */ +#define __arm_vcx1da_u64(coproc, acc, imm) \ + __builtin_arm_vcx1adi(coproc, acc, imm) + +/* uint64_t + __arm_vcx2d_u64(int coproc, uint64_t m, uint32_t imm); */ +#define __arm_vcx2d_u64(coproc, m, imm) \ + __builtin_arm_vcx2di(coproc, m, imm) + +/* uint64_t + __arm_vcx2da_u64(int coproc, uint64_t acc, uint64_t m, uint32_t imm); */ +#define __arm_vcx2da_u64(coproc, acc, m, imm) \ + __builtin_arm_vcx2adi(coproc, acc, m, imm) + +/* uint64_t + __arm_vcx3d_u64(int coproc, uint64_t n, uint64_t m, uint32_t imm); */ +#define __arm_vcx3d_u64(coproc, n, m, imm) \ + __builtin_arm_vcx3di(coproc, n, m, imm) + +/* uint64_t + __arm_vcx3da_u64(int coproc, uint64_t acc, uint64_t n, uint64_t m, + uint32_t imm); */ +#define __arm_vcx3da_u64(coproc, acc, n, m, imm) \ + __builtin_arm_vcx3adi(coproc, acc, n, m, imm) + +#endif /* __ARM_FP || __ARM_FEATURE_MVE. */ +#endif /* __ARM_FEATURE_CDE. */ + #ifdef __cplusplus } #endif diff --git a/gcc/config/arm/arm_cde_builtins.def b/gcc/config/arm/arm_cde_builtins.def new file mode 100644 index 0000000..a9fea93 --- /dev/null +++ b/gcc/config/arm/arm_cde_builtins.def @@ -0,0 +1,33 @@ +/* Arm Custom Datapath Extension (CDE) builtin definitions. + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by Arm Ltd. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +#undef CDE_VAR2 +#define CDE_VAR2(T, N, A, B, IMM_MAX, ECF_FLAG) \ + VAR1 (T, N, A, IMM_MAX, ECF_FLAG) \ + VAR1 (T, N, B, IMM_MAX, ECF_FLAG) + +CDE_VAR2 (CX_IMM, vcx1, si, di, ARM_VCDE_CONST_1, ECF_CONST) +CDE_VAR2 (CX_UNARY, vcx1a, si, di, ARM_VCDE_CONST_1, ECF_CONST) +CDE_VAR2 (CX_UNARY, vcx2, si, di, ARM_VCDE_CONST_2, ECF_CONST) +CDE_VAR2 (CX_BINARY, vcx2a, si, di, ARM_VCDE_CONST_2, ECF_CONST) +CDE_VAR2 (CX_BINARY, vcx3, si, di, ARM_VCDE_CONST_3, ECF_CONST) +CDE_VAR2 (CX_TERNARY, vcx3a, si, di, ARM_VCDE_CONST_3, ECF_CONST) + +#undef CDE_VAR2 diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index e6b66ee..c941987 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -632,7 +632,7 @@ (V2SI "P") (V4SI "q") (V2SF "P") (V4SF "q") (DI "P") (V2DI "q") - (V2HF "") (SF "") + (V2HF "") (SF "") (SI "") (DF "P") (HF "")]) ;; Output template to select the high VFP register of a mult-register value. diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index bb302ed..59cf5b6 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -226,6 +226,23 @@ (and (match_operand 0 "const_int_operand") (match_test "satisfies_constraint_M (op)"))) +(define_predicate "const_int_coproc_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_CDE_CONST_COPROC)") + (match_test "arm_arch_cde_coproc_bits[UINTVAL (op)] & arm_arch_cde_coproc"))) + +(define_predicate "const_int_vcde1_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_VCDE_CONST_1)"))) + +(define_predicate "const_int_vcde2_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_VCDE_CONST_2)"))) + +(define_predicate "const_int_vcde3_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_VCDE_CONST_3)"))) + ;; This doesn't have to do much because the constant is already checked ;; in the shift_operator predicate. (define_predicate "shift_amount_operand" diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index a757587..1645c32 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -154,6 +154,8 @@ UNSPEC_SMUADX ; Represent the SMUADX operation. UNSPEC_SSAT16 ; Represent the SSAT16 operation. UNSPEC_USAT16 ; Represent the USAT16 operation. + UNSPEC_VCDE ; Custom Datapath Extension instruction. + UNSPEC_VCDEA ; Custom Datapath Extension instruction. ]) diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md index dfb1031..ef83b50 100644 --- a/gcc/config/arm/vfp.md +++ b/gcc/config/arm/vfp.md @@ -2165,3 +2165,74 @@ DONE; } ) + +;; CDE instructions using FPU/MVE S/D registers + +(define_insn "arm_vcx1" + [(set (match_operand:SIDI 0 "register_operand" "=t") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SI 2 "const_int_vcde1_operand" "i")] + UNSPEC_VCDE))] + "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" + "vcx1\\tp%c1, %0, #%c2" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx1a" + [(set (match_operand:SIDI 0 "register_operand" "=t") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SIDI 2 "register_operand" "0") + (match_operand:SI 3 "const_int_vcde1_operand" "i")] + UNSPEC_VCDEA))] + "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" + "vcx1a\\tp%c1, %0, #%c3" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx2" + [(set (match_operand:SIDI 0 "register_operand" "=t") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SIDI 2 "register_operand" "t") + (match_operand:SI 3 "const_int_vcde2_operand" "i")] + UNSPEC_VCDE))] + "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" + "vcx2\\tp%c1, %0, %2, #%c3" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx2a" + [(set (match_operand:SIDI 0 "register_operand" "=t") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SIDI 2 "register_operand" "0") + (match_operand:SIDI 3 "register_operand" "t") + (match_operand:SI 4 "const_int_vcde2_operand" "i")] + UNSPEC_VCDEA))] + "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" + "vcx2a\\tp%c1, %0, %3, #%c4" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx3" + [(set (match_operand:SIDI 0 "register_operand" "=t") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SIDI 2 "register_operand" "t") + (match_operand:SIDI 3 "register_operand" "t") + (match_operand:SI 4 "const_int_vcde3_operand" "i")] + UNSPEC_VCDE))] + "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" + "vcx3\\tp%c1, %0, %2, %3, #%c4" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx3a" + [(set (match_operand:SIDI 0 "register_operand" "=t") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SIDI 2 "register_operand" "0") + (match_operand:SIDI 3 "register_operand" "t") + (match_operand:SIDI 4 "register_operand" "t") + (match_operand:SI 5 "const_int_vcde3_operand" "i")] + UNSPEC_VCDEA))] + "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)" + "vcx3a\\tp%c1, %0, %3, %4, #%c5" + [(set_attr "type" "coproc")] +) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 40597ed..9b2d1f6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Dennis Zhang + + * gcc.target/arm/acle/cde_v_1.c: New test. + * gcc.target/arm/acle/cde_v_1_err.c: New test. + * gcc.target/arm/acle/cde_v_1_mve.c: New test. + 2020-04-08 Patrick Palka Core issues 1001 and 1322 diff --git a/gcc/testsuite/gcc.target/arm/acle/cde_v_1.c b/gcc/testsuite/gcc.target/arm/acle/cde_v_1.c new file mode 100644 index 0000000..3104db4 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde_v_1.c @@ -0,0 +1,94 @@ +/* Test the CDE ACLE intrinsic. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8m_main_cde_fp_ok } */ +/* { dg-options "-save-temps -O2" } */ +/* { dg-add-options arm_v8m_main_cde_fp } */ + +#include "arm_cde.h" + +#define TEST0(T, N, C, I) \ +T test_arm_##N##_##C##_##I () { \ + return __arm_##N (C, I); \ +} + +#define TEST1(T, N, C, I) \ +T test_arm_##N##_##C##_##I (T a) { \ + return __arm_##N (C, a, I); \ +} + +#define TEST2(T, N, C, I) \ +T test_arm_##N##_##C##_##I (T a) { \ + return __arm_##N (C, a, a, I); \ +} + +#define TEST3(T, N, C, I) \ +T test_arm_##N##_##C##_##I (T a) { \ + return __arm_##N (C, a, a, a, I); \ +} + +#define TEST_ALL(C) \ +TEST0 (uint32_t, vcx1_u32, C, 0) \ +TEST1 (uint32_t, vcx1a_u32, C, 0) \ +TEST1 (uint32_t, vcx2_u32, C, 0) \ +TEST2 (uint32_t, vcx2a_u32, C, 0) \ +TEST2 (uint32_t, vcx3_u32, C, 0) \ +TEST3 (uint32_t, vcx3a_u32, C, 0) \ +TEST0 (uint64_t, vcx1d_u64, C, 0) \ +TEST1 (uint64_t, vcx1da_u64, C, 0) \ +TEST1 (uint64_t, vcx2d_u64, C, 0) \ +TEST2 (uint64_t, vcx2da_u64, C, 0) \ +TEST2 (uint64_t, vcx3d_u64, C, 0) \ +TEST3 (uint64_t, vcx3da_u64, C, 0) \ +TEST0 (uint32_t, vcx1_u32, C, 2047) \ +TEST1 (uint32_t, vcx1a_u32, C, 2047) \ +TEST1 (uint32_t, vcx2_u32, C, 63) \ +TEST2 (uint32_t, vcx2a_u32, C, 63) \ +TEST2 (uint32_t, vcx3_u32, C, 7) \ +TEST3 (uint32_t, vcx3a_u32, C, 7) \ +TEST0 (uint64_t, vcx1d_u64, C, 2047) \ +TEST1 (uint64_t, vcx1da_u64, C, 2047) \ +TEST1 (uint64_t, vcx2d_u64, C, 63) \ +TEST2 (uint64_t, vcx2da_u64, C, 63) \ +TEST2 (uint64_t, vcx3d_u64, C, 7) \ +TEST3 (uint64_t, vcx3da_u64, C, 7) + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp0+fp") +TEST_ALL (0) +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp1+fp") +TEST_ALL (1) +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp2+cdecp3+cdecp4+cdecp5+cdecp6+cdecp7+fp") +TEST_ALL (2) +TEST_ALL (3) +TEST_ALL (4) +TEST_ALL (5) +TEST_ALL (6) +TEST_ALL (7) +#pragma GCC pop_options + +/* { dg-final { scan-assembler-times {\tvcx1\tp0, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp1, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp2, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp3, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp4, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp5, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp6, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp7, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp[0-7], s[0-9]+, #2047} 8 } } */ +/* { dg-final { scan-assembler-times {\tvcx1a\tp[0-7], s[0-9]+, #[0,2047]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx2\tp[0-7], s[0-9]+, s[0-9]+, #[0,63]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx2a\tp[0-7], s[0-9]+, s[0-9]+, #[0,63]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx3\tp[0-7], s[0-9]+, s[0-9]+, s[0-9]+, #[0,7]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx3a\tp[0-7], s[0-9]+, s[0-9]+, s[0-9]+, #[0,7]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp[0-7], d[0-9]+, #[0,2047]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx1a\tp[0-7], d[0-9]+, #[0,2047]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx2\tp[0-7], d[0-9]+, d[0-9]+, #[0,63]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx2a\tp[0-7], d[0-9]+, d[0-9]+, #[0,63]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx3\tp[0-7], d[0-9]+, d[0-9]+, d[0-9]+, #[0,7]} 16 } } */ +/* { dg-final { scan-assembler-times {\tvcx3a\tp[0-7], d[0-9]+, d[0-9]+, d[0-9]+, #[0,7]} 16 } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c new file mode 100644 index 0000000..023fab4 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c @@ -0,0 +1,127 @@ +/* Test the CDE ACLE intrinsic. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8m_main_cde_fp_ok } */ +/* { dg-add-options arm_v8m_main_cde_fp } */ + +#include "arm_cde.h" + +uint64_t test_coproc_range (uint32_t a, uint64_t b) +{ + uint64_t res = 0; + res += __arm_vcx1_u32 (8, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx1a_u32 (8, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx2_u32 (8, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx2a_u32 (8, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx3_u32 (8, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx3a_u32 (8, a, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx1d_u64 (8, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx1da_u64 (8, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx2d_u64 (8, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx2da_u64 (8, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx3d_u64 (8, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx3da_u64 (8, a, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */ + return res; +} + +uint64_t test_imm_range (uint32_t a, uint64_t b) +{ + uint64_t res = 0; + res += __arm_vcx1_u32 (0, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */ + res += __arm_vcx1a_u32 (0, a, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */ + res += __arm_vcx2_u32 (0, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */ + res += __arm_vcx2a_u32 (0, a, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */ + res += __arm_vcx3_u32 (0, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx3a_u32 (0, a, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx1d_u64 (0, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */ + res += __arm_vcx1da_u64 (0, a, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */ + res += __arm_vcx2d_u64 (0, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */ + res += __arm_vcx2da_u64 (0, a, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */ + res += __arm_vcx3d_u64 (0, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx3da_u64 (0, a, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */ + return res; +} + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp1+fp") +uint64_t test_coproc_match_1 (uint32_t a, uint64_t b) +{ + uint64_t res = 0; + res += __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx1a_u32 (0, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx2_u32 (0, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx2a_u32 (0, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx3_u32 (0, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx3a_u32 (0, a, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx1d_u64 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx1da_u64 (0, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx2d_u64 (0, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx2da_u64 (0, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx3d_u64 (0, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + res += __arm_vcx3da_u64 (0, a, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ + return res; +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp2+fp") +uint32_t test_coproc_match_2 () +{ + return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp3+fp") +uint32_t test_coproc_match_3 () +{ + return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp4+fp") +uint32_t test_coproc_match_4 () +{ + return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp5+fp") +uint32_t test_coproc_match_5 () +{ + return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp6+fp") +uint32_t test_coproc_match_6 () +{ + return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp7+fp") +uint32_t test_coproc_match_7 () +{ + return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */ +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-m.main+cdecp0+fp") +uint32_t test_coproc_match_0 () +{ + uint64_t res = 0; + res += __arm_vcx1_u32 (1, 0); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + res += __arm_vcx1_u32 (2, 0); /* { dg-error {coprocessor 2 is not enabled with \+cdecp2} } */ + res += __arm_vcx1_u32 (3, 0); /* { dg-error {coprocessor 3 is not enabled with \+cdecp3} } */ + res += __arm_vcx1_u32 (4, 0); /* { dg-error {coprocessor 4 is not enabled with \+cdecp4} } */ + res += __arm_vcx1_u32 (5, 0); /* { dg-error {coprocessor 5 is not enabled with \+cdecp5} } */ + res += __arm_vcx1_u32 (6, 0); /* { dg-error {coprocessor 6 is not enabled with \+cdecp6} } */ + res += __arm_vcx1_u32 (7, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + return res; +} +#pragma GCC pop_options diff --git a/gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c new file mode 100644 index 0000000..5140c3f --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c @@ -0,0 +1,56 @@ +/* Test the CDE ACLE intrinsic. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_1m_main_cde_mve_ok } */ +/* { dg-options "-save-temps -O2" } */ +/* { dg-add-options arm_v8_1m_main_cde_mve } */ + +#include "arm_cde.h" + +#define TEST0(T, N, C, I) \ +T test_arm_##N##_##C##_##I () { \ + return __arm_##N (C, I); \ +} + +#define TEST1(T, N, C, I) \ +T test_arm_##N##_##C##_##I (T a) { \ + return __arm_##N (C, a, I); \ +} + +#define TEST2(T, N, C, I) \ +T test_arm_##N##_##C##_##I (T a) { \ + return __arm_##N (C, a, a, I); \ +} + +#define TEST3(T, N, C, I) \ +T test_arm_##N##_##C##_##I (T a) { \ + return __arm_##N (C, a, a, a, I); \ +} + +#define TEST_ALL(C) \ +TEST0 (uint32_t, vcx1_u32, C, 0) \ +TEST1 (uint32_t, vcx1a_u32, C, 0) \ +TEST1 (uint32_t, vcx2_u32, C, 0) \ +TEST2 (uint32_t, vcx2a_u32, C, 0) \ +TEST2 (uint32_t, vcx3_u32, C, 0) \ +TEST3 (uint32_t, vcx3a_u32, C, 0) \ +TEST0 (uint64_t, vcx1d_u64, C, 0) \ +TEST1 (uint64_t, vcx1da_u64, C, 0) \ +TEST1 (uint64_t, vcx2d_u64, C, 0) \ +TEST2 (uint64_t, vcx2da_u64, C, 0) \ +TEST2 (uint64_t, vcx3d_u64, C, 0) \ +TEST3 (uint64_t, vcx3da_u64, C, 0) + +TEST_ALL (0) + +/* { dg-final { scan-assembler-times {\tvcx1\tp0, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1a\tp0, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx2\tp0, s[0-9]+, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx2a\tp0, s[0-9]+, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx3\tp0, s[0-9]+, s[0-9]+, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx3a\tp0, s[0-9]+, s[0-9]+, s[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1\tp0, d[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx1a\tp0, d[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx2\tp0, d[0-9]+, d[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx2a\tp0, d[0-9]+, d[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx3\tp0, d[0-9]+, d[0-9]+, d[0-9]+, #0} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcx3a\tp0, d[0-9]+, d[0-9]+, d[0-9]+, #0} 1 } } */ -- cgit v1.1 From a5f3c89e1b78dbb69d3c7a47d2c9fd7ad93fe136 Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Wed, 8 Apr 2020 16:06:45 +0100 Subject: [Arm] Implement scalar Custom Datapath Extension intrinsics This patch introduces the scalar CDE (Custom Datapath Extension) intrinsics for the arm backend. There is nothing beyond the standard in this patch. We simply build upon what has been done by Dennis for the vector intrinsics. We do add `+cdecp6` to the default arguments for `target-supports.exp`, this allows for using coprocessor 6 in tests. This patch uses an alternate coprocessor to ease assembler scanning by looking for a use of coprocessor 6. We also ensure that any DImode registers are put in an even-odd register pair when compiling for a target with CDE -- this avoids faulty code generation for -Os when producing the cx*d instructions. Testing done: Bootstrapped and regtested for arm-none-linux-gnueabihf. gcc/ChangeLog: 2020-03-03 Matthew Malcomson * config/arm/arm.c (arm_hard_regno_mode_ok): DImode registers forced into even-odd register pairs for TARGET_CDE. * config/arm/arm.h (ARM_CCDE_CONST_1): New. (ARM_CCDE_CONST_2): New. (ARM_CCDE_CONST_3): New. * config/arm/arm.md (arm_cx1si, arm_cx1di arm_cx1asi, arm_cx1adi, arm_cx2si, arm_cx2di arm_cx2asi, arm_cx2adi arm_cx3si, arm_cx3di, arm_cx3asi, arm_cx3adi): New patterns. * config/arm/arm_cde.h (__arm_cx1, __arm_cx1a, __arm_cx2, __arm_cx2a, __arm_cx3, __arm_cx3a, __arm_cx1d, __arm_cx1da, __arm_cx2d, __arm_cx2da, __arm_cx3d, __arm_cx3da): New ACLE function macros. * config/arm/arm_cde_builtins.def (cx1, cx1a, cx2, cx2a, cx3, cx3a): Define intrinsics. * config/arm/iterators.md (cde_suffix, cde_dest): New mode attributes. * config/arm/predicates.md (const_int_ccde1_operand, const_int_ccde2_operand, const_int_ccde3_operand): New. * config/arm/unspecs.md (UNSPEC_CDE, UNSPEC_CDEA): New. gcc/testsuite/ChangeLog: 2020-03-03 Matthew Malcomson * gcc.target/arm/acle/cde-errors.c: New test. * gcc.target/arm/acle/cde.c: New test. * lib/target-supports.exp: Update CDE flags to enable coprocessor 6. --- gcc/config/arm/arm.c | 5 +- gcc/config/arm/arm.h | 3 + gcc/config/arm/arm.md | 70 ++++++++ gcc/config/arm/arm_cde.h | 36 ++++ gcc/config/arm/arm_cde_builtins.def | 7 + gcc/config/arm/iterators.md | 3 + gcc/config/arm/predicates.md | 12 ++ gcc/config/arm/unspecs.md | 2 + gcc/testsuite/gcc.target/arm/acle/cde-errors.c | 111 ++++++++++++ gcc/testsuite/gcc.target/arm/acle/cde.c | 229 +++++++++++++++++++++++++ gcc/testsuite/lib/target-supports.exp | 6 +- 11 files changed, 479 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde-errors.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde.c (limited to 'gcc') diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 4dada07..c38776f 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -25057,10 +25057,11 @@ arm_hard_regno_mode_ok (unsigned int regno, machine_mode mode) if (ARM_NUM_REGS (mode) > 4) return false; - if (TARGET_THUMB2 && !TARGET_HAVE_MVE) + if (TARGET_THUMB2 && !(TARGET_HAVE_MVE || TARGET_CDE)) return true; - return !(TARGET_LDRD && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0); + return !((TARGET_LDRD || TARGET_CDE) + && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0); } if (regno == FRAME_POINTER_REGNUM diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index ca36a74..83886a2 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -576,6 +576,9 @@ extern int arm_arch_cde; extern int arm_arch_cde_coproc; extern const int arm_arch_cde_coproc_bits[]; #define ARM_CDE_CONST_COPROC 7 +#define ARM_CCDE_CONST_1 ((1 << 13) - 1) +#define ARM_CCDE_CONST_2 ((1 << 9 ) - 1) +#define ARM_CCDE_CONST_3 ((1 << 6 ) - 1) #define ARM_VCDE_CONST_1 ((1 << 11) - 1) #define ARM_VCDE_CONST_2 ((1 << 6 ) - 1) #define ARM_VCDE_CONST_3 ((1 << 3 ) - 1) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 6d55603..7bc55cc 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -4408,6 +4408,76 @@ (set_attr "shift" "3") (set_attr "type" "logic_shift_reg")]) +;; Custom Datapath Extension insns. +(define_insn "arm_cx1" + [(set (match_operand:SIDI 0 "s_register_operand" "=r") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SI 2 "const_int_ccde1_operand" "i")] + UNSPEC_CDE))] + "TARGET_CDE" + "cx1\\tp%c1, , %2" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_cx1a" + [(set (match_operand:SIDI 0 "s_register_operand" "=r") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SIDI 2 "s_register_operand" "0") + (match_operand:SI 3 "const_int_ccde1_operand" "i")] + UNSPEC_CDEA))] + "TARGET_CDE" + "cx1a\\tp%c1, , %3" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_cx2" + [(set (match_operand:SIDI 0 "s_register_operand" "=r") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SI 2 "s_register_operand" "r") + (match_operand:SI 3 "const_int_ccde2_operand" "i")] + UNSPEC_CDE))] + "TARGET_CDE" + "cx2\\tp%c1, , %2, %3" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_cx2a" + [(set (match_operand:SIDI 0 "s_register_operand" "=r") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SIDI 2 "s_register_operand" "0") + (match_operand:SI 3 "s_register_operand" "r") + (match_operand:SI 4 "const_int_ccde2_operand" "i")] + UNSPEC_CDEA))] + "TARGET_CDE" + "cx2a\\tp%c1, , %3, %4" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_cx3" + [(set (match_operand:SIDI 0 "s_register_operand" "=r") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SI 2 "s_register_operand" "r") + (match_operand:SI 3 "s_register_operand" "r") + (match_operand:SI 4 "const_int_ccde3_operand" "i")] + UNSPEC_CDE))] + "TARGET_CDE" + "cx3\\tp%c1, , %2, %3, %4" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_cx3a" + [(set (match_operand:SIDI 0 "s_register_operand" "=r") + (unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SIDI 2 "s_register_operand" "0") + (match_operand:SI 3 "s_register_operand" "r") + (match_operand:SI 4 "s_register_operand" "r") + (match_operand:SI 5 "const_int_ccde3_operand" "i")] + UNSPEC_CDEA))] + "TARGET_CDE" + "cx3a\\tp%c1, , %3, %4, %5" + [(set_attr "type" "coproc")] +) + ;; Shift and rotation insns (define_expand "ashldi3" diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h index 4c9f7eb..9adcb99 100644 --- a/gcc/config/arm/arm_cde.h +++ b/gcc/config/arm/arm_cde.h @@ -35,6 +35,42 @@ extern "C" { #if defined (__ARM_FEATURE_CDE) +#define __arm_cx1(coproc, imm) \ + __builtin_arm_cx1si(coproc, imm) + +#define __arm_cx1a(coproc, acc, imm) \ + __builtin_arm_cx1asi(coproc, acc, imm) + +#define __arm_cx2(coproc, n, imm) \ + __builtin_arm_cx2si(coproc, n, imm) + +#define __arm_cx2a(coproc, acc, n, imm) \ + __builtin_arm_cx2asi(coproc, acc, n, imm) + +#define __arm_cx3(coproc, n, m, imm) \ + __builtin_arm_cx3si(coproc, n, m, imm) + +#define __arm_cx3a(coproc, acc, n, m, imm) \ + __builtin_arm_cx3asi(coproc, acc, n, m, imm) + +#define __arm_cx1d(coproc, imm) \ + __builtin_arm_cx1di(coproc, imm) + +#define __arm_cx1da(coproc, acc, imm) \ + __builtin_arm_cx1adi(coproc, acc, imm) + +#define __arm_cx2d(coproc, n, imm) \ + __builtin_arm_cx2di(coproc, n, imm) + +#define __arm_cx2da(coproc, acc, n, imm) \ + __builtin_arm_cx2adi(coproc, acc, n, imm) + +#define __arm_cx3d(coproc, n, m, imm) \ + __builtin_arm_cx3di(coproc, n, m, imm) + +#define __arm_cx3da(coproc, acc, n, m, imm) \ + __builtin_arm_cx3adi(coproc, acc, n, m, imm) + #if defined (__ARM_FP) || defined (__ARM_FEATURE_MVE) /* CDE builtins using FPU/MVE registers. */ diff --git a/gcc/config/arm/arm_cde_builtins.def b/gcc/config/arm/arm_cde_builtins.def index a9fea93..8b2cfc0 100644 --- a/gcc/config/arm/arm_cde_builtins.def +++ b/gcc/config/arm/arm_cde_builtins.def @@ -23,6 +23,13 @@ VAR1 (T, N, A, IMM_MAX, ECF_FLAG) \ VAR1 (T, N, B, IMM_MAX, ECF_FLAG) +CDE_VAR2 (CX_IMM, cx1, si, di, ARM_CCDE_CONST_1, ECF_CONST) +CDE_VAR2 (CX_UNARY, cx1a, si, di, ARM_CCDE_CONST_1, ECF_CONST) +CDE_VAR2 (CX_UNARY, cx2, si, di, ARM_CCDE_CONST_2, ECF_CONST) +CDE_VAR2 (CX_BINARY, cx2a, si, di, ARM_CCDE_CONST_2, ECF_CONST) +CDE_VAR2 (CX_BINARY, cx3, si, di, ARM_CCDE_CONST_3, ECF_CONST) +CDE_VAR2 (CX_TERNARY, cx3a, si, di, ARM_CCDE_CONST_3, ECF_CONST) + CDE_VAR2 (CX_IMM, vcx1, si, di, ARM_VCDE_CONST_1, ECF_CONST) CDE_VAR2 (CX_UNARY, vcx1a, si, di, ARM_VCDE_CONST_1, ECF_CONST) CDE_VAR2 (CX_UNARY, vcx2, si, di, ARM_VCDE_CONST_2, ECF_CONST) diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index c941987..502f4f53 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -896,6 +896,9 @@ (define_mode_attr VSF2BF [(V2SF "V4BF") (V4SF "V8BF")]) +(define_mode_attr cde_suffix [(SI "") (DI "d")]) +(define_mode_attr cde_dest [(SI "%0") (DI "%0, %H0")]) + ;;---------------------------------------------------------------------------- ;; Code attributes ;;---------------------------------------------------------------------------- diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 59cf5b6..3ad47d2 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -231,6 +231,18 @@ (match_test "IN_RANGE (UINTVAL (op), 0, ARM_CDE_CONST_COPROC)") (match_test "arm_arch_cde_coproc_bits[UINTVAL (op)] & arm_arch_cde_coproc"))) +(define_predicate "const_int_ccde1_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_CCDE_CONST_1)"))) + +(define_predicate "const_int_ccde2_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_CCDE_CONST_2)"))) + +(define_predicate "const_int_ccde3_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_CCDE_CONST_3)"))) + (define_predicate "const_int_vcde1_operand" (and (match_operand 0 "const_int_operand") (match_test "IN_RANGE (UINTVAL (op), 0, ARM_VCDE_CONST_1)"))) diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index 1645c32..3250b03 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -154,6 +154,8 @@ UNSPEC_SMUADX ; Represent the SMUADX operation. UNSPEC_SSAT16 ; Represent the SSAT16 operation. UNSPEC_USAT16 ; Represent the USAT16 operation. + UNSPEC_CDE ; Custom Datapath Extension instruction. + UNSPEC_CDEA ; Custom Datapath Extension instruction. UNSPEC_VCDE ; Custom Datapath Extension instruction. UNSPEC_VCDEA ; Custom Datapath Extension instruction. ]) diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-errors.c b/gcc/testsuite/gcc.target/arm/acle/cde-errors.c new file mode 100644 index 0000000..827e03b --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde-errors.c @@ -0,0 +1,111 @@ +/* Test the Custom Datapath Extension ACLE intrinsic. */ + +/* This file is to check we catch incorrect uses of the ACLE. */ + +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8m_main_cde_ok } */ +/* { dg-add-options arm_v8m_main_cde } */ +/* { dg-additional-options "-save-temps" } */ + +#include "arm_cde.h" + +/* + These are the scalar intrinsics. +uint32_t __arm_cx1(int coproc, uint32_t imm); +uint32_t __arm_cx1a(int coproc, uint32_t acc, uint32_t imm); +uint32_t __arm_cx2(int coproc, uint32_t n, uint32_t imm); +uint32_t __arm_cx2a(int coproc, uint32_t acc, uint32_t n, uint32_t imm); +uint32_t __arm_cx3(int coproc, uint32_t n, uint32_t m, uint32_t imm); +uint32_t __arm_cx3a(int coproc, uint32_t acc, uint32_t n, uint32_t m, uint32_t imm); + +uint64_t __arm_cx1d(int coproc, uint32_t imm); +uint64_t __arm_cx1da(int coproc, uint64_t acc, uint32_t imm); +uint64_t __arm_cx2d(int coproc, uint32_t n, uint32_t imm); +uint64_t __arm_cx2da(int coproc, uint64_t acc, uint32_t n, uint32_t imm); +uint64_t __arm_cx3d(int coproc, uint32_t n, uint32_t m, uint32_t imm); +uint64_t __arm_cx3da(int coproc, uint64_t acc, uint32_t n, uint32_t m, uint32_t imm); +*/ + +/* Incorrect types as the constants. */ +uint64_t test_cde (uint32_t n, uint32_t m) +{ + uint64_t accum = 0; + + /* `coproc` not enabled. */ + accum += __arm_cx1 (7, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx1a (7, (uint32_t)accum, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx2 (7, n, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx2a (7, (uint32_t)accum, n, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx3 (7, n, m, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx3a (7, (uint32_t)accum, n, m, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + + accum += __arm_cx1d (7, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx1da (7, accum, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx2d (7, n, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx2da (7, accum, n, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx3d (7, n, m, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + accum += __arm_cx3da (7, accum, n, m, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */ + + /* `coproc` out of range. */ + accum += __arm_cx1 (8, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx1a (8, (uint32_t)accum, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx2 (8, n, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx2a (8, (uint32_t)accum, n, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx3 (8, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx3a (8, (uint32_t)accum, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + + accum += __arm_cx1d (8, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx1da (8, accum, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx2d (8, n, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx2da (8, accum, n, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx3d (8, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx3da (8, accum, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + + /* `imm` out of range. */ + accum += __arm_cx1 (0, 8192); /* { dg-error {argument 2 must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx1a (0, (uint32_t)accum, 8192); /* { dg-error {argument 3 must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx2 (0, n, 512); /* { dg-error {argument 3 must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx2a (0, (uint32_t)accum, n, 512); /* { dg-error {argument 4 must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx3 (0, n, m, 64); /* { dg-error {argument 4 must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx3a (0, (uint32_t)accum, n, m, 64); /* { dg-error {argument 5 must be a constant immediate in range \[0-63\]} } */ + + accum += __arm_cx1d (0, 8192); /* { dg-error {argument 2 must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx1da (0, accum, 8192); /* { dg-error {argument 3 must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx2d (0, n, 512); /* { dg-error {argument 3 must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx2da (0, accum, n, 512); /* { dg-error {argument 4 must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx3d (0, n, m, 64); /* { dg-error {argument 4 must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx3da (0, accum, n, m, 64); /* { dg-error {argument 5 must be a constant immediate in range \[0-63\]} } */ + + /* `imm` is not an immediate. */ + accum += __arm_cx1 (0, n); /* { dg-error {argument 2 must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx1a (0, (uint32_t)accum, n); /* { dg-error {argument 3 must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx2 (0, n, n); /* { dg-error {argument 3 must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx2a (0, (uint32_t)accum, n, n); /* { dg-error {argument 4 must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx3 (0, n, m, n); /* { dg-error {argument 4 must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx3a (0, (uint32_t)accum, n, m, n); /* { dg-error {argument 5 must be a constant immediate in range \[0-63\]} } */ + + accum += __arm_cx1d (0, n); /* { dg-error {argument 2 must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx1da (0, accum, n); /* { dg-error {argument 3 must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx2d (0, n, n); /* { dg-error {argument 3 must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx2da (0, accum, n, n); /* { dg-error {argument 4 must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx3d (0, n, m, n); /* { dg-error {argument 4 must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx3da (0, accum, n, m, n); /* { dg-error {argument 5 must be a constant immediate in range \[0-63\]} } */ + + /* `coproc` is not an immediate. */ + accum += __arm_cx1 ((int)m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx1a ((int)m, (uint32_t)accum, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx2 ((int)m, n, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx2a ((int)m, (uint32_t)accum, n, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx3 ((int)m, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx3a ((int)m, (uint32_t)accum, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + + accum += __arm_cx1d ((int)m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx1da ((int)m, accum, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx2d ((int)m, n, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx2da ((int)m, accum, n, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx3d ((int)m, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_cx3da ((int)m, accum, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + + return accum; +} + diff --git a/gcc/testsuite/gcc.target/arm/acle/cde.c b/gcc/testsuite/gcc.target/arm/acle/cde.c new file mode 100644 index 0000000..f3ba8f0 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde.c @@ -0,0 +1,229 @@ +/* { dg-do compile } */ +/* { dg-skip-if "Require optimsation to compile DCE tests" { *-*-* } { "-O0" } { "" } } */ +/* { dg-require-effective-target arm_v8m_main_cde_ok } */ +/* { dg-add-options arm_v8m_main_cde } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* These are the scalar intrinsics. +uint32_t __arm_cx1(int coproc, uint32_t imm); +uint32_t __arm_cx1a(int coproc, uint32_t acc, uint32_t imm); +uint32_t __arm_cx2(int coproc, uint32_t n, uint32_t imm); +uint32_t __arm_cx2a(int coproc, uint32_t acc, uint32_t n, uint32_t imm); +uint32_t __arm_cx3(int coproc, uint32_t n, uint32_t m, uint32_t imm); +uint32_t __arm_cx3a(int coproc, uint32_t acc, uint32_t n, uint32_t m, uint32_t imm); + +uint64_t __arm_cx1d(int coproc, uint32_t imm); +uint64_t __arm_cx1da(int coproc, uint64_t acc, uint32_t imm); +uint64_t __arm_cx2d(int coproc, uint32_t n, uint32_t imm); +uint64_t __arm_cx2da(int coproc, uint64_t acc, uint32_t n, uint32_t imm); +uint64_t __arm_cx3d(int coproc, uint32_t n, uint32_t m, uint32_t imm); +uint64_t __arm_cx3da(int coproc, uint64_t acc, uint32_t n, uint32_t m, uint32_t imm); */ + +#include "arm_cde.h" + +#define TEST_CDE_SCALAR_INTRINSIC(name, accum_type, arguments) \ + accum_type test_cde_##name (__attribute__ ((unused)) uint32_t n, \ + __attribute__ ((unused)) uint32_t m) \ + { \ + accum_type accum = 0; \ + accum += __arm_##name arguments; \ + return accum; \ + } + +/* Basic test that we produce the assembly as expected. */ +/* +** test_cde_cx1: +** cx1 p0, r0, #33 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx1, uint32_t, (0, 33)) + +/* +** test_cde_cx1a: +** movs r0, #0 +** cx1a p0, r0, #33 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx1a, uint32_t, (0, accum, 33)) + +/* +** test_cde_cx2: +** cx2 p0, r0, r0, #33 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx2, uint32_t, (0, n, 33)) + +/* +** test_cde_cx2a: +** movs (r[0-9]+), #0 +** cx2a p0, \1, r0, #33 +** mov r0, \1 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx2a, uint32_t, (0, accum, n, 33)) + +/* +** test_cde_cx3: +** cx3 p0, r0, r0, r1, #33 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx3, uint32_t, (0, n, m, 33)) + +/* +** test_cde_cx3a: +** movs (r[0-9]+), #0 +** cx3a p0, \1, r0, r1, #33 +** mov r0, \1 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx3a, uint32_t, (0, accum, n, m, 33)) + +/* +** test_cde_cx1d: +** cx1d p0, r0, r1, #33 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx1d, uint64_t, (0, 33)) + +/* +** test_cde_cx1da: +** movs r0, #0 +** movs r1, #0 +** cx1da p0, r0, r1, #33 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx1da, uint64_t, (0, accum, 33)) + +/* +** test_cde_cx2d: +** cx2d p0, r0, r1, r0, #33 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx2d, uint64_t, (0, n, 33)) + +/* This particular function gets optimised by the compiler in two different + ways depending on the optimisation level. So does test_cde_cx3da. That's + why we have two different regexes in each of these function body checks. */ +/* +** test_cde_cx2da: +** ( +** mov (r[0-9]+), r0 +** movs r0, #0 +** movs r1, #0 +** cx2da p0, r0, r1, \1, #33 +** | +** movs (r[0-9]+), #0 +** movs (r[0-9]+), #0 +** cx2da p0, \2, \3, r0, #33 +** mov r0, \2 +** mov r1, \3 +** ) +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx2da, uint64_t, (0, accum, n, 33)) + +/* +** test_cde_cx3d: +** cx3d p0, r0, r1, r0, r1, #33 +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx3d, uint64_t, (0, n, m, 33)) + +/* +** test_cde_cx3da: +** ... +** ( +** movs (r[0-9]+), #0 +** movs (r[0-9]+), #0 +** cx3da p0, \1, \2, r0, r1, #33 +** mov r0, \1 +** mov r1, \2 +** | +** movs r0, #0 +** movs r1, #0 +** cx3da p0, r0, r1, r[0-9]+, r[0-9]+, #33 +** ) +** ... +** bx lr +*/ +TEST_CDE_SCALAR_INTRINSIC (cx3da, uint64_t, (0, accum, n, m, 33)) + + + +/* Ensure this function gets DCE'd out after optimisation. + Should be such since the ACLE specification mentions these functions are + stateless and pure. */ +/* +** test_cde_dce: +** bx lr +*/ +void test_cde_dce (uint32_t n, uint32_t m) +{ + uint64_t accum = 0; + __arm_cx1 (0, 33); + __arm_cx1a (0, accum, 33); + __arm_cx2 (0, n, 33); + __arm_cx2a (0, accum, n, 33); + __arm_cx3 (0, n, m, 33); + __arm_cx3a (0, accum, n, m, 33); + __arm_cx1d (0, 33); + __arm_cx1da (0, accum, 33); + __arm_cx2d (0, n, 33); + __arm_cx2da (0, accum, n, 33); + __arm_cx3d (0, n, m, 33); + __arm_cx3da (0, accum, n, m, 33); +} + +/* Checking this function allows constants with symbolic names. + This test must be run under some level of optimisation. + The actual check we perform is that the function is provided something that, + at the point of expansion, is an immediate. That check is not as strict as + having something that is an immediate directly. + + Since we've already checked these intrinsics generate code in the manner we + expect (above), here we just check that all the instructions we expect are + there. To ensure the instructions are from these functions we use different + constants and search for those specifically with `scan-assembler-times`. */ + +/* Checking this function allows constants with symbolic names. */ +uint32_t test_cde2 (uint32_t n, uint32_t m) +{ + int coproc = 6; + uint32_t imm = 30; + uint32_t accum = 0; + accum += __arm_cx1 (coproc, imm); + accum += __arm_cx1a (coproc, accum, imm); + accum += __arm_cx2 (coproc, n, imm); + accum += __arm_cx2a (coproc, accum, n, imm); + accum += __arm_cx3 (coproc, n, m, imm); + accum += __arm_cx3a (coproc, accum, n, m, imm); + return accum; +} + +/* Checking this function allows constants with symbolic names. */ +uint64_t test_cdedi2 (uint32_t n, uint32_t m) +{ + int coproc = 6; + uint32_t imm = 30; + uint64_t accum = 0; + accum += __arm_cx1d (coproc, imm); + accum += __arm_cx1da (coproc, accum, imm); + accum += __arm_cx2d (coproc, n, imm); + accum += __arm_cx2da (coproc, accum, n, imm); + accum += __arm_cx3d (coproc, n, m, imm); + accum += __arm_cx3da (coproc, accum, n, m, imm); + return accum; +} + +/* { dg-final { scan-assembler-times "cx1\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx2\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx3\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx1a\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx2a\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx3a\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx1d\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx2d\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx3d\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx1da\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx2da\\tp6" 1 } } */ +/* { dg-final { scan-assembler-times "cx3da\\tp6" 1 } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 050b4ba..1e8c0e2 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -5117,13 +5117,13 @@ proc add_options_for_arm_v8_2a_bf16_neon { flags } { foreach { armfunc armflag armdef } { arm_v8m_main_cde - "-march=armv8-m.main+cdecp0 -mthumb" + "-march=armv8-m.main+cdecp0+cdecp6 -mthumb" "defined (__ARM_FEATURE_CDE)" arm_v8m_main_cde_fp - "-march=armv8-m.main+fp+cdecp0 -mthumb" + "-march=armv8-m.main+fp+cdecp0+cdecp6 -mthumb" "defined (__ARM_FEATURE_CDE) && defined (__ARM_FP)" arm_v8_1m_main_cde_mve - "-march=armv8.1-m.main+mve+cdecp0 -mthumb" + "-march=armv8.1-m.main+mve+cdecp0+cdecp6 -mthumb" "defined (__ARM_FEATURE_CDE) && defined (__ARM_FEATURE_MVE)" } { eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef ] { -- cgit v1.1 From 78bf9163764aba15bb0c254cd38c985713924380 Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Wed, 8 Apr 2020 16:06:47 +0100 Subject: [Arm] Implement CDE intrinsics for MVE registers. Implement CDE intrinsics on MVE registers. Other than the basics required for adding intrinsics this patch consists of three changes. ** We separate out the MVE types and casts from the arm_mve.h header. This is so that the types can be used in arm_cde.h without the need to include the entire arm_mve.h header. The only type that arm_cde.h needs is `uint8x16_t`, so this separation could be avoided by using a `typedef` in this file. Since the introduced intrinsics are all defined to act on the full range of MVE types, declaring all such types seems intuitive since it will provide their declaration to the user too. This arm_mve_types.h header not only includes the MVE types, but also the conversion intrinsics between them. Some of the conversion intrinsics are needed for arm_cde.h, but most are not. We include all conversion intrinsics to keep the definition of such conversion functions all in one place, on the understanding that extra conversion functions being defined when including `arm_cde.h` is not a problem. ** We define the TARGET_RESOLVE_OVERLOADED_BUILTIN hook for the Arm backend. This is needed to implement the polymorphism for the required intrinsics. The intrinsics have no specialised version, and the resulting assembly instruction for all different types should be exactly the same. Due to this we have implemented these intrinsics via one builtin on one type. All other calls to the intrinsic with different types are implicitly cast to the one type that is defined, and hence are all expanded to the same RTL pattern that is only defined for one machine mode. ** We seperate the initialisation of the CDE intrinsics from others. This allows us to ensure that the CDE intrinsics acting on MVE registers are only created when both CDE and MVE are available. Only initialising these builtins when both features are available is especially important since they require a type that is only initialised when the target supports hard float. Hence trying to initialise these builtins on a soft float target would cause an ICE. Testing done: Full bootstrap and regtest on arm-none-linux-gnueabihf Regression test on arm-none-eabi Ok for trunk? gcc/ChangeLog: 2020-03-10 Matthew Malcomson * config.gcc (arm_mve_types.h): New extra_header for arm. * config/arm/arm-builtins.c (arm_resolve_overloaded_builtin): New. (arm_init_cde_builtins): New. (arm_init_acle_builtins): Remove initialisation of CDE builtins. (arm_init_builtins): Call arm_init_cde_builtins when target supports CDE. * config/arm/arm-c.c (arm_resolve_overloaded_builtin): New declaration. (arm_register_target_pragmas): Initialise resolve_overloaded_builtin hook to the implementation for the arm backend. * config/arm/arm.h (ARM_MVE_CDE_CONST_1): New. (ARM_MVE_CDE_CONST_2): New. (ARM_MVE_CDE_CONST_3): New. * config/arm/arm_cde.h (__arm_vcx1q_u8): New. (__arm_vcx1qa): New. (__arm_vcx2q): New. (__arm_vcx2q_u8): New. (__arm_vcx2qa): New. (__arm_vcx3q): New. (__arm_vcx3q_u8): New. (__arm_vcx3qa): New. * config/arm/arm_cde_builtins.def (vcx1q, vcx1qa, vcx2q, vcx2qa, vcx3q, vcx3qa): New builtins defined. * config/arm/arm_mve.h: Move typedefs and conversion intrinsics to arm_mve_types.h header. * config/arm/arm_mve_types.h: New file. * config/arm/mve.md (arm_vcx1qv16qi, arm_vcx1qav16qi, arm_vcx2qv16qi, arm_vcx2qav16qi, arm_vcx3qv16qi, arm_vcx3qav16qi): New patterns. * config/arm/predicates.md (const_int_mve_cde1_operand, const_int_mve_cde2_operand, const_int_mve_cde3_operand): New. gcc/testsuite/ChangeLog: 2020-03-23 Matthew Malcomson Dennis Zhang * gcc.target/arm/acle/cde-mve-error-1.c: New test. * gcc.target/arm/acle/cde-mve-error-2.c: New test. * gcc.target/arm/acle/cde-mve-error-3.c: New test. * gcc.target/arm/acle/cde-mve-full-assembly.c: New test. * gcc.target/arm/acle/cde-mve-tests.c: New test. * lib/target-supports.exp (arm_v8_1m_main_cde_mve_fp): New check effective. (arm_v8_1m_main_cde_mve, arm_v8m_main_cde_fp): Use -mfpu=auto so we only check configurations that make sense. --- gcc/config.gcc | 2 +- gcc/config/arm/arm-builtins.c | 103 +- gcc/config/arm/arm-c.c | 3 + gcc/config/arm/arm.h | 3 + gcc/config/arm/arm_cde.h | 22 + gcc/config/arm/arm_cde_builtins.def | 11 + gcc/config/arm/arm_mve.h | 1299 +------------------ gcc/config/arm/arm_mve_types.h | 1330 ++++++++++++++++++++ gcc/config/arm/mve.md | 71 ++ gcc/config/arm/predicates.md | 12 + .../gcc.target/arm/acle/cde-mve-error-1.c | 42 + .../gcc.target/arm/acle/cde-mve-error-2.c | 103 ++ .../gcc.target/arm/acle/cde-mve-error-3.c | 85 ++ .../gcc.target/arm/acle/cde-mve-full-assembly.c | 557 ++++++++ gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c | 722 +++++++++++ gcc/testsuite/lib/target-supports.exp | 7 +- 16 files changed, 3070 insertions(+), 1302 deletions(-) create mode 100644 gcc/config/arm/arm_mve_types.h create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde-mve-error-1.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde-mve-error-2.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde-mve-error-3.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde-mve-full-assembly.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c (limited to 'gcc') diff --git a/gcc/config.gcc b/gcc/config.gcc index 7624c65..cf1a87e 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -346,7 +346,7 @@ arc*-*-*) arm*-*-*) cpu_type=arm extra_objs="arm-builtins.o aarch-common.o" - extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve.h arm_cde.h" + extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h" target_type_format_char='%' c_target_objs="arm-c.o" cxx_target_objs="arm-c.o" diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index a8bad7b..b43898a 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -1833,10 +1833,22 @@ arm_init_acle_builtins (void) arm_builtin_datum *d = &acle_builtin_data[i]; arm_init_builtin (fcode, d, "__builtin_arm"); } +} - fcode = ARM_BUILTIN_CDE_PATTERN_START; +static void +arm_init_cde_builtins (void) +{ + unsigned int i, fcode = ARM_BUILTIN_CDE_PATTERN_START; for (i = 0; i < ARRAY_SIZE (cde_builtin_data); i++, fcode++) { + /* Only define CDE floating point builtins if the target has floating + point registers. NOTE: without HARD_FLOAT we don't have MVE, so we + can break out of this loop directly here. */ + if (!TARGET_MAYBE_HARD_FLOAT && fcode >= ARM_BUILTIN_vcx1si) + break; + /* Only define CDE/MVE builtins if MVE is available. */ + if (!TARGET_HAVE_MVE && fcode >= ARM_BUILTIN_vcx1qv16qi) + break; arm_builtin_cde_datum *cde = &cde_builtin_data[i]; arm_builtin_datum *d = &cde->base; arm_init_builtin (fcode, d, "__builtin_arm"); @@ -2628,6 +2640,9 @@ arm_init_builtins (void) arm_init_crypto_builtins (); } + if (TARGET_CDE) + arm_init_cde_builtins (); + arm_init_acle_builtins (); if (TARGET_MAYBE_HARD_FLOAT) @@ -4178,4 +4193,90 @@ arm_check_builtin_call (location_t , vec , tree fndecl, return true; } +/* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. This is currently only + used for the MVE related builtins for the CDE extension. + Here we ensure the type of arguments is such that the size is correct, and + then return a tree that describes the same function call but with the + relevant types cast as necessary. */ +tree +arm_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist) +{ + if (DECL_MD_FUNCTION_CODE (fndecl) <= ARM_BUILTIN_vcx1qv16qi + || DECL_MD_FUNCTION_CODE (fndecl) >= ARM_BUILTIN_MVE_BASE) + return NULL_TREE; + + vec *params = static_cast *> (arglist); + unsigned param_num = params ? params->length() : 0; + unsigned num_args = list_length (TYPE_ARG_TYPES (TREE_TYPE (fndecl))) - 1; + /* Ensure this function has the correct number of arguments. + This won't happen when using the intrinsics defined by the ACLE, since + they're exposed to the user via a wrapper in the arm_cde.h header that has + the correct number of arguments ... hence the compiler would already catch + an incorrect number of arguments there. + + It is still possible to get here if the user tries to call the __bulitin_* + functions directly. We could print some error message in this function, + but instead we leave it to the rest of the code to catch this problem in + the same way that other __builtin_* functions catch it. + + This does mean an odd error message, but it's consistent with the rest of + the builtins. */ + if (param_num != num_args) + return NULL_TREE; + + tree to_return = NULL_TREE; + /* Take the functions return type since that's the same type as the arguments + this function needs (the types of the builtin function all come from the + machine mode of the RTL pattern, and they're all the same and calculated + in the same way). */ + tree pattern_type = TREE_TYPE (TREE_TYPE (fndecl)); + + unsigned i; + for (i = 1; i < (param_num - 1); i++) + { + tree this_param = (*params)[i]; + if (TREE_CODE (this_param) == ERROR_MARK) + return NULL_TREE; + tree param_type = TREE_TYPE (this_param); + + /* Return value is cast to type that second argument originally was. + All non-constant arguments are cast to the return type calculated from + the RTL pattern. + + Set the return type to an unqualified version of the type of the first + parameter. The first parameter since that is how the intrinsics are + defined -- to always return the same type as the first polymorphic + argument. Unqualified version of the type since we don't want passing + a constant parameter to mean that the return value of the builtin is + also constant. */ + if (i == 1) + to_return = build_qualified_type (param_type, 0 MEM_STAT_INFO); + + /* The only requirement of these intrinsics on the type of the variable + is that it's 128 bits wide. All other types are valid and we simply + VIEW_CONVERT_EXPR them to the type of the underlying builtin. */ + tree type_size = TYPE_SIZE (param_type); + if (! tree_fits_shwi_p (type_size) + || tree_to_shwi (type_size) != 128) + { + error_at (loc, + "argument %u to function %qE is of type %qT which is not " + "known to be 128 bits wide", + i, fndecl, param_type); + return NULL_TREE; + } + + /* Only convert the argument if we actually need to. */ + if (! check_base_type (pattern_type, param_type)) + (*params)[i] = build1 (VIEW_CONVERT_EXPR, pattern_type, this_param); + } + tree call_expr = build_call_expr_loc_array (loc, fndecl, param_num, + params->address()); + + gcc_assert (to_return != NULL_TREE); + if (! check_base_type (to_return, pattern_type)) + return build1 (VIEW_CONVERT_EXPR, to_return, call_expr); + return call_expr; +} + #include "gt-arm-builtins.h" diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c index 7e92e8a..f173b33 100644 --- a/gcc/config/arm/arm-c.c +++ b/gcc/config/arm/arm-c.c @@ -28,6 +28,8 @@ #include "c-family/c-pragma.h" #include "stringpool.h" +tree arm_resolve_overloaded_builtin (location_t, tree, void*); + /* Output C specific EABI object attributes. These cannot be done in arm.c because they require information from the C frontend. */ @@ -360,6 +362,7 @@ arm_register_target_pragmas (void) { /* Update pragma hook to allow parsing #pragma GCC target. */ targetm.target_option.pragma_parse = arm_pragma_target_parse; + targetm.resolve_overloaded_builtin = arm_resolve_overloaded_builtin; #ifdef REGISTER_SUBTARGET_PRAGMAS REGISTER_SUBTARGET_PRAGMAS (); diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 83886a2..0126f39 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -582,6 +582,9 @@ extern const int arm_arch_cde_coproc_bits[]; #define ARM_VCDE_CONST_1 ((1 << 11) - 1) #define ARM_VCDE_CONST_2 ((1 << 6 ) - 1) #define ARM_VCDE_CONST_3 ((1 << 3 ) - 1) +#define ARM_MVE_CDE_CONST_1 ((1 << 12) - 1) +#define ARM_MVE_CDE_CONST_2 ((1 << 7 ) - 1) +#define ARM_MVE_CDE_CONST_3 ((1 << 4 ) - 1) #ifndef TARGET_DEFAULT #define TARGET_DEFAULT (MASK_APCS_FRAME) diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h index 9adcb99..e9564d5 100644 --- a/gcc/config/arm/arm_cde.h +++ b/gcc/config/arm/arm_cde.h @@ -140,6 +140,28 @@ extern "C" { #endif /* __ARM_FP || __ARM_FEATURE_MVE. */ #endif /* __ARM_FEATURE_CDE. */ +#if __ARM_FEATURE_MVE +#include "arm_mve_types.h" + +#define __arm_vcx1q_u8(coproc, imm) \ + (uint8x16_t)__builtin_arm_vcx1qv16qi(coproc, imm) +#define __arm_vcx1qa(coproc, acc, imm) \ + __builtin_arm_vcx1qav16qi(coproc, acc, imm) +#define __arm_vcx2q(coproc, n, imm) \ + __builtin_arm_vcx2qv16qi(coproc, n, imm) +#define __arm_vcx2q_u8(coproc, n, imm) \ + (uint8x16_t)__builtin_arm_vcx2qv16qi(coproc, n, imm) +#define __arm_vcx2qa(coproc, acc, n, imm) \ + __builtin_arm_vcx2qav16qi(coproc, acc, n, imm) +#define __arm_vcx3q(coproc, n, m, imm) \ + __builtin_arm_vcx3qv16qi(coproc, n, m, imm) +#define __arm_vcx3q_u8(coproc, n, m, imm) \ + (uint8x16_t)__builtin_arm_vcx3qv16qi(coproc, n, m, imm) +#define __arm_vcx3qa(coproc, acc, n, m, imm) \ + __builtin_arm_vcx3qav16qi(coproc, acc, n, m, imm) + +#endif + #ifdef __cplusplus } #endif diff --git a/gcc/config/arm/arm_cde_builtins.def b/gcc/config/arm/arm_cde_builtins.def index 8b2cfc0..1e107cf 100644 --- a/gcc/config/arm/arm_cde_builtins.def +++ b/gcc/config/arm/arm_cde_builtins.def @@ -37,4 +37,15 @@ CDE_VAR2 (CX_BINARY, vcx2a, si, di, ARM_VCDE_CONST_2, ECF_CONST) CDE_VAR2 (CX_BINARY, vcx3, si, di, ARM_VCDE_CONST_3, ECF_CONST) CDE_VAR2 (CX_TERNARY, vcx3a, si, di, ARM_VCDE_CONST_3, ECF_CONST) +/* NOTE: The MVE intrinsics must be defined at the end of this file, and with + vcx1q first. + These restrictions are relied on to determine which intrinsics need + overload resolution in `arm_resolve_overloaded_builtin`. */ +VAR1 (CX_IMM, vcx1q, v16qi, ARM_MVE_CDE_CONST_1, ECF_CONST) +VAR1 (CX_UNARY, vcx1qa, v16qi, ARM_MVE_CDE_CONST_1, ECF_CONST) +VAR1 (CX_UNARY, vcx2q, v16qi, ARM_MVE_CDE_CONST_2, ECF_CONST) +VAR1 (CX_BINARY, vcx2qa, v16qi, ARM_MVE_CDE_CONST_2, ECF_CONST) +VAR1 (CX_BINARY, vcx3q, v16qi, ARM_MVE_CDE_CONST_3, ECF_CONST) +VAR1 (CX_TERNARY, vcx3qa, v16qi, ARM_MVE_CDE_CONST_3, ECF_CONST) + #undef CDE_VAR2 diff --git a/gcc/config/arm/arm_mve.h b/gcc/config/arm/arm_mve.h index d75c430..4ab16b7 100644 --- a/gcc/config/arm/arm_mve.h +++ b/gcc/config/arm/arm_mve.h @@ -32,43 +32,7 @@ #ifndef __cplusplus #include #endif - -#if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ -typedef __fp16 float16_t; -typedef float float32_t; -typedef __simd128_float16_t float16x8_t; -typedef __simd128_float32_t float32x4_t; -#endif - -#if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ -typedef struct { float16x8_t val[2]; } float16x8x2_t; -typedef struct { float16x8_t val[4]; } float16x8x4_t; -typedef struct { float32x4_t val[2]; } float32x4x2_t; -typedef struct { float32x4_t val[4]; } float32x4x4_t; -#endif - -typedef uint16_t mve_pred16_t; -typedef __simd128_uint8_t uint8x16_t; -typedef __simd128_uint16_t uint16x8_t; -typedef __simd128_uint32_t uint32x4_t; -typedef __simd128_uint64_t uint64x2_t; -typedef __simd128_int8_t int8x16_t; -typedef __simd128_int16_t int16x8_t; -typedef __simd128_int32_t int32x4_t; -typedef __simd128_int64_t int64x2_t; - -typedef struct { int16x8_t val[2]; } int16x8x2_t; -typedef struct { int16x8_t val[4]; } int16x8x4_t; -typedef struct { int32x4_t val[2]; } int32x4x2_t; -typedef struct { int32x4_t val[4]; } int32x4x4_t; -typedef struct { int8x16_t val[2]; } int8x16x2_t; -typedef struct { int8x16_t val[4]; } int8x16x4_t; -typedef struct { uint16x8_t val[2]; } uint16x8x2_t; -typedef struct { uint16x8_t val[4]; } uint16x8x4_t; -typedef struct { uint32x4_t val[2]; } uint32x4x2_t; -typedef struct { uint32x4_t val[4]; } uint32x4x4_t; -typedef struct { uint8x16_t val[2]; } uint8x16x2_t; -typedef struct { uint8x16_t val[4]; } uint8x16x4_t; +#include "arm_mve_types.h" #ifndef __ARM_MVE_PRESERVE_USER_NAMESPACE #define vst4q(__addr, __value) __arm_vst4q(__addr, __value) @@ -13608,399 +13572,6 @@ __arm_vuninitializedq_s64 (void) return __uninit; } -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_s32 (int32x4_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_s64 (int64x2_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_s8 (int8x16_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_u16 (uint16x8_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_u32 (uint32x4_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_u64 (uint64x2_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_u8 (uint8x16_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_s16 (int16x8_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_s64 (int64x2_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_s8 (int8x16_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_u16 (uint16x8_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_u32 (uint32x4_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_u64 (uint64x2_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_u8 (uint8x16_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_s16 (int16x8_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_s32 (int32x4_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_s8 (int8x16_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_u16 (uint16x8_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_u32 (uint32x4_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_u64 (uint64x2_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_u8 (uint8x16_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_s16 (int16x8_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_s32 (int32x4_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_s64 (int64x2_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_u16 (uint16x8_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_u32 (uint32x4_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_u64 (uint64x2_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_u8 (uint8x16_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_s16 (int16x8_t __a) -{ - return (uint16x8_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_s32 (int32x4_t __a) -{ - return (uint16x8_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_s64 (int64x2_t __a) -{ - return (uint16x8_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_s8 (int8x16_t __a) -{ - return (uint16x8_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_u32 (uint32x4_t __a) -{ - return (uint16x8_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_u64 (uint64x2_t __a) -{ - return (uint16x8_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_u8 (uint8x16_t __a) -{ - return (uint16x8_t) __a; -} - - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_s16 (int16x8_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_s32 (int32x4_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_s64 (int64x2_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_s8 (int8x16_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_u16 (uint16x8_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_u64 (uint64x2_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_u8 (uint8x16_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_s16 (int16x8_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_s32 (int32x4_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_s64 (int64x2_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_s8 (int8x16_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_u16 (uint16x8_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_u32 (uint32x4_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_u8 (uint8x16_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_s16 (int16x8_t __a) -{ - return (uint8x16_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_s32 (int32x4_t __a) -{ - return (uint8x16_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_s64 (int64x2_t __a) -{ - return (uint8x16_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_s8 (int8x16_t __a) -{ - return (uint8x16_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_u16 (uint16x8_t __a) -{ - return (uint8x16_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_u32 (uint32x4_t __a) -{ - return (uint8x16_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_u64 (uint64x2_t __a) -{ - return (uint8x16_t) __a; -} - __extension__ extern __inline uint8x16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vddupq_m_n_u8 (uint8x16_t __inactive, uint32_t __a, const int __imm, mve_pred16_t __p) @@ -19653,244 +19224,6 @@ __arm_vuninitializedq_f32 (void) return __uninit; } -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_f16 (float16x8_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32_f32 (float32x4_t __a) -{ - return (int32x4_t) __a; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_f16 (float16x8_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16_f32 (float32x4_t __a) -{ - return (int16x8_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_f16 (float16x8_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64_f32 (float32x4_t __a) -{ - return (int64x2_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_f16 (float16x8_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8_f32 (float32x4_t __a) -{ - return (int8x16_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_f16 (float16x8_t __a) -{ - return (uint16x8_t) __a; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16_f32 (float32x4_t __a) -{ - return (uint16x8_t) __a; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_f16 (float16x8_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32_f32 (float32x4_t __a) -{ - return (uint32x4_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_f16 (float16x8_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64_f32 (float32x4_t __a) -{ - return (uint64x2_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_f16 (float16x8_t __a) -{ - return (uint8x16_t) __a; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8_f32 (float32x4_t __a) -{ - return (uint8x16_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_f32 (float32x4_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_s16 (int16x8_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_s32 (int32x4_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_s64 (int64x2_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_s8 (int8x16_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_u16 (uint16x8_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_u32 (uint32x4_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_u64 (uint64x2_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16_u8 (uint8x16_t __a) -{ - return (float16x8_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_f16 (float16x8_t __a) -{ - return (float32x4_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_s16 (int16x8_t __a) -{ - return (float32x4_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_s32 (int32x4_t __a) -{ - return (float32x4_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_s64 (int64x2_t __a) -{ - return (float32x4_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_s8 (int8x16_t __a) -{ - return (float32x4_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_u16 (uint16x8_t __a) -{ - return (float32x4_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_u32 (uint32x4_t __a) -{ - return (float32x4_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_u64 (uint64x2_t __a) -{ - return (float32x4_t) __a; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32_u8 (uint8x16_t __a) -{ - return (float32x4_t) __a; -} - __extension__ extern __inline float32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vldrwq_gather_base_wb_f32 (uint32x4_t * __addr, const int __offset) @@ -30867,398 +30200,6 @@ __arm_vuninitializedq (int64x2_t /* __v ATTRIBUTE UNUSED */) return __arm_vuninitializedq_s64 (); } -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (int32x4_t __a) -{ - return __arm_vreinterpretq_s16_s32 (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (int64x2_t __a) -{ - return __arm_vreinterpretq_s16_s64 (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (int8x16_t __a) -{ - return __arm_vreinterpretq_s16_s8 (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (uint16x8_t __a) -{ - return __arm_vreinterpretq_s16_u16 (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (uint32x4_t __a) -{ - return __arm_vreinterpretq_s16_u32 (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (uint64x2_t __a) -{ - return __arm_vreinterpretq_s16_u64 (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (uint8x16_t __a) -{ - return __arm_vreinterpretq_s16_u8 (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (int16x8_t __a) -{ - return __arm_vreinterpretq_s32_s16 (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (int64x2_t __a) -{ - return __arm_vreinterpretq_s32_s64 (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (int8x16_t __a) -{ - return __arm_vreinterpretq_s32_s8 (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (uint16x8_t __a) -{ - return __arm_vreinterpretq_s32_u16 (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (uint32x4_t __a) -{ - return __arm_vreinterpretq_s32_u32 (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (uint64x2_t __a) -{ - return __arm_vreinterpretq_s32_u64 (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (uint8x16_t __a) -{ - return __arm_vreinterpretq_s32_u8 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (int16x8_t __a) -{ - return __arm_vreinterpretq_s64_s16 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (int32x4_t __a) -{ - return __arm_vreinterpretq_s64_s32 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (int8x16_t __a) -{ - return __arm_vreinterpretq_s64_s8 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (uint16x8_t __a) -{ - return __arm_vreinterpretq_s64_u16 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (uint32x4_t __a) -{ - return __arm_vreinterpretq_s64_u32 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (uint64x2_t __a) -{ - return __arm_vreinterpretq_s64_u64 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (uint8x16_t __a) -{ - return __arm_vreinterpretq_s64_u8 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (int16x8_t __a) -{ - return __arm_vreinterpretq_s8_s16 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (int32x4_t __a) -{ - return __arm_vreinterpretq_s8_s32 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (int64x2_t __a) -{ - return __arm_vreinterpretq_s8_s64 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (uint16x8_t __a) -{ - return __arm_vreinterpretq_s8_u16 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (uint32x4_t __a) -{ - return __arm_vreinterpretq_s8_u32 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (uint64x2_t __a) -{ - return __arm_vreinterpretq_s8_u64 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (uint8x16_t __a) -{ - return __arm_vreinterpretq_s8_u8 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (int16x8_t __a) -{ - return __arm_vreinterpretq_u16_s16 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (int32x4_t __a) -{ - return __arm_vreinterpretq_u16_s32 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (int64x2_t __a) -{ - return __arm_vreinterpretq_u16_s64 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (int8x16_t __a) -{ - return __arm_vreinterpretq_u16_s8 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (uint32x4_t __a) -{ - return __arm_vreinterpretq_u16_u32 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (uint64x2_t __a) -{ - return __arm_vreinterpretq_u16_u64 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (uint8x16_t __a) -{ - return __arm_vreinterpretq_u16_u8 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (int16x8_t __a) -{ - return __arm_vreinterpretq_u32_s16 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (int32x4_t __a) -{ - return __arm_vreinterpretq_u32_s32 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (int64x2_t __a) -{ - return __arm_vreinterpretq_u32_s64 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (int8x16_t __a) -{ - return __arm_vreinterpretq_u32_s8 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (uint16x8_t __a) -{ - return __arm_vreinterpretq_u32_u16 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (uint64x2_t __a) -{ - return __arm_vreinterpretq_u32_u64 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (uint8x16_t __a) -{ - return __arm_vreinterpretq_u32_u8 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (int16x8_t __a) -{ - return __arm_vreinterpretq_u64_s16 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (int32x4_t __a) -{ - return __arm_vreinterpretq_u64_s32 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (int64x2_t __a) -{ - return __arm_vreinterpretq_u64_s64 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (int8x16_t __a) -{ - return __arm_vreinterpretq_u64_s8 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (uint16x8_t __a) -{ - return __arm_vreinterpretq_u64_u16 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (uint32x4_t __a) -{ - return __arm_vreinterpretq_u64_u32 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (uint8x16_t __a) -{ - return __arm_vreinterpretq_u64_u8 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (int16x8_t __a) -{ - return __arm_vreinterpretq_u8_s16 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (int32x4_t __a) -{ - return __arm_vreinterpretq_u8_s32 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (int64x2_t __a) -{ - return __arm_vreinterpretq_u8_s64 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (int8x16_t __a) -{ - return __arm_vreinterpretq_u8_s8 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (uint16x8_t __a) -{ - return __arm_vreinterpretq_u8_u16 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (uint32x4_t __a) -{ - return __arm_vreinterpretq_u8_u32 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (uint64x2_t __a) -{ - return __arm_vreinterpretq_u8_u64 (__a); -} - __extension__ extern __inline uint8x16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vddupq_m (uint8x16_t __inactive, uint32_t __a, const int __imm, mve_pred16_t __p) @@ -36168,244 +35109,6 @@ __arm_vuninitializedq (float32x4_t /* __v ATTRIBUTE UNUSED */) return __arm_vuninitializedq_f32 (); } -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (float16x8_t __a) -{ - return __arm_vreinterpretq_s32_f16 (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s32 (float32x4_t __a) -{ - return __arm_vreinterpretq_s32_f32 (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (float16x8_t __a) -{ - return __arm_vreinterpretq_s16_f16 (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s16 (float32x4_t __a) -{ - return __arm_vreinterpretq_s16_f32 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (float16x8_t __a) -{ - return __arm_vreinterpretq_s64_f16 (__a); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s64 (float32x4_t __a) -{ - return __arm_vreinterpretq_s64_f32 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (float16x8_t __a) -{ - return __arm_vreinterpretq_s8_f16 (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_s8 (float32x4_t __a) -{ - return __arm_vreinterpretq_s8_f32 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (float16x8_t __a) -{ - return __arm_vreinterpretq_u16_f16 (__a); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u16 (float32x4_t __a) -{ - return __arm_vreinterpretq_u16_f32 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (float16x8_t __a) -{ - return __arm_vreinterpretq_u32_f16 (__a); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u32 (float32x4_t __a) -{ - return __arm_vreinterpretq_u32_f32 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (float16x8_t __a) -{ - return __arm_vreinterpretq_u64_f16 (__a); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u64 (float32x4_t __a) -{ - return __arm_vreinterpretq_u64_f32 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (float16x8_t __a) -{ - return __arm_vreinterpretq_u8_f16 (__a); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_u8 (float32x4_t __a) -{ - return __arm_vreinterpretq_u8_f32 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (float32x4_t __a) -{ - return __arm_vreinterpretq_f16_f32 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (int16x8_t __a) -{ - return __arm_vreinterpretq_f16_s16 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (int32x4_t __a) -{ - return __arm_vreinterpretq_f16_s32 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (int64x2_t __a) -{ - return __arm_vreinterpretq_f16_s64 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (int8x16_t __a) -{ - return __arm_vreinterpretq_f16_s8 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (uint16x8_t __a) -{ - return __arm_vreinterpretq_f16_u16 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (uint32x4_t __a) -{ - return __arm_vreinterpretq_f16_u32 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (uint64x2_t __a) -{ - return __arm_vreinterpretq_f16_u64 (__a); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f16 (uint8x16_t __a) -{ - return __arm_vreinterpretq_f16_u8 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (float16x8_t __a) -{ - return __arm_vreinterpretq_f32_f16 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (int16x8_t __a) -{ - return __arm_vreinterpretq_f32_s16 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (int32x4_t __a) -{ - return __arm_vreinterpretq_f32_s32 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (int64x2_t __a) -{ - return __arm_vreinterpretq_f32_s64 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (int8x16_t __a) -{ - return __arm_vreinterpretq_f32_s8 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (uint16x8_t __a) -{ - return __arm_vreinterpretq_f32_u16 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (uint32x4_t __a) -{ - return __arm_vreinterpretq_f32_u32 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (uint64x2_t __a) -{ - return __arm_vreinterpretq_f32_u64 (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vreinterpretq_f32 (uint8x16_t __a) -{ - return __arm_vreinterpretq_f32_u8 (__a); -} - __extension__ extern __inline void __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vstrwq_scatter_base_wb (uint32x4_t * __addr, const int __offset, float32x4_t __value) diff --git a/gcc/config/arm/arm_mve_types.h b/gcc/config/arm/arm_mve_types.h new file mode 100644 index 0000000..0776f79 --- /dev/null +++ b/gcc/config/arm/arm_mve_types.h @@ -0,0 +1,1330 @@ +/* Arm MVE intrinsics include file. + + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by Arm. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +#ifndef _GCC_ARM_MVE_TYPES_H +#define _GCC_ARM_MVE_TYPES_H + +#if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ +typedef __fp16 float16_t; +typedef float float32_t; +typedef __simd128_float16_t float16x8_t; +typedef __simd128_float32_t float32x4_t; + +typedef struct { float16x8_t val[2]; } float16x8x2_t; +typedef struct { float16x8_t val[4]; } float16x8x4_t; +typedef struct { float32x4_t val[2]; } float32x4x2_t; +typedef struct { float32x4_t val[4]; } float32x4x4_t; +#endif + +typedef uint16_t mve_pred16_t; +typedef __simd128_uint8_t uint8x16_t; +typedef __simd128_uint16_t uint16x8_t; +typedef __simd128_uint32_t uint32x4_t; +typedef __simd128_uint64_t uint64x2_t; +typedef __simd128_int8_t int8x16_t; +typedef __simd128_int16_t int16x8_t; +typedef __simd128_int32_t int32x4_t; +typedef __simd128_int64_t int64x2_t; + +typedef struct { int16x8_t val[2]; } int16x8x2_t; +typedef struct { int16x8_t val[4]; } int16x8x4_t; +typedef struct { int32x4_t val[2]; } int32x4x2_t; +typedef struct { int32x4_t val[4]; } int32x4x4_t; +typedef struct { int8x16_t val[2]; } int8x16x2_t; +typedef struct { int8x16_t val[4]; } int8x16x4_t; +typedef struct { uint16x8_t val[2]; } uint16x8x2_t; +typedef struct { uint16x8_t val[4]; } uint16x8x4_t; +typedef struct { uint32x4_t val[2]; } uint32x4x2_t; +typedef struct { uint32x4_t val[4]; } uint32x4x4_t; +typedef struct { uint8x16_t val[2]; } uint8x16x2_t; +typedef struct { uint8x16_t val[4]; } uint8x16x4_t; + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_s32 (int32x4_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_s64 (int64x2_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_s8 (int8x16_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_u16 (uint16x8_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_u32 (uint32x4_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_u64 (uint64x2_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_u8 (uint8x16_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_s16 (int16x8_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_s64 (int64x2_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_s8 (int8x16_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_u16 (uint16x8_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_u32 (uint32x4_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_u64 (uint64x2_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_u8 (uint8x16_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_s16 (int16x8_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_s32 (int32x4_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_s8 (int8x16_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_u16 (uint16x8_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_u32 (uint32x4_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_u64 (uint64x2_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_u8 (uint8x16_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_s16 (int16x8_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_s32 (int32x4_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_s64 (int64x2_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_u16 (uint16x8_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_u32 (uint32x4_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_u64 (uint64x2_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_u8 (uint8x16_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_s16 (int16x8_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_s32 (int32x4_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_s64 (int64x2_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_s8 (int8x16_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_u32 (uint32x4_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_u64 (uint64x2_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_u8 (uint8x16_t __a) +{ + return (uint16x8_t) __a; +} + + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_s16 (int16x8_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_s32 (int32x4_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_s64 (int64x2_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_s8 (int8x16_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_u16 (uint16x8_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_u64 (uint64x2_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_u8 (uint8x16_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_s16 (int16x8_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_s32 (int32x4_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_s64 (int64x2_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_s8 (int8x16_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_u16 (uint16x8_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_u32 (uint32x4_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_u8 (uint8x16_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_s16 (int16x8_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_s32 (int32x4_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_s64 (int64x2_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_s8 (int8x16_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_u16 (uint16x8_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_u32 (uint32x4_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_u64 (uint64x2_t __a) +{ + return (uint8x16_t) __a; +} + +#if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_f16 (float16x8_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32_f32 (float32x4_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_f16 (float16x8_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16_f32 (float32x4_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_f16 (float16x8_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64_f32 (float32x4_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_f16 (float16x8_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8_f32 (float32x4_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_f16 (float16x8_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16_f32 (float32x4_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_f16 (float16x8_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32_f32 (float32x4_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_f16 (float16x8_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64_f32 (float32x4_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_f16 (float16x8_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8_f32 (float32x4_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_f32 (float32x4_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_s16 (int16x8_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_s32 (int32x4_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_s64 (int64x2_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_s8 (int8x16_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_u16 (uint16x8_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_u32 (uint32x4_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_u64 (uint64x2_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16_u8 (uint8x16_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_f16 (float16x8_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_s16 (int16x8_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_s32 (int32x4_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_s64 (int64x2_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_s8 (int8x16_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_u16 (uint16x8_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_u32 (uint32x4_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_u64 (uint64x2_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32_u8 (uint8x16_t __a) +{ + return (float32x4_t) __a; +} + +#endif + +#ifdef __cplusplus + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (int32x4_t __a) +{ + return __arm_vreinterpretq_s16_s32 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (int64x2_t __a) +{ + return __arm_vreinterpretq_s16_s64 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (int8x16_t __a) +{ + return __arm_vreinterpretq_s16_s8 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (uint16x8_t __a) +{ + return __arm_vreinterpretq_s16_u16 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (uint32x4_t __a) +{ + return __arm_vreinterpretq_s16_u32 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (uint64x2_t __a) +{ + return __arm_vreinterpretq_s16_u64 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (uint8x16_t __a) +{ + return __arm_vreinterpretq_s16_u8 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (int16x8_t __a) +{ + return __arm_vreinterpretq_s32_s16 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (int64x2_t __a) +{ + return __arm_vreinterpretq_s32_s64 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (int8x16_t __a) +{ + return __arm_vreinterpretq_s32_s8 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (uint16x8_t __a) +{ + return __arm_vreinterpretq_s32_u16 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (uint32x4_t __a) +{ + return __arm_vreinterpretq_s32_u32 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (uint64x2_t __a) +{ + return __arm_vreinterpretq_s32_u64 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (uint8x16_t __a) +{ + return __arm_vreinterpretq_s32_u8 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (int16x8_t __a) +{ + return __arm_vreinterpretq_s64_s16 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (int32x4_t __a) +{ + return __arm_vreinterpretq_s64_s32 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (int8x16_t __a) +{ + return __arm_vreinterpretq_s64_s8 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (uint16x8_t __a) +{ + return __arm_vreinterpretq_s64_u16 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (uint32x4_t __a) +{ + return __arm_vreinterpretq_s64_u32 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (uint64x2_t __a) +{ + return __arm_vreinterpretq_s64_u64 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (uint8x16_t __a) +{ + return __arm_vreinterpretq_s64_u8 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (int16x8_t __a) +{ + return __arm_vreinterpretq_s8_s16 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (int32x4_t __a) +{ + return __arm_vreinterpretq_s8_s32 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (int64x2_t __a) +{ + return __arm_vreinterpretq_s8_s64 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (uint16x8_t __a) +{ + return __arm_vreinterpretq_s8_u16 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (uint32x4_t __a) +{ + return __arm_vreinterpretq_s8_u32 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (uint64x2_t __a) +{ + return __arm_vreinterpretq_s8_u64 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (uint8x16_t __a) +{ + return __arm_vreinterpretq_s8_u8 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (int16x8_t __a) +{ + return __arm_vreinterpretq_u16_s16 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (int32x4_t __a) +{ + return __arm_vreinterpretq_u16_s32 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (int64x2_t __a) +{ + return __arm_vreinterpretq_u16_s64 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (int8x16_t __a) +{ + return __arm_vreinterpretq_u16_s8 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (uint32x4_t __a) +{ + return __arm_vreinterpretq_u16_u32 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (uint64x2_t __a) +{ + return __arm_vreinterpretq_u16_u64 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (uint8x16_t __a) +{ + return __arm_vreinterpretq_u16_u8 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (int16x8_t __a) +{ + return __arm_vreinterpretq_u32_s16 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (int32x4_t __a) +{ + return __arm_vreinterpretq_u32_s32 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (int64x2_t __a) +{ + return __arm_vreinterpretq_u32_s64 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (int8x16_t __a) +{ + return __arm_vreinterpretq_u32_s8 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (uint16x8_t __a) +{ + return __arm_vreinterpretq_u32_u16 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (uint64x2_t __a) +{ + return __arm_vreinterpretq_u32_u64 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (uint8x16_t __a) +{ + return __arm_vreinterpretq_u32_u8 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (int16x8_t __a) +{ + return __arm_vreinterpretq_u64_s16 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (int32x4_t __a) +{ + return __arm_vreinterpretq_u64_s32 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (int64x2_t __a) +{ + return __arm_vreinterpretq_u64_s64 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (int8x16_t __a) +{ + return __arm_vreinterpretq_u64_s8 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (uint16x8_t __a) +{ + return __arm_vreinterpretq_u64_u16 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (uint32x4_t __a) +{ + return __arm_vreinterpretq_u64_u32 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (uint8x16_t __a) +{ + return __arm_vreinterpretq_u64_u8 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (int16x8_t __a) +{ + return __arm_vreinterpretq_u8_s16 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (int32x4_t __a) +{ + return __arm_vreinterpretq_u8_s32 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (int64x2_t __a) +{ + return __arm_vreinterpretq_u8_s64 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (int8x16_t __a) +{ + return __arm_vreinterpretq_u8_s8 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (uint16x8_t __a) +{ + return __arm_vreinterpretq_u8_u16 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (uint32x4_t __a) +{ + return __arm_vreinterpretq_u8_u32 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (uint64x2_t __a) +{ + return __arm_vreinterpretq_u8_u64 (__a); +} + +#if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (float16x8_t __a) +{ + return __arm_vreinterpretq_s32_f16 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s32 (float32x4_t __a) +{ + return __arm_vreinterpretq_s32_f32 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (float16x8_t __a) +{ + return __arm_vreinterpretq_s16_f16 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s16 (float32x4_t __a) +{ + return __arm_vreinterpretq_s16_f32 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (float16x8_t __a) +{ + return __arm_vreinterpretq_s64_f16 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s64 (float32x4_t __a) +{ + return __arm_vreinterpretq_s64_f32 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (float16x8_t __a) +{ + return __arm_vreinterpretq_s8_f16 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_s8 (float32x4_t __a) +{ + return __arm_vreinterpretq_s8_f32 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (float16x8_t __a) +{ + return __arm_vreinterpretq_u16_f16 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u16 (float32x4_t __a) +{ + return __arm_vreinterpretq_u16_f32 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (float16x8_t __a) +{ + return __arm_vreinterpretq_u32_f16 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u32 (float32x4_t __a) +{ + return __arm_vreinterpretq_u32_f32 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (float16x8_t __a) +{ + return __arm_vreinterpretq_u64_f16 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u64 (float32x4_t __a) +{ + return __arm_vreinterpretq_u64_f32 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (float16x8_t __a) +{ + return __arm_vreinterpretq_u8_f16 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_u8 (float32x4_t __a) +{ + return __arm_vreinterpretq_u8_f32 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (float32x4_t __a) +{ + return __arm_vreinterpretq_f16_f32 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (int16x8_t __a) +{ + return __arm_vreinterpretq_f16_s16 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (int32x4_t __a) +{ + return __arm_vreinterpretq_f16_s32 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (int64x2_t __a) +{ + return __arm_vreinterpretq_f16_s64 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (int8x16_t __a) +{ + return __arm_vreinterpretq_f16_s8 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (uint16x8_t __a) +{ + return __arm_vreinterpretq_f16_u16 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (uint32x4_t __a) +{ + return __arm_vreinterpretq_f16_u32 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (uint64x2_t __a) +{ + return __arm_vreinterpretq_f16_u64 (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f16 (uint8x16_t __a) +{ + return __arm_vreinterpretq_f16_u8 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (float16x8_t __a) +{ + return __arm_vreinterpretq_f32_f16 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (int16x8_t __a) +{ + return __arm_vreinterpretq_f32_s16 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (int32x4_t __a) +{ + return __arm_vreinterpretq_f32_s32 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (int64x2_t __a) +{ + return __arm_vreinterpretq_f32_s64 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (int8x16_t __a) +{ + return __arm_vreinterpretq_f32_s8 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (uint16x8_t __a) +{ + return __arm_vreinterpretq_f32_u16 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (uint32x4_t __a) +{ + return __arm_vreinterpretq_f32_u32 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (uint64x2_t __a) +{ + return __arm_vreinterpretq_f32_u64 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vreinterpretq_f32 (uint8x16_t __a) +{ + return __arm_vreinterpretq_f32_u8 (__a); +} +#endif /* __ARM_FEATURE_MVE & 2 (MVE floating point) */ +#endif /* __cplusplus */ + +#endif /* _GCC_ARM_MVE_H. */ diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index c49c14c..1ae0840 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -11301,3 +11301,74 @@ "vpst\;vshlct\t%q0, %1, %4" [(set_attr "type" "mve_move") (set_attr "length" "8")]) + +;; CDE instructions on MVE registers. + +(define_insn "arm_vcx1qv16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:SI 2 "const_int_mve_cde1_operand" "i")] + UNSPEC_VCDE))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vcx1\\tp%c1, %q0, #%c2" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx1qav16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:V16QI 2 "register_operand" "0") + (match_operand:SI 3 "const_int_mve_cde1_operand" "i")] + UNSPEC_VCDEA))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vcx1a\\tp%c1, %q0, #%c3" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx2qv16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:V16QI 2 "register_operand" "t") + (match_operand:SI 3 "const_int_mve_cde2_operand" "i")] + UNSPEC_VCDE))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vcx2\\tp%c1, %q0, %q2, #%c3" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx2qav16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:V16QI 2 "register_operand" "0") + (match_operand:V16QI 3 "register_operand" "t") + (match_operand:SI 4 "const_int_mve_cde2_operand" "i")] + UNSPEC_VCDEA))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vcx2a\\tp%c1, %q0, %q3, #%c4" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx3qv16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:V16QI 2 "register_operand" "t") + (match_operand:V16QI 3 "register_operand" "t") + (match_operand:SI 4 "const_int_mve_cde3_operand" "i")] + UNSPEC_VCDE))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vcx3\\tp%c1, %q0, %q2, %q3, #%c4" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx3qav16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:V16QI 2 "register_operand" "0") + (match_operand:V16QI 3 "register_operand" "t") + (match_operand:V16QI 4 "register_operand" "t") + (match_operand:SI 5 "const_int_mve_cde3_operand" "i")] + UNSPEC_VCDEA))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vcx3a\\tp%c1, %q0, %q3, %q4, #%c5" + [(set_attr "type" "coproc")] +) diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 3ad47d2..009862e 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -255,6 +255,18 @@ (and (match_operand 0 "const_int_operand") (match_test "IN_RANGE (UINTVAL (op), 0, ARM_VCDE_CONST_3)"))) +(define_predicate "const_int_mve_cde1_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_MVE_CDE_CONST_1)"))) + +(define_predicate "const_int_mve_cde2_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_MVE_CDE_CONST_2)"))) + +(define_predicate "const_int_mve_cde3_operand" + (and (match_operand 0 "const_int_operand") + (match_test "IN_RANGE (UINTVAL (op), 0, ARM_MVE_CDE_CONST_3)"))) + ;; This doesn't have to do much because the constant is already checked ;; in the shift_operator predicate. (define_predicate "shift_amount_operand" diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-1.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-1.c new file mode 100644 index 0000000..0adacb5 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-1.c @@ -0,0 +1,42 @@ +#include "arm_cde.h" + +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ + +/* Ensure the error messages make sense when passing too many/too few arguments + to the intrinsic user-facing functions. */ +uint8x16_t test_invalid_arguments (uint8x16_t n, uint8x16_t m) +{ + uint8x16_t accum = __arm_vcx1q_u8 (0, 33, 1); /* { dg-error {macro "__arm_vcx1q_u8" passed 3 arguments, but takes just 2} } */ + accum += __arm_vcx1qa (0, accum, 33, 1); /* { dg-error {macro "__arm_vcx1qa" passed 4 arguments, but takes just 3} } */ + accum += __arm_vcx2q_u8 (0, n, 33, 1); /* { dg-error {macro "__arm_vcx2q_u8" passed 4 arguments, but takes just 3} } */ + accum += __arm_vcx2q (0, n, 33, 1); /* { dg-error {macro "__arm_vcx2q" passed 4 arguments, but takes just 3} } */ + accum += __arm_vcx2qa (0, accum, n, 33, 1); /* { dg-error {macro "__arm_vcx2qa" passed 5 arguments, but takes just 4} } */ + accum += __arm_vcx3q_u8 (0, n, m, 33, 1); /* { dg-error {macro "__arm_vcx3q_u8" passed 5 arguments, but takes just 4} } */ + accum += __arm_vcx3q (0, n, m, 33, 1); /* { dg-error {macro "__arm_vcx3q" passed 5 arguments, but takes just 4} } */ + accum += __arm_vcx3qa (0, accum, n, m, 33, 1); /* { dg-error {macro "__arm_vcx3qa" passed 6 arguments, but takes just 5} } */ + accum += __arm_vcx1q_u8 (0); /* { dg-error {macro "__arm_vcx1q_u8" requires 2 arguments, but only 1 given} } */ + accum += __arm_vcx1qa (0, accum); /* { dg-error {macro "__arm_vcx1qa" requires 3 arguments, but only 2 given} } */ + accum += __arm_vcx2q_u8 (0, n); /* { dg-error {macro "__arm_vcx2q_u8" requires 3 arguments, but only 2 given} } */ + accum += __arm_vcx2q (0, n); /* { dg-error {macro "__arm_vcx2q" requires 3 arguments, but only 2 given} } */ + accum += __arm_vcx2qa (0, accum, n); /* { dg-error {macro "__arm_vcx2qa" requires 4 arguments, but only 3 given} } */ + accum += __arm_vcx3q_u8 (0, n, m); /* { dg-error {macro "__arm_vcx3q_u8" requires 4 arguments, but only 3 given} } */ + accum += __arm_vcx3q (0, n, m); /* { dg-error {macro "__arm_vcx3q" requires 4 arguments, but only 3 given} } */ + accum += __arm_vcx3qa (0, accum, n, m); /* { dg-error {macro "__arm_vcx3qa" requires 5 arguments, but only 4 given} } */ + + /* The preprocessor complains that the macro was given an invalid number of + arguments, and because of that ends up not expanding the macro but + rather just leaving the macro name in the source code. That macro name + results in these errors. */ + /* { dg-error {'__arm_vcx1q_u8' undeclared \(first use in this function\)} "" { target { *-*-* } } 11 } */ + /* { dg-error {'__arm_vcx1qa' undeclared \(first use in this function\)} "" { target { *-*-* } } 12 } */ + /* { dg-error {'__arm_vcx2q_u8' undeclared \(first use in this function\)} "" { target { *-*-* } } 13 } */ + /* { dg-error {'__arm_vcx2q' undeclared \(first use in this function\)} "" { target { *-*-* } } 14 } */ + /* { dg-error {'__arm_vcx2qa' undeclared \(first use in this function\)} "" { target { *-*-* } } 15 } */ + /* { dg-error {'__arm_vcx3q_u8' undeclared \(first use in this function\)} "" { target { *-*-* } } 16 } */ + /* { dg-error {'__arm_vcx3q' undeclared \(first use in this function\)} "" { target { *-*-* } } 17 } */ + /* { dg-error {'__arm_vcx3qa' undeclared \(first use in this function\)} "" { target { *-*-* } } 18 } */ + + return accum; +} diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-2.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-2.c new file mode 100644 index 0000000..27e491a --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-2.c @@ -0,0 +1,103 @@ +#include "arm_cde.h" + +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ + +/* This file and cde-mve-error-tests.c are split since there are two kinds of + errors happening here. The errors in the other file cause the compiler to + not reach the errors found here, hence they need to be in a different file + so we can inspect these ones. */ + +uint8x16_t test_bad_immediates (uint8x16_t n, uint8x16_t m, int someval) +{ + uint8x16_t accum = (uint8x16_t)(uint32x4_t){0, 0, 0, 0}; + + /* We always different constants for the pairs (__arm_vcx2q and + __arm_vcx2q_u8) and (__arm_vcx3q and __arm_vcx3q_u8) despite them mapping + to the same builtin and us wanting to test the same thing in each block. + + This is because we have told the compiler that these functions are + constant and pure (i.e. produce a value solely based on their arguments + and have no side-effects). + + With that information the compiler eliminates duplicate calls to the + functions, and we only get error messages for one of the pairs. + Hence, in order to get error messages for both function calls, we use + different constants. */ + + /* `coproc' not enabled. */ + accum += __arm_vcx1q_u8 (1, 4095); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx1qa (1, accum, 4095); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx2q (1, n, 126); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx2q_u8 (1, n, 127); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx2qa (1, accum, n, 127); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx3q_u8 (1, n, m, 14); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx3q (1, n, m, 15); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx3qa (1, accum, n, m, 15); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + + /* `coproc' out of range. */ + accum += __arm_vcx1q_u8 (8, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx1qa (8, accum, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2q (8, n, 126); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2q_u8 (8, n, 127); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2qa (8, accum, n, 127); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3q_u8 (8, n, m, 14); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3q (8, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3qa (8, accum, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + + /* `imm' out of range. */ + accum += __arm_vcx1q_u8 (0, 4096); /* { dg-error {argument 2 must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx1qa (0, accum, 4096); /* { dg-error {argument 3 must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx2q (0, n, 128); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2q_u8 (0, n, 129); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2qa (0, accum, n, 128); /* { dg-error {argument 4 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx3q_u8 (0, n, m, 16); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3q (0, n, m, 17); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3qa (0, accum, n, m, 16); /* { dg-error {argument 5 must be a constant immediate in range \[0-15\]} } */ + + /* `imm' is not an immediate. */ + accum += __arm_vcx1q_u8 (0, someval); /* { dg-error {argument 2 must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx1qa (0, accum, someval); /* { dg-error {argument 3 must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx2q (0, n, someval); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2q_u8 (6, n, someval); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2qa (0, accum, n, someval); /* { dg-error {argument 4 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx3q_u8 (0, n, m, someval); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3q (6, n, m, someval); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3qa (0, accum, n, m, someval); /* { dg-error {argument 5 must be a constant immediate in range \[0-15\]} } */ + + /* `coproc' is not an immediate. */ + accum += __arm_vcx1q_u8 (someval, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx1qa (someval, accum, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2q (someval, n, 126); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2q_u8 (someval, n, 127); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2qa (someval, accum, n, 127); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3q_u8 (someval, n, m, 14); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3q (someval, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3qa (someval, accum, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + + /* `imm' is of wrong type. */ + accum += __arm_vcx1q_u8 (0, ""); /* { dg-error {argument 2 must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx1qa (0, accum, ""); /* { dg-error {argument 3 must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx2q (0, n, ""); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2q_u8 (0, n, "x"); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2qa (0, accum, n, ""); /* { dg-error {argument 4 must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx3q_u8 (0, n, m, ""); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3q (0, n, m, "x"); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3qa (0, accum, n, m, ""); /* { dg-error {argument 5 must be a constant immediate in range \[0-15\]} } */ + + /* `coproc' is of wrong type. */ + accum += __arm_vcx1q_u8 ("", 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx1qa ("", accum, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2q ("", n, 126); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2q_u8 ("", n, 127); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2qa ("", accum, n, 127); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3q_u8 ("", n, m, 14); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3q ("", n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3qa ("", accum, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + + /* { dg-warning {passing argument 2 of '__builtin_arm_vcx1qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 80 } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx1qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 90 } */ + + return accum; +} diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-3.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-3.c new file mode 100644 index 0000000..e637ab8 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-3.c @@ -0,0 +1,85 @@ +#include "arm_cde.h" + +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ + +uint32_t test (int8x16_t m, int8x16_t n) +{ + /* Bad types for polymophic arguments. */ + uint32_t accum = 0, n_int = 0; + accum += __arm_vcx1qa (0, accum, 4095); + accum += __arm_vcx2q (0, n_int, 126); + accum += __arm_vcx2q_u8 (0, n_int, 127); + accum += __arm_vcx2qa (0, accum, n, 127); + accum += __arm_vcx3q_u8 (0, n_int, m, 14); + accum += __arm_vcx3q (0, n_int, m, 15); + accum += __arm_vcx3qa (0, accum, n, m, 15); + + /* { dg-error {argument 1 to function '__builtin_arm_vcx1qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 11 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx1qav16qi'} "" { target *-*-* } 11 } */ + /* { dg-error {argument 1 to function '__builtin_arm_vcx2qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 12 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx2qv16qi'} "" { target *-*-* } 12 } */ + /* { dg-error {argument 1 to function '__builtin_arm_vcx2qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 13 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx2qv16qi'} "" { target *-*-* } 13 } */ + /* { dg-error {argument 1 to function '__builtin_arm_vcx2qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 14 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx2qav16qi'} "" { target *-*-* } 14 } */ + /* { dg-error {argument 1 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 15 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 15 } */ + /* { dg-error {argument 1 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 16 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 16 } */ + /* { dg-error {argument 1 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 17 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 17 } */ + return accum; +} + +int8x16_t test2 (int8x16_t m, int8x16_t n) +{ + uint32_t n_int = 0, m_int = 0; + int8x16_t accum = (int8x16_t)(uint64x2_t) { 0, 0 }; + accum += __arm_vcx2qa (0, accum, n_int, 127); + accum += __arm_vcx3q_u8 (0, n, m_int, 14); + accum += __arm_vcx3q (0, n, m_int, 15); + accum += __arm_vcx3qa (0, accum, n_int, m, 15); + accum += __arm_vcx3qa (0, accum, n_int, m, 15); + accum += __arm_vcx3qa (0, accum, n, m_int, 15); + accum += __arm_vcx3qa (0, accum, n, m_int, 15); + + /* { dg-error {argument 2 to function '__builtin_arm_vcx2qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 40 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx2qav16qi'} "" { target *-*-* } 40 } */ + /* { dg-error {argument 2 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 41 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 41 } */ + /* { dg-error {argument 2 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 42 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 42 } */ + /* { dg-error {argument 2 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 43 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 43 } */ + /* { dg-error {argument 2 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 44 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 44 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 45 } */ + /* { dg-error {incompatible type for argument 4 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 45 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 46 } */ + /* { dg-error {incompatible type for argument 4 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 46 } */ + return accum; +} + +/* Testing that undeclared variables work as expected. + (This to verify we fixed a problem hit during development). */ +int8x16_t test3 (int8x16_t m, int8x16_t n) +{ + int8x16_t accum = (int8x16_t)(uint64x2_t) { 0, 0 }; + accum += __arm_vcx1qa (0, accum_int, 4095); + accum += __arm_vcx2q (0, n_int, 126); + accum += __arm_vcx2q_u8 (0, n_int, 127); + accum += __arm_vcx2qa (0, accum, n_int, 127); + accum += __arm_vcx3q_u8 (0, n_int, m, 14); + accum += __arm_vcx3q_u8 (0, n, m_int, 14); + accum += __arm_vcx3q (0, n_int, m, 15); + accum += __arm_vcx3q (0, n, m_int, 15); + accum += __arm_vcx3qa (0, accum, n_int, m, 15); + accum += __arm_vcx3qa (0, accum, n_int, m_int, 15); + + /* { dg-error {'accum_int' undeclared \(first use in this function\)} "" { target *-*-* } 70 } */ + /* { dg-error {'n_int' undeclared \(first use in this function\)} "" { target *-*-* } 71 } */ + /* { dg-error {'m_int' undeclared \(first use in this function\)} "" { target *-*-* } 75 } */ + return accum; +} diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-full-assembly.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-full-assembly.c new file mode 100644 index 0000000..a10ff9f --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-full-assembly.c @@ -0,0 +1,557 @@ +/* { dg-do compile } */ +/* { dg-skip-if "Require optimisation to compile DCE tests" { *-*-* } { "-O0" "-mfloat-abi=softfp" } { "" } } */ +/* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ +/* We use -ffast-math so that the addition of 0.0 to a value is assumed to not + change the value. This means the tests for float types can use the same + trick of adding to a value initialised to zero to check whether the RTL + patterns correctly mark that the incoming value is not used. */ +/* { dg-additional-options "-ffast-math" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "cde-mve-tests.c" + +/* NOTE: + We avoid matching the functions returning a __builtin_neon_ti value since + there are variations between processors that make matching the whole + function difficult. + Since moving a TImode value into an MVE 'Q' register takes a few + temporaries, this leaves many instructions which can end up being + scheduled in different ways. Matching the ways this ends up getting + scheduled and restructured is awkward, and the extra tests for this one + data type don't seem to be worth the confusing testcases. */ + +/* +** test_cde_vcx1q_u8float16x8_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8float32x4_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8uint8x16_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8uint16x8_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8uint32x4_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8uint64x2_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8int8x16_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8int16x8_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8int32x4_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1q_u8int64x2_tintint: +** vcx1 p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qafloat16x8_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qafloat32x4_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qauint8x16_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qauint16x8_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qauint32x4_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qauint64x2_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qaint8x16_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qaint16x8_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qaint32x4_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx1qaint64x2_tintint: +** vldr\.64 d0, \.L([0-9]*) +** vldr\.64 d1, \.L\1\+8 +** vcx1a p0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8float16x8_tuint16x8_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8float16x8_tfloat32x4_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8float32x4_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8int64x2_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8int8x16_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8uint16x8_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8uint8x16_tint64x2_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8uint8x16_tint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8uint8x16_tuint16x8_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2q_u8uint8x16_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2qfloat16x8_tuint16x8_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2qfloat16x8_tfloat32x4_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2qfloat32x4_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2qint64x2_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2qint8x16_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2quint16x8_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2quint8x16_tint64x2_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2quint8x16_tint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2quint8x16_tuint16x8_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2quint8x16_tuint8x16_tint: +** vcx2 p0, q0, q0, #33 +** bx lr +*/ +/* +** test_cde_vcx2qafloat16x8_tuint16x8_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qafloat16x8_tfloat32x4_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qafloat32x4_tuint8x16_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qaint64x2_tuint8x16_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qaint8x16_tuint8x16_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qauint16x8_tuint8x16_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qauint8x16_tint64x2_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qauint8x16_tint8x16_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qauint8x16_tuint16x8_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx2qauint8x16_tuint8x16_tint: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx2a p0, (q[0-7]), q0, #33 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint16x8_tuint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint16x8_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_tuint16x8_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8float16x8_tfloat16x8_tfloat16x8_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8float32x4_tuint64x2_tfloat16x8_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8int8x16_tuint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint8x16_tint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_tint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8int64x2_tuint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint8x16_tint64x2_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_tint64x2_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3q_u8uint8x16_tint64x2_tint64x2_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3qfloat16x8_tfloat16x8_tfloat16x8_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3qfloat32x4_tuint64x2_tfloat16x8_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint16x8_tuint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint8x16_tuint16x8_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_tuint16x8_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3qint8x16_tuint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint8x16_tint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_tint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3qint64x2_tuint8x16_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint8x16_tint64x2_tuint8x16_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_tint64x2_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3quint8x16_tint64x2_tint64x2_t: +** vcx3 p0, q0, q0, q1, #12 +** bx lr +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_tuint8x16_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qafloat16x8_tfloat16x8_tfloat16x8_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qafloat32x4_tuint64x2_tfloat16x8_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qauint16x8_tuint8x16_tuint8x16_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qauint8x16_tuint16x8_tuint8x16_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_tuint16x8_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qaint8x16_tuint8x16_tuint8x16_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qauint8x16_tint8x16_tuint8x16_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_tint8x16_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qaint64x2_tuint8x16_tuint8x16_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qauint8x16_tint64x2_tuint8x16_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_tint64x2_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ +/* +** test_cde_vcx3qauint8x16_tint64x2_tint64x2_t: +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L([0-9]*) +** vldr\.64 d(?:[01][0-4]|[0-9]), \.L\1\+8 +** vcx3a p0, (q[0-7]), q0, q1, #12 +** vmov q0, \2 +** bx lr +*/ diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c new file mode 100644 index 0000000..11341cb --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c @@ -0,0 +1,722 @@ +#include "arm_cde.h" + +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ +/* { dg-final { check-function-bodies "**" "" } } */ + + +/* Test that the assembly is produced as expected. + Test that the same thing happens for each valid type. + (ensure we check *every* valid type, though we're not bothering with every + type combination, just checking "all same type" and "different types", + also want to check every valid type at least once) */ + +#define TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, accum_type, n_type, m_type, arguments) \ + accum_type test_cde_##name##accum_type##n_type##m_type ( \ + __attribute__ ((unused)) n_type n, \ + __attribute__ ((unused)) m_type m) \ + { \ + accum_type accum = (accum_type)(uint32x4_t){0,0,0,0}; \ + accum += (accum_type) __arm_##name arguments; \ + return accum; \ + } + +/* Use every valid type for the output -- demonstrate can use any 128 bit value + (which is a requirement for these intrinsics). */ +#define TEST_CDE_MVE_INTRINSIC_1(name, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, __builtin_neon_ti, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, float16x8_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, float32x4_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint16x8_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint32x4_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint64x2_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, int8x16_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, int16x8_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, int32x4_t, int, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, int64x2_t, int, int, arguments) \ + +#define TEST_CDE_MVE_INTRINSIC_2(name, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, __builtin_neon_ti, uint8x16_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, __builtin_neon_ti, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, float16x8_t, uint16x8_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, float16x8_t, float32x4_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, float32x4_t, uint8x16_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, int64x2_t, uint8x16_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, int8x16_t, uint8x16_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint16x8_t, uint8x16_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, int64x2_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, int8x16_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint16x8_t, int, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint8x16_t, int, arguments) + +#define TEST_CDE_MVE_INTRINSIC_3(name, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, __builtin_neon_ti, uint8x16_t, uint8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint8x16_t, __builtin_neon_ti, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint8x16_t, uint8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, float16x8_t, float16x8_t, float16x8_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, float32x4_t, uint64x2_t, float16x8_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint16x8_t, uint8x16_t, uint8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint16x8_t, uint8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint8x16_t, uint16x8_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, int8x16_t, uint8x16_t, uint8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, int8x16_t, uint8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint8x16_t, int8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, int64x2_t, uint8x16_t, uint8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, int64x2_t, uint8x16_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint8x16_t, int64x2_t, arguments) \ + TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, int64x2_t, int64x2_t, arguments) + +TEST_CDE_MVE_INTRINSIC_1(vcx1q_u8, (0, 33)) +TEST_CDE_MVE_INTRINSIC_1(vcx1qa, (0, accum, 33)) + +TEST_CDE_MVE_INTRINSIC_2(vcx2q_u8, (0, n, 33)) +TEST_CDE_MVE_INTRINSIC_2(vcx2q, (0, n, 33)) +TEST_CDE_MVE_INTRINSIC_2(vcx2qa, (0, accum, n, 33)) + +TEST_CDE_MVE_INTRINSIC_3(vcx3q_u8, (0, n, m, 12)) +TEST_CDE_MVE_INTRINSIC_3(vcx3q, (0, n, m, 12)) +TEST_CDE_MVE_INTRINSIC_3(vcx3qa, (0, accum, n, m, 12)) + +/* This testcase checks that in all compilations this C code produces the + expected CDE instructions from the above intrinsics. + + Here we check that there are the expected number of `vcx*` occurences, and + that each function has the expected form in it. + + Another testcase (cde-mve-full-assembly.c) checks that when using + `-mfloat-abi=hard` and when compiled with an FPU the above C code produces + code that demonstrates the compiler knows that the intrinsics are constant + and pure, and that demonstrates the compiler generates sane code from them. + That testcase needs these special arguments so it can ignore things like + accounting for the soft float ABI or leftovers from temporaries that are + later removed when generating code for a target with Floating Point + registers but without an FPU. */ + +/* { dg-final { scan-assembler-times "\tvcx1\t" 11 } } */ +/* { dg-final { scan-assembler-times "\tvcx1a\t" 11 } } */ +/* { dg-final { scan-assembler-times "\tvcx2\t" 24 } } */ +/* { dg-final { scan-assembler-times "\tvcx2a\t" 12 } } */ +/* { dg-final { scan-assembler-times "\tvcx3\t" 30 } } */ +/* { dg-final { scan-assembler-times "\tvcx3a\t" 15 } } */ + +/* +** test_cde_vcx1q_u8__builtin_neon_tiintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8float16x8_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8float32x4_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8uint8x16_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8uint16x8_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8uint32x4_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8uint64x2_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8int8x16_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8int16x8_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8int32x4_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1q_u8int64x2_tintint: +** ... +** vcx1 p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qa__builtin_neon_tiintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qafloat16x8_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qafloat32x4_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qauint8x16_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qauint16x8_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qauint32x4_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qauint64x2_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qaint8x16_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qaint16x8_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qaint32x4_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx1qaint64x2_tintint: +** ... +** vcx1a p0, q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8__builtin_neon_tiuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8uint8x16_t__builtin_neon_tiint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8float16x8_tuint16x8_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8float16x8_tfloat32x4_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8float32x4_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8int64x2_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8int8x16_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8uint16x8_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8uint8x16_tint64x2_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8uint8x16_tint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8uint8x16_tuint16x8_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q_u8uint8x16_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2q__builtin_neon_tiuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2quint8x16_t__builtin_neon_tiint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qfloat16x8_tuint16x8_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qfloat16x8_tfloat32x4_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qfloat32x4_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qint64x2_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qint8x16_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2quint16x8_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2quint8x16_tint64x2_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2quint8x16_tint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2quint8x16_tuint16x8_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2quint8x16_tuint8x16_tint: +** ... +** vcx2 p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qa__builtin_neon_tiuint8x16_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qauint8x16_t__builtin_neon_tiint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qafloat16x8_tuint16x8_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qafloat16x8_tfloat32x4_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qafloat32x4_tuint8x16_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qaint64x2_tuint8x16_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qaint8x16_tuint8x16_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qauint16x8_tuint8x16_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qauint8x16_tint64x2_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qauint8x16_tint8x16_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qauint8x16_tuint16x8_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx2qauint8x16_tuint8x16_tint: +** ... +** vcx2a p0, q[0-7], q[0-7], #33 +** ... +*/ +/* +** test_cde_vcx3q_u8__builtin_neon_tiuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_t__builtin_neon_ti: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint16x8_tuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint16x8_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_tuint16x8_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8float16x8_tfloat16x8_tfloat16x8_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8float32x4_tuint64x2_tfloat16x8_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8int8x16_tuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_tint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8int64x2_tuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tint64x2_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tuint8x16_tint64x2_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q_u8uint8x16_tint64x2_tint64x2_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3q__builtin_neon_tiuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_t__builtin_neon_ti: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qfloat16x8_tfloat16x8_tfloat16x8_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qfloat32x4_tuint64x2_tfloat16x8_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint16x8_tuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tuint16x8_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_tuint16x8_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qint8x16_tuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_tint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qint64x2_tuint8x16_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tint64x2_tuint8x16_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tuint8x16_tint64x2_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3quint8x16_tint64x2_tint64x2_t: +** ... +** vcx3 p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qa__builtin_neon_tiuint8x16_tuint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_t__builtin_neon_ti: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_tuint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qafloat16x8_tfloat16x8_tfloat16x8_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qafloat32x4_tuint64x2_tfloat16x8_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint16x8_tuint8x16_tuint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tuint16x8_tuint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_tuint16x8_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qaint8x16_tuint8x16_tuint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tint8x16_tuint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_tint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qaint64x2_tuint8x16_tuint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tint64x2_tuint8x16_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tuint8x16_tint64x2_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ +/* +** test_cde_vcx3qauint8x16_tint64x2_tint64x2_t: +** ... +** vcx3a p0, q[0-7], q[0-7], q[0-7], #12 +** ... +*/ + diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 1e8c0e2..e42d0ea 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -5120,11 +5120,14 @@ foreach { armfunc armflag armdef } { "-march=armv8-m.main+cdecp0+cdecp6 -mthumb" "defined (__ARM_FEATURE_CDE)" arm_v8m_main_cde_fp - "-march=armv8-m.main+fp+cdecp0+cdecp6 -mthumb" + "-march=armv8-m.main+fp+cdecp0+cdecp6 -mthumb -mfpu=auto" "defined (__ARM_FEATURE_CDE) && defined (__ARM_FP)" arm_v8_1m_main_cde_mve - "-march=armv8.1-m.main+mve+cdecp0+cdecp6 -mthumb" + "-march=armv8.1-m.main+mve+cdecp0+cdecp6 -mthumb -mfpu=auto" "defined (__ARM_FEATURE_CDE) && defined (__ARM_FEATURE_MVE)" + arm_v8_1m_main_cde_mve_fp + "-march=armv8.1-m.main+mve.fp+cdecp0+cdecp6 -mthumb -mfpu=auto" + "defined (__ARM_FEATURE_CDE) || __ARM_FEATURE_MVE == 3" } { eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef ] { proc check_effective_target_FUNC_ok_nocache { } { -- cgit v1.1 From ef684c7827361e7e66543b4511fb1ca15ace4b1f Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Wed, 8 Apr 2020 16:06:48 +0100 Subject: [Arm] Implement CDE predicated intrinsics for MVE registers These intrinsics are the predicated version of the intrinsics inroduced in https://gcc.gnu.org/pipermail/gcc-patches/2020-March/542725.html. These are not yet public on developer.arm.com but we have reached internal consensus on them. The approach follows the same method as for the CDE intrinsics for MVE registers, most notably using the same arm_resolve_overloaded_builtin function with minor modifications. The resolver hook has been moved from arm-builtins.c to arm-c.c so it can access the c-common function build_function_call_vec. This function is needed to perform the same checks on arguments as a normal C or C++ function would perform. It is fine to put this resolver in arm-c.c since it's only use is for the ACLE functions, and these are only available in C/C++. So that the resolver function has access to information it needs from the builtins, we put two query functions into arm-builtins.c and use them from arm-c.c. We rely on the order that the builtins are defined in gcc/config/arm/arm_cde_builtins.def, knowing that the predicated versions come after the non-predicated versions. The machine description patterns for these builtins are simpler than those for the non-predicated versions, since the accumulator versions *and* non-accumulator versions both need an input vector now. The input vector is needed for the non-accumulator version to describe the original values for those lanes that are not updated during the merge operation. We additionally need to introduce qualifiers for these new builtins, which follow the same pattern as the non-predicated versions but with an extra argument to describe the predicate. Error message changes: - We directly mention the builtin argument when complaining that an argument is not in the correct range. This more closely matches the C error messages. - We ensure the resolver complains about *all* invalid arguments to a function instead of just the first one. - The resolver error messages index arguments from 1 instead of 0 to match the arguments coming from the C/C++ frontend. In order to allow the user to give an argument for the merging predicate when they don't care what data is stored in the 'false' lanes, we also move the __arm_vuninitializedq* intrinsics from arm_mve.h to arm_mve_types.h which is shared with arm_cde.h. We only move the fully type-specified `__arm_vuninitializedq*` intrinsics and not the polymorphic versions, since moving the polymorphic versions requires moving the _Generic framework as well as just the intrinsics we're interested in. This matches the approach taken for the `__arm_vreinterpret*` functions in this include file. This patch also contains a slight change in spacing of an existing assembly instruction to be emitted. This is just to help writing tests -- vmsr usually has a tab and a space between the mnemonic and the first argument, but in one case it just has a tab -- making all the same helps make test regexps simpler. Testing Done: Bootstrap and full regtest on arm-none-linux-gnueabihf Full regtest on arm-none-eabi All testing done with a local fix for the bugzilla PR below. That bugzilla currently causes multiple ICE's on the tests added in this patch. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94341 gcc/ChangeLog: 2020-04-02 Matthew Malcomson * config/arm/arm-builtins.c (CX_UNARY_UNONE_QUALIFIERS): New. (CX_BINARY_UNONE_QUALIFIERS): New. (CX_TERNARY_UNONE_QUALIFIERS): New. (arm_resolve_overloaded_builtin): Move to arm-c.c. (arm_expand_builtin_args): Update error message. (enum resolver_ident): New. (arm_describe_resolver): New. (arm_cde_end_args): New. * config/arm/arm-builtins.h: New file. * config/arm/arm-c.c (arm_resolve_overloaded_builtin): New. (arm_resolve_cde_builtin): Moved from arm-builtins.c. * config/arm/arm_cde.h (__arm_vcx1q_m, __arm_vcx1qa_m, __arm_vcx2q_m, __arm_vcx2qa_m, __arm_vcx3q_m, __arm_vcx3qa_m): New. * config/arm/arm_cde_builtins.def (vcx1q_p_, vcx1qa_p_, vcx2q_p_, vcx2qa_p_, vcx3q_p_, vcx3qa_p_): New builtin defs. * config/arm/iterators.md (CDE_VCX): New int iterator. (a) New int attribute. * config/arm/mve.md (arm_vcx1q_p_v16qi, arm_vcx2q_p_v16qi, arm_vcx3q_p_v16qi): New patterns. * config/arm/vfp.md (thumb2_movhi_fp16): Extra space in assembly. gcc/testsuite/ChangeLog: 2020-04-02 Matthew Malcomson * gcc.target/arm/acle/cde-errors.c: Add predicated forms. * gcc.target/arm/acle/cde-mve-error-1.c: Add predicated forms. * gcc.target/arm/acle/cde-mve-error-2.c: Add predicated forms. * gcc.target/arm/acle/cde-mve-error-3.c: Add predicated forms. * gcc.target/arm/acle/cde-mve-full-assembly.c: Add predicated forms. * gcc.target/arm/acle/cde-mve-tests.c: Add predicated forms. * gcc.target/arm/acle/cde_v_1_err.c (test_imm_range): Update for error message format change. * gcc.target/arm/mve/intrinsics/vldrwq_gather_base_wb_z_f32.c: Update scan-assembler regexp. --- gcc/config/arm/arm-builtins.c | 126 ++--- gcc/config/arm/arm-builtins.h | 35 ++ gcc/config/arm/arm-c.c | 114 +++- gcc/config/arm/arm_cde.h | 15 + gcc/config/arm/arm_cde_builtins.def | 9 +- gcc/config/arm/arm_mve.h | 160 ------ gcc/config/arm/arm_mve_types.h | 160 ++++++ gcc/config/arm/iterators.md | 5 + gcc/config/arm/mve.md | 42 ++ gcc/config/arm/vfp.md | 2 +- gcc/testsuite/gcc.target/arm/acle/cde-errors.c | 56 +- .../gcc.target/arm/acle/cde-mve-error-1.c | 20 + .../gcc.target/arm/acle/cde-mve-error-2.c | 152 ++++-- .../gcc.target/arm/acle/cde-mve-error-3.c | 117 ++-- .../gcc.target/arm/acle/cde-mve-full-assembly.c | 594 +++++++++++++++++++++ gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c | 583 +++++++++++++++++++- gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c | 24 +- .../mve/intrinsics/vldrwq_gather_base_wb_z_f32.c | 2 +- 18 files changed, 1840 insertions(+), 376 deletions(-) create mode 100644 gcc/config/arm/arm-builtins.h (limited to 'gcc') diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index b43898a..16d2fb0 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -42,6 +42,7 @@ #include "case-cfn-macros.h" #include "sbitmap.h" #include "stringpool.h" +#include "arm-builtins.h" #define SIMD_MAX_BUILTIN_ARGS 7 @@ -334,6 +335,32 @@ arm_cx_ternary_qualifiers[SIMD_MAX_BUILTIN_ARGS] qualifier_unsigned_immediate }; #define CX_TERNARY_QUALIFIERS (arm_cx_ternary_qualifiers) +/* T (immediate, T, unsigned immediate). */ +static enum arm_type_qualifiers +arm_cx_unary_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_immediate, qualifier_none, + qualifier_unsigned_immediate, + qualifier_unsigned }; +#define CX_UNARY_UNONE_QUALIFIERS (arm_cx_unary_unone_qualifiers) + +/* T (immediate, T, T, unsigned immediate). */ +static enum arm_type_qualifiers +arm_cx_binary_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_immediate, + qualifier_none, qualifier_none, + qualifier_unsigned_immediate, + qualifier_unsigned }; +#define CX_BINARY_UNONE_QUALIFIERS (arm_cx_binary_unone_qualifiers) + +/* T (immediate, T, T, T, unsigned immediate). */ +static enum arm_type_qualifiers +arm_cx_ternary_unone_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_immediate, + qualifier_none, qualifier_none, qualifier_none, + qualifier_unsigned_immediate, + qualifier_unsigned }; +#define CX_TERNARY_UNONE_QUALIFIERS (arm_cx_ternary_unone_qualifiers) + /* The first argument (return type) of a store should be void type, which we represent with qualifier_void. Their first operand will be a DImode pointer to the location to store to, so we must use @@ -3064,8 +3091,12 @@ constant_arg: ARM_CDE_CONST_COPROC); } else - error ("%Kargument %d must be a constant immediate " + /* Here we mention the builtin name to follow the same + format that the C/C++ frontends use for referencing + a given argument index. */ + error ("%Kargument %d to %qE must be a constant immediate " "in range [0-%d]", exp, argc + 1, + arm_builtin_decls[fcode], cde_builtin_data[fcode - ARM_BUILTIN_CDE_PATTERN_START].imm_max); } @@ -4193,90 +4224,19 @@ arm_check_builtin_call (location_t , vec , tree fndecl, return true; } -/* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. This is currently only - used for the MVE related builtins for the CDE extension. - Here we ensure the type of arguments is such that the size is correct, and - then return a tree that describes the same function call but with the - relevant types cast as necessary. */ -tree -arm_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist) +enum resolver_ident +arm_describe_resolver (tree fndecl) { - if (DECL_MD_FUNCTION_CODE (fndecl) <= ARM_BUILTIN_vcx1qv16qi - || DECL_MD_FUNCTION_CODE (fndecl) >= ARM_BUILTIN_MVE_BASE) - return NULL_TREE; - - vec *params = static_cast *> (arglist); - unsigned param_num = params ? params->length() : 0; - unsigned num_args = list_length (TYPE_ARG_TYPES (TREE_TYPE (fndecl))) - 1; - /* Ensure this function has the correct number of arguments. - This won't happen when using the intrinsics defined by the ACLE, since - they're exposed to the user via a wrapper in the arm_cde.h header that has - the correct number of arguments ... hence the compiler would already catch - an incorrect number of arguments there. - - It is still possible to get here if the user tries to call the __bulitin_* - functions directly. We could print some error message in this function, - but instead we leave it to the rest of the code to catch this problem in - the same way that other __builtin_* functions catch it. - - This does mean an odd error message, but it's consistent with the rest of - the builtins. */ - if (param_num != num_args) - return NULL_TREE; - - tree to_return = NULL_TREE; - /* Take the functions return type since that's the same type as the arguments - this function needs (the types of the builtin function all come from the - machine mode of the RTL pattern, and they're all the same and calculated - in the same way). */ - tree pattern_type = TREE_TYPE (TREE_TYPE (fndecl)); - - unsigned i; - for (i = 1; i < (param_num - 1); i++) - { - tree this_param = (*params)[i]; - if (TREE_CODE (this_param) == ERROR_MARK) - return NULL_TREE; - tree param_type = TREE_TYPE (this_param); - - /* Return value is cast to type that second argument originally was. - All non-constant arguments are cast to the return type calculated from - the RTL pattern. - - Set the return type to an unqualified version of the type of the first - parameter. The first parameter since that is how the intrinsics are - defined -- to always return the same type as the first polymorphic - argument. Unqualified version of the type since we don't want passing - a constant parameter to mean that the return value of the builtin is - also constant. */ - if (i == 1) - to_return = build_qualified_type (param_type, 0 MEM_STAT_INFO); - - /* The only requirement of these intrinsics on the type of the variable - is that it's 128 bits wide. All other types are valid and we simply - VIEW_CONVERT_EXPR them to the type of the underlying builtin. */ - tree type_size = TYPE_SIZE (param_type); - if (! tree_fits_shwi_p (type_size) - || tree_to_shwi (type_size) != 128) - { - error_at (loc, - "argument %u to function %qE is of type %qT which is not " - "known to be 128 bits wide", - i, fndecl, param_type); - return NULL_TREE; - } - - /* Only convert the argument if we actually need to. */ - if (! check_base_type (pattern_type, param_type)) - (*params)[i] = build1 (VIEW_CONVERT_EXPR, pattern_type, this_param); - } - tree call_expr = build_call_expr_loc_array (loc, fndecl, param_num, - params->address()); + if (DECL_MD_FUNCTION_CODE (fndecl) >= ARM_BUILTIN_vcx1qv16qi + && DECL_MD_FUNCTION_CODE (fndecl) < ARM_BUILTIN_MVE_BASE) + return arm_cde_resolver; + return arm_no_resolver; +} - gcc_assert (to_return != NULL_TREE); - if (! check_base_type (to_return, pattern_type)) - return build1 (VIEW_CONVERT_EXPR, to_return, call_expr); - return call_expr; +unsigned +arm_cde_end_args (tree fndecl) +{ + return DECL_MD_FUNCTION_CODE (fndecl) >= ARM_BUILTIN_vcx1q_p_v16qi ? 2 : 1; } #include "gt-arm-builtins.h" diff --git a/gcc/config/arm/arm-builtins.h b/gcc/config/arm/arm-builtins.h new file mode 100644 index 0000000..62d6f17 --- /dev/null +++ b/gcc/config/arm/arm-builtins.h @@ -0,0 +1,35 @@ +/* Declarations for determining resolver for a given builtin. + Copyright (C) 2020 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef GCC_ARM_BUILTINS_H +#define GCC_ARM_BUILTINS_H + +enum resolver_ident { + arm_cde_resolver, + arm_no_resolver +}; +enum resolver_ident arm_describe_resolver (tree); +unsigned arm_cde_end_args (tree); + +#endif /* GCC_ARM_BUILTINS_H */ diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c index f173b33..7468a20 100644 --- a/gcc/config/arm/arm-c.c +++ b/gcc/config/arm/arm-c.c @@ -27,8 +27,120 @@ #include "tm_p.h" #include "c-family/c-pragma.h" #include "stringpool.h" +#include "arm-builtins.h" -tree arm_resolve_overloaded_builtin (location_t, tree, void*); +tree +arm_resolve_cde_builtin (location_t loc, tree fndecl, void *arglist) +{ + vec *params = static_cast *> (arglist); + unsigned param_num = params ? params->length() : 0; + unsigned num_args = list_length (TYPE_ARG_TYPES (TREE_TYPE (fndecl))) - 1; + /* Ensure this function has the correct number of arguments. + This won't happen when using the intrinsics defined by the ACLE, since + they're exposed to the user via a wrapper in the arm_cde.h header that has + the correct number of arguments ... hence the compiler would already catch + an incorrect number of arguments there. + + It is still possible to get here if the user tries to call the __bulitin_* + functions directly. We could print some error message in this function, + but instead we leave it to the rest of the code to catch this problem in + the same way that other __builtin_* functions catch it. + + This does mean an odd error message, but it's consistent with the rest of + the builtins. */ + if (param_num != num_args) + return NULL_TREE; + + tree to_return = NULL_TREE; + /* Take the functions return type since that's the same type as the arguments + this function needs (the types of the builtin function all come from the + machine mode of the RTL pattern, and they're all the same and calculated + in the same way). */ + tree pattern_type = TREE_TYPE (TREE_TYPE (fndecl)); + + unsigned i; + /* Hard coding the number of parameters we don't want to cast at the end of + the builtin. This is the easiest approach for the CDE intrinsics, and + introducing a parameter to store in the builtins.def macros seems overkill + when they're only relevant here. */ + unsigned end_args = arm_cde_end_args (fndecl); + unsigned cast_param_end = param_num - end_args; + /* For the vcx1q patterns that don't need any casts. */ + if (cast_param_end == 1) + return NULL_TREE; + + /* In order to check all arguments rather than complaining on the first + invalid one we record whether *any* arguments are invalid using this + boolean variable. */ + bool invalid = false; + for (i = 1; i < cast_param_end; i++) + { + tree this_param = (*params)[i]; + if (TREE_CODE (this_param) == ERROR_MARK) + { + invalid = true; + continue; + } + tree param_type = TREE_TYPE (this_param); + + /* Return value is cast to type that second argument originally was. + All non-constant arguments are cast to the return type calculated from + the RTL pattern. + + Set the return type to an unqualified version of the type of the first + parameter. The first parameter since that is how the intrinsics are + defined -- to always return the same type as the first polymorphic + argument. Unqualified version of the type since we don't want passing + a constant parameter to mean that the return value of the builtin is + also constant. */ + if (i == 1) + to_return = build_qualified_type (param_type, 0 MEM_STAT_INFO); + + /* The only requirement of these intrinsics on the type of the variable + is that it's 128 bits wide. All other types are valid and we simply + VIEW_CONVERT_EXPR them to the type of the underlying builtin. */ + tree type_size = TYPE_SIZE (param_type); + if (! tree_fits_shwi_p (type_size) + || tree_to_shwi (type_size) != 128) + { + error_at (loc, + "argument %u to function %qE is of type %qT which is not " + "known to be 128 bits wide", + i + 1, fndecl, param_type); + invalid = true; + continue; + } + + /* Only convert the argument if we actually need to. */ + if (! check_base_type (pattern_type, param_type)) + (*params)[i] = build1 (VIEW_CONVERT_EXPR, pattern_type, this_param); + } + if (invalid) + return NULL_TREE; + + /* We know it's safe to call this since this builtin is here to implement an + ACLE function, and those functions are only for C/C++. */ + tree call_expr = build_function_call_vec (loc, vNULL, fndecl, params, + NULL, fndecl); + + gcc_assert (to_return != NULL_TREE); + if (! check_base_type (to_return, pattern_type)) + return build1 (VIEW_CONVERT_EXPR, to_return, call_expr); + return call_expr; +} + +/* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. This is currently only + used for the MVE related builtins for the CDE extension. + Here we ensure the type of arguments is such that the size is correct, and + then return a tree that describes the same function call but with the + relevant types cast as necessary. */ +tree +arm_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist) +{ + if (arm_describe_resolver (fndecl) == arm_cde_resolver) + return arm_resolve_cde_builtin (loc, fndecl, arglist); + return NULL_TREE; +} /* Output C specific EABI object attributes. These cannot be done in arm.c because they require information from the C frontend. */ diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h index e9564d5..d8ddda6 100644 --- a/gcc/config/arm/arm_cde.h +++ b/gcc/config/arm/arm_cde.h @@ -160,6 +160,21 @@ extern "C" { #define __arm_vcx3qa(coproc, acc, n, m, imm) \ __builtin_arm_vcx3qav16qi(coproc, acc, n, m, imm) +#define __arm_vcx1q_m(coproc, inactive, imm, pred) \ + __builtin_arm_vcx1q_p_v16qi(coproc, inactive, imm, pred) +#define __arm_vcx1qa_m(coproc, acc, imm, pred) \ + __builtin_arm_vcx1qa_p_v16qi(coproc, acc, imm, pred) + +#define __arm_vcx2q_m(coproc, inactive, n, imm, pred) \ + __builtin_arm_vcx2q_p_v16qi(coproc, inactive, n, imm, pred) +#define __arm_vcx2qa_m(coproc, acc, n, imm, pred) \ + __builtin_arm_vcx2qa_p_v16qi(coproc, acc, n, imm, pred) + +#define __arm_vcx3q_m(coproc, inactive, n, m, imm, pred) \ + __builtin_arm_vcx3q_p_v16qi(coproc, inactive, n, m, imm, pred) +#define __arm_vcx3qa_m(coproc, acc, n, m, imm, pred) \ + __builtin_arm_vcx3qa_p_v16qi(coproc, acc, n, m, imm, pred) + #endif #ifdef __cplusplus diff --git a/gcc/config/arm/arm_cde_builtins.def b/gcc/config/arm/arm_cde_builtins.def index 1e107cf..9f8ddb5 100644 --- a/gcc/config/arm/arm_cde_builtins.def +++ b/gcc/config/arm/arm_cde_builtins.def @@ -38,7 +38,8 @@ CDE_VAR2 (CX_BINARY, vcx3, si, di, ARM_VCDE_CONST_3, ECF_CONST) CDE_VAR2 (CX_TERNARY, vcx3a, si, di, ARM_VCDE_CONST_3, ECF_CONST) /* NOTE: The MVE intrinsics must be defined at the end of this file, and with - vcx1q first. + vcx1q first. Amongst the MVE intrinsics, the predicated ones are + defined last. These restrictions are relied on to determine which intrinsics need overload resolution in `arm_resolve_overloaded_builtin`. */ VAR1 (CX_IMM, vcx1q, v16qi, ARM_MVE_CDE_CONST_1, ECF_CONST) @@ -48,4 +49,10 @@ VAR1 (CX_BINARY, vcx2qa, v16qi, ARM_MVE_CDE_CONST_2, ECF_CONST) VAR1 (CX_BINARY, vcx3q, v16qi, ARM_MVE_CDE_CONST_3, ECF_CONST) VAR1 (CX_TERNARY, vcx3qa, v16qi, ARM_MVE_CDE_CONST_3, ECF_CONST) +VAR1 (CX_UNARY_UNONE, vcx1q_p_, v16qi, ARM_MVE_CDE_CONST_1, ECF_CONST) +VAR1 (CX_UNARY_UNONE, vcx1qa_p_, v16qi, ARM_MVE_CDE_CONST_1, ECF_CONST) +VAR1 (CX_BINARY_UNONE, vcx2q_p_, v16qi, ARM_MVE_CDE_CONST_2, ECF_CONST) +VAR1 (CX_BINARY_UNONE, vcx2qa_p_, v16qi, ARM_MVE_CDE_CONST_2, ECF_CONST) +VAR1 (CX_TERNARY_UNONE, vcx3q_p_, v16qi, ARM_MVE_CDE_CONST_3, ECF_CONST) +VAR1 (CX_TERNARY_UNONE, vcx3qa_p_, v16qi, ARM_MVE_CDE_CONST_3, ECF_CONST) #undef CDE_VAR2 diff --git a/gcc/config/arm/arm_mve.h b/gcc/config/arm/arm_mve.h index 4ab16b7..8fe7c6e 100644 --- a/gcc/config/arm/arm_mve.h +++ b/gcc/config/arm/arm_mve.h @@ -13502,78 +13502,6 @@ __arm_vaddq_u32 (uint32x4_t __a, uint32x4_t __b) __extension__ extern __inline uint8x16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_u8 (void) -{ - uint8x16_t __uninit; - __asm__ ("": "=w"(__uninit)); - return __uninit; -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_u16 (void) -{ - uint16x8_t __uninit; - __asm__ ("": "=w"(__uninit)); - return __uninit; -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_u32 (void) -{ - uint32x4_t __uninit; - __asm__ ("": "=w"(__uninit)); - return __uninit; -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_u64 (void) -{ - uint64x2_t __uninit; - __asm__ ("": "=w"(__uninit)); - return __uninit; -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_s8 (void) -{ - int8x16_t __uninit; - __asm__ ("": "=w"(__uninit)); - return __uninit; -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_s16 (void) -{ - int16x8_t __uninit; - __asm__ ("": "=w"(__uninit)); - return __uninit; -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_s32 (void) -{ - int32x4_t __uninit; - __asm__ ("": "=w"(__uninit)); - return __uninit; -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_s64 (void) -{ - int64x2_t __uninit; - __asm__ ("": "=w"(__uninit)); - return __uninit; -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vddupq_m_n_u8 (uint8x16_t __inactive, uint32_t __a, const int __imm, mve_pred16_t __p) { return __builtin_mve_vddupq_m_n_uv16qi (__inactive, __a, __imm, __p); @@ -19206,24 +19134,6 @@ __arm_vaddq_f32 (float32x4_t __a, float32x4_t __b) return __a + __b; } -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_f16 (void) -{ - float16x8_t __uninit; - __asm__ ("": "=w" (__uninit)); - return __uninit; -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq_f32 (void) -{ - float32x4_t __uninit; - __asm__ ("": "=w" (__uninit)); - return __uninit; -} - __extension__ extern __inline float32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vldrwq_gather_base_wb_f32 (uint32x4_t * __addr, const int __offset) @@ -30146,62 +30056,6 @@ __arm_vaddq (uint32x4_t __a, uint32x4_t __b) __extension__ extern __inline uint8x16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (uint8x16_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_u8 (); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (uint16x8_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_u16 (); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (uint32x4_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_u32 (); -} - -__extension__ extern __inline uint64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (uint64x2_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_u64 (); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (int8x16_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_s8 (); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (int16x8_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_s16 (); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (int32x4_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_s32 (); -} - -__extension__ extern __inline int64x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (int64x2_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_s64 (); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vddupq_m (uint8x16_t __inactive, uint32_t __a, const int __imm, mve_pred16_t __p) { return __arm_vddupq_m_n_u8 (__inactive, __a, __imm, __p); @@ -35095,20 +34949,6 @@ __arm_vaddq (float32x4_t __a, float32x4_t __b) return __arm_vaddq_f32 (__a, __b); } -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (float16x8_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_f16 (); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vuninitializedq (float32x4_t /* __v ATTRIBUTE UNUSED */) -{ - return __arm_vuninitializedq_f32 (); -} - __extension__ extern __inline void __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vstrwq_scatter_base_wb (uint32x4_t * __addr, const int __offset, float32x4_t __value) diff --git a/gcc/config/arm/arm_mve_types.h b/gcc/config/arm/arm_mve_types.h index 0776f79..554e285 100644 --- a/gcc/config/arm/arm_mve_types.h +++ b/gcc/config/arm/arm_mve_types.h @@ -450,6 +450,78 @@ __arm_vreinterpretq_u8_u64 (uint64x2_t __a) return (uint8x16_t) __a; } +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_u8 (void) +{ + uint8x16_t __uninit; + __asm__ ("": "=w"(__uninit)); + return __uninit; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_u16 (void) +{ + uint16x8_t __uninit; + __asm__ ("": "=w"(__uninit)); + return __uninit; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_u32 (void) +{ + uint32x4_t __uninit; + __asm__ ("": "=w"(__uninit)); + return __uninit; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_u64 (void) +{ + uint64x2_t __uninit; + __asm__ ("": "=w"(__uninit)); + return __uninit; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_s8 (void) +{ + int8x16_t __uninit; + __asm__ ("": "=w"(__uninit)); + return __uninit; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_s16 (void) +{ + int16x8_t __uninit; + __asm__ ("": "=w"(__uninit)); + return __uninit; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_s32 (void) +{ + int32x4_t __uninit; + __asm__ ("": "=w"(__uninit)); + return __uninit; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_s64 (void) +{ + int64x2_t __uninit; + __asm__ ("": "=w"(__uninit)); + return __uninit; +} + #if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ __extension__ extern __inline int32x4_t @@ -690,6 +762,24 @@ __arm_vreinterpretq_f32_u8 (uint8x16_t __a) return (float32x4_t) __a; } +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_f16 (void) +{ + float16x8_t __uninit; + __asm__ ("": "=w" (__uninit)); + return __uninit; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq_f32 (void) +{ + float32x4_t __uninit; + __asm__ ("": "=w" (__uninit)); + return __uninit; +} + #endif #ifdef __cplusplus @@ -1086,6 +1176,62 @@ __arm_vreinterpretq_u8 (uint64x2_t __a) return __arm_vreinterpretq_u8_u64 (__a); } +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (uint8x16_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_u8 (); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (uint16x8_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_u16 (); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (uint32x4_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_u32 (); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (uint64x2_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_u64 (); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (int8x16_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_s8 (); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (int16x8_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_s16 (); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (int32x4_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_s32 (); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (int64x2_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_s64 (); +} + #if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */ __extension__ extern __inline int32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) @@ -1324,6 +1470,20 @@ __arm_vreinterpretq_f32 (uint8x16_t __a) { return __arm_vreinterpretq_f32_u8 (__a); } + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (float16x8_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_f16 (); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__arm_vuninitializedq (float32x4_t /* __v ATTRIBUTE UNUSED */) +{ + return __arm_vuninitializedq_f32 (); +} #endif /* __ARM_FEATURE_MVE & 2 (MVE floating point) */ #endif /* __cplusplus */ diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 502f4f53..0bc9eba 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -529,6 +529,8 @@ (define_int_iterator BF_MA [UNSPEC_BFMAB UNSPEC_BFMAT]) +(define_int_iterator CDE_VCX [UNSPEC_VCDE UNSPEC_VCDEA]) + ;;---------------------------------------------------------------------------- ;; Mode attributes ;;---------------------------------------------------------------------------- @@ -1251,3 +1253,6 @@ ;; An iterator for VFMA (define_int_attr bt [(UNSPEC_BFMAB "b") (UNSPEC_BFMAT "t")]) + +;; An iterator for CDE MVE accumulator/non-accumulator versions. +(define_int_attr a [(UNSPEC_VCDE "") (UNSPEC_VCDEA "a")]) diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index 1ae0840..7054f7b 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -11372,3 +11372,45 @@ "vcx3a\\tp%c1, %q0, %q3, %q4, #%c5" [(set_attr "type" "coproc")] ) + +(define_insn "arm_vcx1q_p_v16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:V16QI 2 "register_operand" "0") + (match_operand:SI 3 "const_int_mve_cde1_operand" "i") + (match_operand:HI 4 "vpr_register_operand" "Up")] + CDE_VCX))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vpst\;vcx1t\\tp%c1, %q0, #%c3" + [(set_attr "type" "coproc") + (set_attr "length" "8")] +) + +(define_insn "arm_vcx2q_p_v16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:V16QI 2 "register_operand" "0") + (match_operand:V16QI 3 "register_operand" "t") + (match_operand:SI 4 "const_int_mve_cde2_operand" "i") + (match_operand:HI 5 "vpr_register_operand" "Up")] + CDE_VCX))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vpst\;vcx2t\\tp%c1, %q0, %q3, #%c4" + [(set_attr "type" "coproc") + (set_attr "length" "8")] +) + +(define_insn "arm_vcx3q_p_v16qi" + [(set (match_operand:V16QI 0 "register_operand" "=t") + (unspec:V16QI [(match_operand:SI 1 "const_int_coproc_operand" "i") + (match_operand:V16QI 2 "register_operand" "0") + (match_operand:V16QI 3 "register_operand" "t") + (match_operand:V16QI 4 "register_operand" "t") + (match_operand:SI 5 "const_int_mve_cde3_operand" "i") + (match_operand:HI 6 "vpr_register_operand" "Up")] + CDE_VCX))] + "TARGET_CDE && TARGET_HAVE_MVE" + "vpst\;vcx3t\\tp%c1, %q0, %q3, %q4, #%c5" + [(set_attr "type" "coproc") + (set_attr "length" "8")] +) diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md index ef83b50..3470679 100644 --- a/gcc/config/arm/vfp.md +++ b/gcc/config/arm/vfp.md @@ -199,7 +199,7 @@ case 8: return "vmov%?.f32\t%0, %1\t%@ int"; case 9: - return "vmsr%?\tP0, %1\t%@ movhi"; + return "vmsr%?\t P0, %1\t%@ movhi"; case 10: return "vmrs%?\t%0, P0\t%@ movhi"; default: diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-errors.c b/gcc/testsuite/gcc.target/arm/acle/cde-errors.c index 827e03b..85a9166 100644 --- a/gcc/testsuite/gcc.target/arm/acle/cde-errors.c +++ b/gcc/testsuite/gcc.target/arm/acle/cde-errors.c @@ -62,34 +62,34 @@ uint64_t test_cde (uint32_t n, uint32_t m) accum += __arm_cx3da (8, accum, n, m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ /* `imm` out of range. */ - accum += __arm_cx1 (0, 8192); /* { dg-error {argument 2 must be a constant immediate in range \[0-8191\]} } */ - accum += __arm_cx1a (0, (uint32_t)accum, 8192); /* { dg-error {argument 3 must be a constant immediate in range \[0-8191\]} } */ - accum += __arm_cx2 (0, n, 512); /* { dg-error {argument 3 must be a constant immediate in range \[0-511\]} } */ - accum += __arm_cx2a (0, (uint32_t)accum, n, 512); /* { dg-error {argument 4 must be a constant immediate in range \[0-511\]} } */ - accum += __arm_cx3 (0, n, m, 64); /* { dg-error {argument 4 must be a constant immediate in range \[0-63\]} } */ - accum += __arm_cx3a (0, (uint32_t)accum, n, m, 64); /* { dg-error {argument 5 must be a constant immediate in range \[0-63\]} } */ - - accum += __arm_cx1d (0, 8192); /* { dg-error {argument 2 must be a constant immediate in range \[0-8191\]} } */ - accum += __arm_cx1da (0, accum, 8192); /* { dg-error {argument 3 must be a constant immediate in range \[0-8191\]} } */ - accum += __arm_cx2d (0, n, 512); /* { dg-error {argument 3 must be a constant immediate in range \[0-511\]} } */ - accum += __arm_cx2da (0, accum, n, 512); /* { dg-error {argument 4 must be a constant immediate in range \[0-511\]} } */ - accum += __arm_cx3d (0, n, m, 64); /* { dg-error {argument 4 must be a constant immediate in range \[0-63\]} } */ - accum += __arm_cx3da (0, accum, n, m, 64); /* { dg-error {argument 5 must be a constant immediate in range \[0-63\]} } */ - - /* `imm` is not an immediate. */ - accum += __arm_cx1 (0, n); /* { dg-error {argument 2 must be a constant immediate in range \[0-8191\]} } */ - accum += __arm_cx1a (0, (uint32_t)accum, n); /* { dg-error {argument 3 must be a constant immediate in range \[0-8191\]} } */ - accum += __arm_cx2 (0, n, n); /* { dg-error {argument 3 must be a constant immediate in range \[0-511\]} } */ - accum += __arm_cx2a (0, (uint32_t)accum, n, n); /* { dg-error {argument 4 must be a constant immediate in range \[0-511\]} } */ - accum += __arm_cx3 (0, n, m, n); /* { dg-error {argument 4 must be a constant immediate in range \[0-63\]} } */ - accum += __arm_cx3a (0, (uint32_t)accum, n, m, n); /* { dg-error {argument 5 must be a constant immediate in range \[0-63\]} } */ - - accum += __arm_cx1d (0, n); /* { dg-error {argument 2 must be a constant immediate in range \[0-8191\]} } */ - accum += __arm_cx1da (0, accum, n); /* { dg-error {argument 3 must be a constant immediate in range \[0-8191\]} } */ - accum += __arm_cx2d (0, n, n); /* { dg-error {argument 3 must be a constant immediate in range \[0-511\]} } */ - accum += __arm_cx2da (0, accum, n, n); /* { dg-error {argument 4 must be a constant immediate in range \[0-511\]} } */ - accum += __arm_cx3d (0, n, m, n); /* { dg-error {argument 4 must be a constant immediate in range \[0-63\]} } */ - accum += __arm_cx3da (0, accum, n, m, n); /* { dg-error {argument 5 must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx1 (0, 8192); /* { dg-error {argument 2 to '__builtin_arm_cx1si' must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx1a (0, (uint32_t)accum, 8192); /* { dg-error {argument 3 to '__builtin_arm_cx1asi' must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx2 (0, n, 512); /* { dg-error {argument 3 to '__builtin_arm_cx2si' must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx2a (0, (uint32_t)accum, n, 512); /* { dg-error {argument 4 to '__builtin_arm_cx2asi' must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx3 (0, n, m, 64); /* { dg-error {argument 4 to '__builtin_arm_cx3si' must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx3a (0, (uint32_t)accum, n, m, 64); /* { dg-error {argument 5 to '__builtin_arm_cx3asi' must be a constant immediate in range \[0-63\]} } */ + + accum += __arm_cx1d (0, 8192); /* { dg-error {argument 2 to '__builtin_arm_cx1di' must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx1da (0, accum, 8192); /* { dg-error {argument 3 to '__builtin_arm_cx1adi' must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx2d (0, n, 512); /* { dg-error {argument 3 to '__builtin_arm_cx2di' must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx2da (0, accum, n, 512); /* { dg-error {argument 4 to '__builtin_arm_cx2adi' must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx3d (0, n, m, 64); /* { dg-error {argument 4 to '__builtin_arm_cx3di' must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx3da (0, accum, n, m, 64); /* { dg-error {argument 5 to '__builtin_arm_cx3adi' must be a constant immediate in range \[0-63\]} } */ + + /* `imm` must be an immediate. */ + accum += __arm_cx1 (0, n); /* { dg-error {argument 2 to '__builtin_arm_cx1si' must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx1a (0, (uint32_t)accum, n); /* { dg-error {argument 3 to '__builtin_arm_cx1asi' must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx2 (0, n, n); /* { dg-error {argument 3 to '__builtin_arm_cx2si' must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx2a (0, (uint32_t)accum, n, n); /* { dg-error {argument 4 to '__builtin_arm_cx2asi' must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx3 (0, n, m, n); /* { dg-error {argument 4 to '__builtin_arm_cx3si' must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx3a (0, (uint32_t)accum, n, m, n); /* { dg-error {argument 5 to '__builtin_arm_cx3asi' must be a constant immediate in range \[0-63\]} } */ + + accum += __arm_cx1d (0, n); /* { dg-error {argument 2 to '__builtin_arm_cx1di' must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx1da (0, accum, n); /* { dg-error {argument 3 to '__builtin_arm_cx1adi' must be a constant immediate in range \[0-8191\]} } */ + accum += __arm_cx2d (0, n, n); /* { dg-error {argument 3 to '__builtin_arm_cx2di' must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx2da (0, accum, n, n); /* { dg-error {argument 4 to '__builtin_arm_cx2adi' must be a constant immediate in range \[0-511\]} } */ + accum += __arm_cx3d (0, n, m, n); /* { dg-error {argument 4 to '__builtin_arm_cx3di' must be a constant immediate in range \[0-63\]} } */ + accum += __arm_cx3da (0, accum, n, m, n); /* { dg-error {argument 5 to '__builtin_arm_cx3adi' must be a constant immediate in range \[0-63\]} } */ /* `coproc` is not an immediate. */ accum += __arm_cx1 ((int)m, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-1.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-1.c index 0adacb5..611bdb9 100644 --- a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-1.c +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-1.c @@ -25,6 +25,19 @@ uint8x16_t test_invalid_arguments (uint8x16_t n, uint8x16_t m) accum += __arm_vcx3q (0, n, m); /* { dg-error {macro "__arm_vcx3q" requires 4 arguments, but only 3 given} } */ accum += __arm_vcx3qa (0, accum, n, m); /* { dg-error {macro "__arm_vcx3qa" requires 5 arguments, but only 4 given} } */ + accum += __arm_vcx1q_m (0, accum, 33, 1, 4); /* { dg-error {macro "__arm_vcx1q_m" passed 5 arguments, but takes just 4} } */ + accum += __arm_vcx1qa_m (0, accum, 33, 1, 4); /* { dg-error {macro "__arm_vcx1qa_m" passed 5 arguments, but takes just 4} } */ + accum += __arm_vcx2q_m (0, accum, n, 33, 1, 4); /* { dg-error {macro "__arm_vcx2q_m" passed 6 arguments, but takes just 5} } */ + accum += __arm_vcx2qa_m (0, accum, n, 33, 1, 4); /* { dg-error {macro "__arm_vcx2qa_m" passed 6 arguments, but takes just 5} } */ + accum += __arm_vcx3q_m (0, accum, n, m, 33, 1, 4); /* { dg-error {macro "__arm_vcx3q_m" passed 7 arguments, but takes just 6} } */ + accum += __arm_vcx3qa_m (0, accum, n, m, 33, 1, 4); /* { dg-error {macro "__arm_vcx3qa_m" passed 7 arguments, but takes just 6} } */ + accum += __arm_vcx1q_m (0, accum, 4); /* { dg-error {macro "__arm_vcx1q_m" requires 4 arguments, but only 3 given} } */ + accum += __arm_vcx1qa_m (0, accum, 4); /* { dg-error {macro "__arm_vcx1qa_m" requires 4 arguments, but only 3 given} } */ + accum += __arm_vcx2q_m (0, accum, n, 4); /* { dg-error {macro "__arm_vcx2q_m" requires 5 arguments, but only 4 given} } */ + accum += __arm_vcx2qa_m (0, accum, n, 4); /* { dg-error {macro "__arm_vcx2qa_m" requires 5 arguments, but only 4 given} } */ + accum += __arm_vcx3q_m (0, accum, n, m, 4); /* { dg-error {macro "__arm_vcx3q_m" requires 6 arguments, but only 5 given} } */ + accum += __arm_vcx3qa_m (0, accum, n, m, 4); /* { dg-error {macro "__arm_vcx3qa_m" requires 6 arguments, but only 5 given} } */ + /* The preprocessor complains that the macro was given an invalid number of arguments, and because of that ends up not expanding the macro but rather just leaving the macro name in the source code. That macro name @@ -38,5 +51,12 @@ uint8x16_t test_invalid_arguments (uint8x16_t n, uint8x16_t m) /* { dg-error {'__arm_vcx3q' undeclared \(first use in this function\)} "" { target { *-*-* } } 17 } */ /* { dg-error {'__arm_vcx3qa' undeclared \(first use in this function\)} "" { target { *-*-* } } 18 } */ + /* { dg-error {'__arm_vcx1q_m' undeclared \(first use in this function\)} "" { target { *-*-* } } 28 } */ + /* { dg-error {'__arm_vcx1qa_m' undeclared \(first use in this function\)} "" { target { *-*-* } } 29 } */ + /* { dg-error {'__arm_vcx2q_m' undeclared \(first use in this function\)} "" { target { *-*-* } } 30 } */ + /* { dg-error {'__arm_vcx2qa_m' undeclared \(first use in this function\)} "" { target { *-*-* } } 31 } */ + /* { dg-error {'__arm_vcx3q_m' undeclared \(first use in this function\)} "" { target { *-*-* } } 32 } */ + /* { dg-error {'__arm_vcx3qa_m' undeclared \(first use in this function\)} "" { target { *-*-* } } 33 } */ + return accum; } diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-2.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-2.c index 27e491a..37335a0 100644 --- a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-2.c +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-2.c @@ -4,12 +4,14 @@ /* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ /* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ -/* This file and cde-mve-error-tests.c are split since there are two kinds of - errors happening here. The errors in the other file cause the compiler to - not reach the errors found here, hence they need to be in a different file - so we can inspect these ones. */ +/* The error checking files are split since there are three kinds of + errors happening here. Different error types cause errors at different + times, which means the compiler stops and doesn't produce messages about the + later errors. Hence they need to be in a different file so we can inspect + these ones. */ -uint8x16_t test_bad_immediates (uint8x16_t n, uint8x16_t m, int someval) +uint8x16_t test_bad_immediates (uint8x16_t n, uint8x16_t m, int someval, + mve_pred16_t pred) { uint8x16_t accum = (uint8x16_t)(uint32x4_t){0, 0, 0, 0}; @@ -36,6 +38,13 @@ uint8x16_t test_bad_immediates (uint8x16_t n, uint8x16_t m, int someval) accum += __arm_vcx3q (1, n, m, 15); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ accum += __arm_vcx3qa (1, accum, n, m, 15); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx1q_m (1, accum, 4094, pred); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx1qa_m (1, accum, 4095, pred); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx2q_m (1, accum, n, 126, pred); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx2qa_m (1, accum, n, 127, pred); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx3q_m (1, accum, n, m, 15, pred); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + accum += __arm_vcx3qa_m (1, accum, n, m, 15, pred); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */ + /* `coproc' out of range. */ accum += __arm_vcx1q_u8 (8, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ accum += __arm_vcx1qa (8, accum, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ @@ -46,25 +55,46 @@ uint8x16_t test_bad_immediates (uint8x16_t n, uint8x16_t m, int someval) accum += __arm_vcx3q (8, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ accum += __arm_vcx3qa (8, accum, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx1q_m (8, accum, 4094, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx1qa_m (8, accum, 4095, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2q_m (8, accum, n, 126, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2qa_m (8, accum, n, 127, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3q_m (8, accum, n, m, 15, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3qa_m (8, accum, n, m, 15, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* `imm' out of range. */ - accum += __arm_vcx1q_u8 (0, 4096); /* { dg-error {argument 2 must be a constant immediate in range \[0-4095\]} } */ - accum += __arm_vcx1qa (0, accum, 4096); /* { dg-error {argument 3 must be a constant immediate in range \[0-4095\]} } */ - accum += __arm_vcx2q (0, n, 128); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx2q_u8 (0, n, 129); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx2qa (0, accum, n, 128); /* { dg-error {argument 4 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx3q_u8 (0, n, m, 16); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ - accum += __arm_vcx3q (0, n, m, 17); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ - accum += __arm_vcx3qa (0, accum, n, m, 16); /* { dg-error {argument 5 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx1q_u8 (0, 4096); /* { dg-error {argument 2 to '__builtin_arm_vcx1qv16qi' must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx1qa (0, accum, 4096); /* { dg-error {argument 3 to '__builtin_arm_vcx1qav16qi' must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx2q (0, n, 128); /* { dg-error {argument 3 to '__builtin_arm_vcx2qv16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2q_u8 (0, n, 129); /* { dg-error {argument 3 to '__builtin_arm_vcx2qv16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2qa (0, accum, n, 128); /* { dg-error {argument 4 to '__builtin_arm_vcx2qav16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx3q_u8 (0, n, m, 16); /* { dg-error {argument 4 to '__builtin_arm_vcx3qv16qi' must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3q (0, n, m, 17); /* { dg-error {argument 4 to '__builtin_arm_vcx3qv16qi' must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3qa (0, accum, n, m, 16); /* { dg-error {argument 5 to '__builtin_arm_vcx3qav16qi' must be a constant immediate in range \[0-15\]} } */ + + accum += __arm_vcx1q_m (0, accum, 4097, pred); /* { dg-error {argument 3 to '__builtin_arm_vcx1q_p_v16qi' must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx1qa_m (0, accum, 4096, pred); /* { dg-error {argument 3 to '__builtin_arm_vcx1qa_p_v16qi' must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx2q_m (0, accum, n, 128, pred); /* { dg-error {argument 4 to '__builtin_arm_vcx2q_p_v16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2qa_m (0, accum, n, 128, pred); /* { dg-error {argument 4 to '__builtin_arm_vcx2qa_p_v16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx3q_m (0, accum, n, m, 17, pred); /* { dg-error {argument 5 to '__builtin_arm_vcx3q_p_v16qi' must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3qa_m (0, accum, n, m, 16, pred); /* { dg-error {argument 5 to '__builtin_arm_vcx3qa_p_v16qi' must be a constant immediate in range \[0-15\]} } */ /* `imm' is not an immediate. */ - accum += __arm_vcx1q_u8 (0, someval); /* { dg-error {argument 2 must be a constant immediate in range \[0-4095\]} } */ - accum += __arm_vcx1qa (0, accum, someval); /* { dg-error {argument 3 must be a constant immediate in range \[0-4095\]} } */ - accum += __arm_vcx2q (0, n, someval); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx2q_u8 (6, n, someval); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx2qa (0, accum, n, someval); /* { dg-error {argument 4 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx3q_u8 (0, n, m, someval); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ - accum += __arm_vcx3q (6, n, m, someval); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ - accum += __arm_vcx3qa (0, accum, n, m, someval); /* { dg-error {argument 5 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx1q_u8 (6, someval); /* { dg-error {argument 2 to '__builtin_arm_vcx1qv16qi' must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx1qa (0, accum, someval); /* { dg-error {argument 3 to '__builtin_arm_vcx1qav16qi' must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx2q (0, n, someval); /* { dg-error {argument 3 to '__builtin_arm_vcx2qv16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2q_u8 (6, n, someval); /* { dg-error {argument 3 to '__builtin_arm_vcx2qv16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2qa (0, accum, n, someval); /* { dg-error {argument 4 to '__builtin_arm_vcx2qav16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx3q_u8 (0, n, m, someval); /* { dg-error {argument 4 to '__builtin_arm_vcx3qv16qi' must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3q (6, n, m, someval); /* { dg-error {argument 4 to '__builtin_arm_vcx3qv16qi' must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3qa (0, accum, n, m, someval); /* { dg-error {argument 5 to '__builtin_arm_vcx3qav16qi' must be a constant immediate in range \[0-15\]} } */ + + accum += __arm_vcx1q_m (6, accum, someval, pred); /* { dg-error {argument 3 to '__builtin_arm_vcx1q_p_v16qi' must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx1qa_m (0, accum, someval, pred); /* { dg-error {argument 3 to '__builtin_arm_vcx1qa_p_v16qi' must be a constant immediate in range \[0-4095\]} } */ + accum += __arm_vcx2q_m (0, accum, n, someval, pred); /* { dg-error {argument 4 to '__builtin_arm_vcx2q_p_v16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx2qa_m (0, accum, n, someval, pred); /* { dg-error {argument 4 to '__builtin_arm_vcx2qa_p_v16qi' must be a constant immediate in range \[0-127\]} } */ + accum += __arm_vcx3q_m (6, accum, n, m, someval, pred); /* { dg-error {argument 5 to '__builtin_arm_vcx3q_p_v16qi' must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx3qa_m (0, accum, n, m, someval, pred); /* { dg-error {argument 5 to '__builtin_arm_vcx3qa_p_v16qi' must be a constant immediate in range \[0-15\]} } */ /* `coproc' is not an immediate. */ accum += __arm_vcx1q_u8 (someval, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ @@ -76,28 +106,82 @@ uint8x16_t test_bad_immediates (uint8x16_t n, uint8x16_t m, int someval) accum += __arm_vcx3q (someval, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ accum += __arm_vcx3qa (someval, accum, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx1q_m (someval, accum, 4096, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx1qa_m (someval, accum, 4095, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2q_m (someval, accum, n, 126, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx2qa_m (someval, accum, n, 127, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3q_m (someval, accum, n, m, 15, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + accum += __arm_vcx3qa_m (someval, accum, n, m, 15, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* `imm' is of wrong type. */ - accum += __arm_vcx1q_u8 (0, ""); /* { dg-error {argument 2 must be a constant immediate in range \[0-4095\]} } */ - accum += __arm_vcx1qa (0, accum, ""); /* { dg-error {argument 3 must be a constant immediate in range \[0-4095\]} } */ - accum += __arm_vcx2q (0, n, ""); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx2q_u8 (0, n, "x"); /* { dg-error {argument 3 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx2qa (0, accum, n, ""); /* { dg-error {argument 4 must be a constant immediate in range \[0-127\]} } */ - accum += __arm_vcx3q_u8 (0, n, m, ""); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ - accum += __arm_vcx3q (0, n, m, "x"); /* { dg-error {argument 4 must be a constant immediate in range \[0-15\]} } */ - accum += __arm_vcx3qa (0, accum, n, m, ""); /* { dg-error {argument 5 must be a constant immediate in range \[0-15\]} } */ + accum += __arm_vcx1q_u8 (0, ""); /* { dg-error {argument 2 to '__builtin_arm_vcx1qv16qi' must be a constant immediate in range \[0-4095\]} } */ + /* { dg-warning {passing argument 2 of '__builtin_arm_vcx1qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 117 } */ + accum += __arm_vcx1qa (0, accum, ""); /* { dg-error {argument 3 to '__builtin_arm_vcx1qav16qi' must be a constant immediate in range \[0-4095\]} } */ + /* { dg-warning {passing argument 3 of '__builtin_arm_vcx1qav16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 119 } */ + accum += __arm_vcx2q (0, n, ""); /* { dg-error {argument 3 to '__builtin_arm_vcx2qv16qi' must be a constant immediate in range \[0-127\]} } */ + /* { dg-warning {passing argument 3 of '__builtin_arm_vcx2qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 121 } */ + accum += __arm_vcx2q_u8 (0, n, "x"); /* { dg-error {argument 3 to '__builtin_arm_vcx2qv16qi' must be a constant immediate in range \[0-127\]} } */ + /* { dg-warning {passing argument 3 of '__builtin_arm_vcx2qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 123 } */ + accum += __arm_vcx2qa (0, accum, n, ""); /* { dg-error {argument 4 to '__builtin_arm_vcx2qav16qi' must be a constant immediate in range \[0-127\]} } */ + /* { dg-warning {passing argument 4 of '__builtin_arm_vcx2qav16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 125 } */ + accum += __arm_vcx3q_u8 (0, n, m, ""); /* { dg-error {argument 4 to '__builtin_arm_vcx3qv16qi' must be a constant immediate in range \[0-15\]} } */ + /* { dg-warning {passing argument 4 of '__builtin_arm_vcx3qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 127 } */ + accum += __arm_vcx3q (0, n, m, "x"); /* { dg-error {argument 4 to '__builtin_arm_vcx3qv16qi' must be a constant immediate in range \[0-15\]} } */ + /* { dg-warning {passing argument 4 of '__builtin_arm_vcx3qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 129 } */ + accum += __arm_vcx3qa (0, accum, n, m, ""); /* { dg-error {argument 5 to '__builtin_arm_vcx3qav16qi' must be a constant immediate in range \[0-15\]} } */ + /* { dg-warning {passing argument 5 of '__builtin_arm_vcx3qav16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 131 } */ + + accum += __arm_vcx1q_m (0, accum, "", pred); /* { dg-error {argument 3 to '__builtin_arm_vcx1q_p_v16qi' must be a constant immediate in range \[0-4095\]} } */ + /* { dg-warning {passing argument 3 of '__builtin_arm_vcx1q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 134 } */ + accum += __arm_vcx1qa_m (0, accum, "", pred); /* { dg-error {argument 3 to '__builtin_arm_vcx1qa_p_v16qi' must be a constant immediate in range \[0-4095\]} } */ + /* { dg-warning {passing argument 3 of '__builtin_arm_vcx1qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 136 } */ + accum += __arm_vcx2q_m (0, accum, n, "", pred); /* { dg-error {argument 4 to '__builtin_arm_vcx2q_p_v16qi' must be a constant immediate in range \[0-127\]} } */ + /* { dg-warning {passing argument 4 of '__builtin_arm_vcx2q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 138 } */ + accum += __arm_vcx2qa_m (0, accum, n, "", pred); /* { dg-error {argument 4 to '__builtin_arm_vcx2qa_p_v16qi' must be a constant immediate in range \[0-127\]} } */ + /* { dg-warning {passing argument 4 of '__builtin_arm_vcx2qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 140 } */ + accum += __arm_vcx3q_m (0, accum, n, m, "x", pred); /* { dg-error {argument 5 to '__builtin_arm_vcx3q_p_v16qi' must be a constant immediate in range \[0-15\]} } */ + /* { dg-warning {passing argument 5 of '__builtin_arm_vcx3q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 142 } */ + accum += __arm_vcx3qa_m (0, accum, n, m, "", pred); /* { dg-error {argument 5 to '__builtin_arm_vcx3qa_p_v16qi' must be a constant immediate in range \[0-15\]} } */ + /* { dg-warning {passing argument 5 of '__builtin_arm_vcx3qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 144 } */ /* `coproc' is of wrong type. */ - accum += __arm_vcx1q_u8 ("", 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ accum += __arm_vcx1qa ("", accum, 4095); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx1qav16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 148 } */ accum += __arm_vcx2q ("", n, 126); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ - accum += __arm_vcx2q_u8 ("", n, 127); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx2qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 150 } */ accum += __arm_vcx2qa ("", accum, n, 127); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ - accum += __arm_vcx3q_u8 ("", n, m, 14); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx2qav16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 152 } */ accum += __arm_vcx3q ("", n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx3qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 154 } */ accum += __arm_vcx3qa ("", accum, n, m, 15); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx3qav16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 156 } */ + + accum += __arm_vcx1q_m ("", accum, 4094, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx1q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 159 } */ + accum += __arm_vcx1qa_m ("", accum, 4095, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx1qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 161 } */ + accum += __arm_vcx2q_m ("", accum, n, 126, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx2q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 163 } */ + accum += __arm_vcx2qa_m ("", accum, n, 127, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx2qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 165 } */ + accum += __arm_vcx3q_m ("", accum, n, m, 15, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx3q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 167 } */ + accum += __arm_vcx3qa_m ("", accum, n, m, 15, pred); /* { dg-error {coproc must be a constant immediate in range \[0-7\] enabled with \+cdecp} } */ + /* { dg-warning {passing argument 1 of '__builtin_arm_vcx3qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 169 } */ - /* { dg-warning {passing argument 2 of '__builtin_arm_vcx1qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 80 } */ - /* { dg-warning {passing argument 1 of '__builtin_arm_vcx1qv16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 90 } */ + /* `pred" is of wrong type. */ + accum += __arm_vcx1q_m (0, accum, 4094, ""); + /* { dg-warning {passing argument 4 of '__builtin_arm_vcx1q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 173 } */ + accum += __arm_vcx1qa_m (0, accum, 4095, ""); + /* { dg-warning {passing argument 4 of '__builtin_arm_vcx1qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 175 } */ + accum += __arm_vcx2q_m (0, accum, n, 126, ""); + /* { dg-warning {passing argument 5 of '__builtin_arm_vcx2q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 177 } */ + accum += __arm_vcx2qa_m (0, accum, n, 127, ""); + /* { dg-warning {passing argument 5 of '__builtin_arm_vcx2qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 179 } */ + accum += __arm_vcx3q_m (0, accum, n, m, 15, ""); + /* { dg-warning {passing argument 6 of '__builtin_arm_vcx3q_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 181 } */ + accum += __arm_vcx3qa_m (0, accum, n, m, 15, ""); + /* { dg-warning {passing argument 6 of '__builtin_arm_vcx3qa_p_v16qi' makes integer from pointer without a cast \[-Wint-conversion\]} "" { target *-*-* } 183 } */ return accum; } diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-3.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-3.c index e637ab8..68ed51a 100644 --- a/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-3.c +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-error-3.c @@ -4,61 +4,90 @@ /* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ /* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ -uint32_t test (int8x16_t m, int8x16_t n) +uint32_t test (int8x16_t m, int8x16_t n, mve_pred16_t pred) { /* Bad types for polymophic arguments. */ - uint32_t accum = 0, n_int = 0; + uint32_t accum = 0, n_int = 0, m_int = 0; accum += __arm_vcx1qa (0, accum, 4095); accum += __arm_vcx2q (0, n_int, 126); accum += __arm_vcx2q_u8 (0, n_int, 127); - accum += __arm_vcx2qa (0, accum, n, 127); - accum += __arm_vcx3q_u8 (0, n_int, m, 14); - accum += __arm_vcx3q (0, n_int, m, 15); - accum += __arm_vcx3qa (0, accum, n, m, 15); + accum += __arm_vcx2qa (0, accum, n_int, 127); + accum += __arm_vcx3q_u8 (0, n_int, m_int, 14); + accum += __arm_vcx3q (0, n_int, m_int, 15); + accum += __arm_vcx3qa (0, accum, n_int, m_int, 15); - /* { dg-error {argument 1 to function '__builtin_arm_vcx1qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 11 } */ + /* We get a at least two errors for each function since the errors are + checked for validity in two different ways and both are caught. + The resolver manually checks that each type is 128 bits wide, and only + casts the value if that's true. + After the resolver rejects the function call then the C frontend tries to + fit the original call to the builtin. This produces a second set of + error messages from the C frontend argument checking. */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx1qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 11 } */ /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx1qav16qi'} "" { target *-*-* } 11 } */ - /* { dg-error {argument 1 to function '__builtin_arm_vcx2qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 12 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx2qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 12 } */ /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx2qv16qi'} "" { target *-*-* } 12 } */ - /* { dg-error {argument 1 to function '__builtin_arm_vcx2qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 13 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx2qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 13 } */ /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx2qv16qi'} "" { target *-*-* } 13 } */ - /* { dg-error {argument 1 to function '__builtin_arm_vcx2qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 14 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx2qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 14 } */ /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx2qav16qi'} "" { target *-*-* } 14 } */ - /* { dg-error {argument 1 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 15 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx2qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 14 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx2qav16qi'} "" { target *-*-* } 14 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 15 } */ /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 15 } */ - /* { dg-error {argument 1 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 16 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 15 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 15 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 16 } */ /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 16 } */ - /* { dg-error {argument 1 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 17 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 16 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 16 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 17 } */ /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 17 } */ - return accum; -} + /* { dg-error {argument 3 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 17 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 17 } */ + /* { dg-error {argument 4 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 17 } */ + /* { dg-error {incompatible type for argument 4 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 17 } */ + + accum += __arm_vcx1qa_m (0, accum, 4095, pred); + accum += __arm_vcx2q_m (0, accum, n_int, 126, pred); + accum += __arm_vcx2qa_m (0, accum, n_int, 127, pred); + accum += __arm_vcx3q_m (0, accum, n_int, m_int, 15, pred); + accum += __arm_vcx3qa_m (0, accum, n_int, m_int, 15, pred); + + /* { dg-error {argument 2 to function '__builtin_arm_vcx1qa_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 58 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx1qa_p_v16qi'} "" { target *-*-* } 58 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx2q_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 59 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx2q_p_v16qi'} "" { target *-*-* } 59 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx2q_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 59 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx2q_p_v16qi'} "" { target *-*-* } 59 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx2qa_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 60 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx2qa_p_v16qi'} "" { target *-*-* } 60 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx2qa_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 60 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx2qa_p_v16qi'} "" { target *-*-* } 60 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx3q_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 61 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx3q_p_v16qi'} "" { target *-*-* } 61 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx3q_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 61 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3q_p_v16qi'} "" { target *-*-* } 61 } */ + /* { dg-error {argument 4 to function '__builtin_arm_vcx3q_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 61 } */ + /* { dg-error {incompatible type for argument 4 of '__builtin_arm_vcx3q_p_v16qi'} "" { target *-*-* } 61 } */ + + /* { dg-error {argument 2 to function '__builtin_arm_vcx3qa_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 62 } */ + /* { dg-error {incompatible type for argument 2 of '__builtin_arm_vcx3qa_p_v16qi'} "" { target *-*-* } 62 } */ + /* { dg-error {argument 3 to function '__builtin_arm_vcx3qa_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 62 } */ + /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qa_p_v16qi'} "" { target *-*-* } 62 } */ + /* { dg-error {argument 4 to function '__builtin_arm_vcx3qa_p_v16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 62 } */ + /* { dg-error {incompatible type for argument 4 of '__builtin_arm_vcx3qa_p_v16qi'} "" { target *-*-* } 62 } */ -int8x16_t test2 (int8x16_t m, int8x16_t n) -{ - uint32_t n_int = 0, m_int = 0; - int8x16_t accum = (int8x16_t)(uint64x2_t) { 0, 0 }; - accum += __arm_vcx2qa (0, accum, n_int, 127); - accum += __arm_vcx3q_u8 (0, n, m_int, 14); - accum += __arm_vcx3q (0, n, m_int, 15); - accum += __arm_vcx3qa (0, accum, n_int, m, 15); - accum += __arm_vcx3qa (0, accum, n_int, m, 15); - accum += __arm_vcx3qa (0, accum, n, m_int, 15); - accum += __arm_vcx3qa (0, accum, n, m_int, 15); - - /* { dg-error {argument 2 to function '__builtin_arm_vcx2qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 40 } */ - /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx2qav16qi'} "" { target *-*-* } 40 } */ - /* { dg-error {argument 2 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 41 } */ - /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 41 } */ - /* { dg-error {argument 2 to function '__builtin_arm_vcx3qv16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 42 } */ - /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qv16qi'} "" { target *-*-* } 42 } */ - /* { dg-error {argument 2 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 43 } */ - /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 43 } */ - /* { dg-error {argument 2 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 44 } */ - /* { dg-error {incompatible type for argument 3 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 44 } */ - /* { dg-error {argument 3 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 45 } */ - /* { dg-error {incompatible type for argument 4 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 45 } */ - /* { dg-error {argument 3 to function '__builtin_arm_vcx3qav16qi' is of type 'uint32_t' {aka '(?:long )?unsigned int'} which is not known to be 128 bits wide} "" { target *-*-* } 46 } */ - /* { dg-error {incompatible type for argument 4 of '__builtin_arm_vcx3qav16qi'} "" { target *-*-* } 46 } */ return accum; } @@ -78,8 +107,8 @@ int8x16_t test3 (int8x16_t m, int8x16_t n) accum += __arm_vcx3qa (0, accum, n_int, m, 15); accum += __arm_vcx3qa (0, accum, n_int, m_int, 15); - /* { dg-error {'accum_int' undeclared \(first use in this function\)} "" { target *-*-* } 70 } */ - /* { dg-error {'n_int' undeclared \(first use in this function\)} "" { target *-*-* } 71 } */ - /* { dg-error {'m_int' undeclared \(first use in this function\)} "" { target *-*-* } 75 } */ + /* { dg-error {'accum_int' undeclared \(first use in this function\)} "" { target *-*-* } 99 } */ + /* { dg-error {'n_int' undeclared \(first use in this function\)} "" { target *-*-* } 100 } */ + /* { dg-error {'m_int' undeclared \(first use in this function\)} "" { target *-*-* } 104 } */ return accum; } diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-full-assembly.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-full-assembly.c index a10ff9f..501cc84 100644 --- a/gcc/testsuite/gcc.target/arm/acle/cde-mve-full-assembly.c +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-full-assembly.c @@ -555,3 +555,597 @@ ** vmov q0, \2 ** bx lr */ + +/* Predicated MVE intrinsics. */ +/* Merging lane predication types. + NOTE: Depending on the target, the setup instructions (vldr's and vmsr) can + be in a different order. Here we just check that all the expected setup + instructions are there. We don't check that the setup instructions are + different since the likelyhood of the compiler generating repeated versions + of one rather than one and the other is very low and it's difficult to apply + such a constraint in TCL regexps (lookahead/lookbehind constraints may not + contain back references). */ +/* +** test_cde_vcx1q_mfloat16x8_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_mfloat32x4_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_muint8x16_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_muint16x8_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_muint32x4_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_muint64x2_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_mint8x16_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_mint16x8_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_mint32x4_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1q_mint64x2_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1t p0, q0, #32 +** bx lr +*/ + + +/* +** test_cde_vcx1qa_mfloat16x8_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_mfloat32x4_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_muint8x16_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_muint16x8_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_muint32x4_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_muint64x2_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_mint8x16_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_mint16x8_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_mint32x4_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ +/* +** test_cde_vcx1qa_mint64x2_tintint: +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** (?:vldr\.64 d0, \.L[0-9]*\n\tvldr\.64 d1, \.L[0-9]*\+8|vmsr P0, r2 @ movhi) +** vpst +** vcx1at p0, q0, #32 +** bx lr +*/ + + +/* +** test_cde_vcx2q_mfloat16x8_tuint16x8_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_mfloat16x8_tfloat32x4_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_mfloat32x4_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_mint64x2_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_mint8x16_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_muint16x8_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_muint8x16_tint64x2_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_muint8x16_tint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_muint8x16_tuint16x8_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2q_muint8x16_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2t p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ + + +/* +** test_cde_vcx2qa_mfloat16x8_tuint16x8_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_mfloat16x8_tfloat32x4_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_mfloat32x4_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_mint64x2_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_mint8x16_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_muint16x8_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_muint8x16_tint64x2_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_muint8x16_tint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_muint8x16_tuint16x8_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx2qa_muint8x16_tuint8x16_tint: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r1 @ movhi) +** vpst +** vcx2at p0, (q[0-7]), q0, #32 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ + + +/* +** test_cde_vcx3q_muint8x16_tuint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_mfloat16x8_tfloat16x8_tfloat16x8_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_mfloat32x4_tuint64x2_tfloat16x8_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_muint16x8_tuint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_muint8x16_tuint16x8_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_muint8x16_tuint8x16_tuint16x8_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_mint8x16_tuint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_muint8x16_tint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_muint8x16_tuint8x16_tint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_mint64x2_tuint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_muint8x16_tint64x2_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_muint8x16_tuint8x16_tint64x2_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3q_muint8x16_tint64x2_tint64x2_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3t p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ + + +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_mfloat16x8_tfloat16x8_tfloat16x8_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_mfloat32x4_tuint64x2_tfloat16x8_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_muint16x8_tuint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint16x8_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_tuint16x8_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_mint8x16_tuint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_muint8x16_tint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_tint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_mint64x2_tuint8x16_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_muint8x16_tint64x2_tuint8x16_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_tint64x2_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ +/* +** test_cde_vcx3qa_muint8x16_tint64x2_tint64x2_t: +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** (?:vldr\.64 d(?:[02468]|1[024]), \.L[0-9]*\n\tvldr\.64 d(?:[13579]|1[135]), \.L[0-9]*\+8|vmsr P0, r0 @ movhi) +** vpst +** vcx3at p0, (q[0-7]), q0, q1, #15 +** vmov q0, \1([[:space:]]+@ [^\n]*)? +** bx lr +*/ diff --git a/gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c b/gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c index 11341cb..e73ce2f 100644 --- a/gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c +++ b/gcc/testsuite/gcc.target/arm/acle/cde-mve-tests.c @@ -4,7 +4,7 @@ /* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ /* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ /* { dg-final { check-function-bodies "**" "" } } */ - +/* { dg-additional-options "-mfpu=auto" } */ /* Test that the assembly is produced as expected. Test that the same thing happens for each valid type. @@ -12,16 +12,6 @@ type combination, just checking "all same type" and "different types", also want to check every valid type at least once) */ -#define TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, accum_type, n_type, m_type, arguments) \ - accum_type test_cde_##name##accum_type##n_type##m_type ( \ - __attribute__ ((unused)) n_type n, \ - __attribute__ ((unused)) m_type m) \ - { \ - accum_type accum = (accum_type)(uint32x4_t){0,0,0,0}; \ - accum += (accum_type) __arm_##name arguments; \ - return accum; \ - } - /* Use every valid type for the output -- demonstrate can use any 128 bit value (which is a requirement for these intrinsics). */ #define TEST_CDE_MVE_INTRINSIC_1(name, arguments) \ @@ -68,6 +58,17 @@ TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, uint8x16_t, int64x2_t, arguments) \ TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, uint8x16_t, int64x2_t, int64x2_t, arguments) + +#define TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, accum_type, n_type, m_type, arguments) \ + accum_type test_cde_##name##accum_type##n_type##m_type ( \ + __attribute__ ((unused)) n_type n, \ + __attribute__ ((unused)) m_type m) \ + { \ + accum_type accum = (accum_type)(uint32x4_t){0,0,0,0}; \ + accum += (accum_type) __arm_##name arguments; \ + return accum; \ + } + TEST_CDE_MVE_INTRINSIC_1(vcx1q_u8, (0, 33)) TEST_CDE_MVE_INTRINSIC_1(vcx1qa, (0, accum, 33)) @@ -79,6 +80,27 @@ TEST_CDE_MVE_INTRINSIC_3(vcx3q_u8, (0, n, m, 12)) TEST_CDE_MVE_INTRINSIC_3(vcx3q, (0, n, m, 12)) TEST_CDE_MVE_INTRINSIC_3(vcx3qa, (0, accum, n, m, 12)) +#undef TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE +#define TEST_CDE_MVE_INTRINSIC_SPECIFIED_TYPE(name, accum_type, n_type, m_type, arguments) \ + accum_type test_cde_##name##accum_type##n_type##m_type ( \ + __attribute__ ((unused)) n_type n, \ + __attribute__ ((unused)) m_type m, \ + mve_pred16_t pred) \ + { \ + accum_type accum = (accum_type)(uint32x4_t){0,0,0,0}; \ + accum += (accum_type) __arm_##name arguments; \ + return accum; \ + } + +TEST_CDE_MVE_INTRINSIC_1(vcx1q_m, (0, accum, 32, pred)) +TEST_CDE_MVE_INTRINSIC_1(vcx1qa_m, (0, accum, 32, pred)) + +TEST_CDE_MVE_INTRINSIC_2(vcx2q_m, (0, accum, n, 32, pred)) +TEST_CDE_MVE_INTRINSIC_2(vcx2qa_m, (0, accum, n, 32, pred)) + +TEST_CDE_MVE_INTRINSIC_3(vcx3q_m, (0, accum, n, m, 15, pred)) +TEST_CDE_MVE_INTRINSIC_3(vcx3qa_m, (0, accum, n, m, 15, pred)) + /* This testcase checks that in all compilations this C code produces the expected CDE instructions from the above intrinsics. @@ -101,6 +123,13 @@ TEST_CDE_MVE_INTRINSIC_3(vcx3qa, (0, accum, n, m, 12)) /* { dg-final { scan-assembler-times "\tvcx3\t" 30 } } */ /* { dg-final { scan-assembler-times "\tvcx3a\t" 15 } } */ +/* { dg-final { scan-assembler-times "\tvcx1t\t" 11 } } */ +/* { dg-final { scan-assembler-times "\tvcx1at\t" 11 } } */ +/* { dg-final { scan-assembler-times "\tvcx2t\t" 12 } } */ +/* { dg-final { scan-assembler-times "\tvcx2at\t" 12 } } */ +/* { dg-final { scan-assembler-times "\tvcx3t\t" 15 } } */ +/* { dg-final { scan-assembler-times "\tvcx3at\t" 15 } } */ + /* ** test_cde_vcx1q_u8__builtin_neon_tiintint: ** ... @@ -720,3 +749,535 @@ TEST_CDE_MVE_INTRINSIC_3(vcx3qa, (0, accum, n, m, 12)) ** ... */ +/* +** test_cde_vcx1q_m__builtin_neon_tiintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_mfloat16x8_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_mfloat32x4_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_muint8x16_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_muint16x8_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_muint32x4_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_muint64x2_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_mint8x16_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_mint16x8_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_mint32x4_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1q_mint64x2_tintint: +** ... +** vpst +** vcx1t p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_m__builtin_neon_tiintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_mfloat16x8_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_mfloat32x4_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_muint8x16_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_muint16x8_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_muint32x4_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_muint64x2_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_mint8x16_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_mint16x8_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_mint32x4_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx1qa_mint64x2_tintint: +** ... +** vpst +** vcx1at p0, q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_m__builtin_neon_tiuint8x16_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_muint8x16_t__builtin_neon_tiint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_mfloat16x8_tuint16x8_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_mfloat16x8_tfloat32x4_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_mfloat32x4_tuint8x16_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_mint64x2_tuint8x16_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_mint8x16_tuint8x16_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_muint16x8_tuint8x16_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_muint8x16_tint64x2_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_muint8x16_tint8x16_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_muint8x16_tuint16x8_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2q_muint8x16_tuint8x16_tint: +** ... +** vpst +** vcx2t p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_m__builtin_neon_tiuint8x16_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_muint8x16_t__builtin_neon_tiint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_mfloat16x8_tuint16x8_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_mfloat16x8_tfloat32x4_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_mfloat32x4_tuint8x16_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_mint64x2_tuint8x16_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_mint8x16_tuint8x16_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_muint16x8_tuint8x16_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_muint8x16_tint64x2_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_muint8x16_tint8x16_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_muint8x16_tuint16x8_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx2qa_muint8x16_tuint8x16_tint: +** ... +** vpst +** vcx2at p0, q[0-7], q[0-7], #32 +** ... +*/ +/* +** test_cde_vcx3q_m__builtin_neon_tiuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tuint8x16_t__builtin_neon_ti: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_mfloat16x8_tfloat16x8_tfloat16x8_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_mfloat32x4_tuint64x2_tfloat16x8_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint16x8_tuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tuint16x8_tuint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tuint8x16_tuint16x8_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_mint8x16_tuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tint8x16_tuint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tuint8x16_tint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_mint64x2_tuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tint64x2_tuint8x16_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tuint8x16_tint64x2_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3q_muint8x16_tint64x2_tint64x2_t: +** ... +** vpst +** vcx3t p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_m__builtin_neon_tiuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_t__builtin_neon_ti: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_mfloat16x8_tfloat16x8_tfloat16x8_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_mfloat32x4_tuint64x2_tfloat16x8_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint16x8_tuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint16x8_tuint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_tuint16x8_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_mint8x16_tuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tint8x16_tuint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_tint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_mint64x2_tuint8x16_tuint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tint64x2_tuint8x16_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tuint8x16_tint64x2_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ +/* +** test_cde_vcx3qa_muint8x16_tint64x2_tint64x2_t: +** ... +** vpst +** vcx3at p0, q[0-7], q[0-7], q[0-7], #15 +** ... +*/ diff --git a/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c index 023fab4..121d201 100644 --- a/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c +++ b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c @@ -26,18 +26,18 @@ uint64_t test_coproc_range (uint32_t a, uint64_t b) uint64_t test_imm_range (uint32_t a, uint64_t b) { uint64_t res = 0; - res += __arm_vcx1_u32 (0, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */ - res += __arm_vcx1a_u32 (0, a, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */ - res += __arm_vcx2_u32 (0, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */ - res += __arm_vcx2a_u32 (0, a, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */ - res += __arm_vcx3_u32 (0, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */ - res += __arm_vcx3a_u32 (0, a, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */ - res += __arm_vcx1d_u64 (0, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */ - res += __arm_vcx1da_u64 (0, a, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */ - res += __arm_vcx2d_u64 (0, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */ - res += __arm_vcx2da_u64 (0, a, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */ - res += __arm_vcx3d_u64 (0, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */ - res += __arm_vcx3da_u64 (0, a, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx1_u32 (0, 2048); /* { dg-error {argument [2-5] to '__builtin_arm_vcx1si' must be a constant immediate in range \[0-2047\]} } */ + res += __arm_vcx1a_u32 (0, a, 2048); /* { dg-error {argument [2-5] to '__builtin_arm_vcx1asi' must be a constant immediate in range \[0-2047\]} } */ + res += __arm_vcx2_u32 (0, a, 64); /* { dg-error {argument [2-5] to '__builtin_arm_vcx2si' must be a constant immediate in range \[0-63\]} } */ + res += __arm_vcx2a_u32 (0, a, a, 64); /* { dg-error {argument [2-5] to '__builtin_arm_vcx2asi' must be a constant immediate in range \[0-63\]} } */ + res += __arm_vcx3_u32 (0, a, a, 8); /* { dg-error {argument [2-5] to '__builtin_arm_vcx3si' must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx3a_u32 (0, a, a, a, 8); /* { dg-error {argument [2-5] to '__builtin_arm_vcx3asi' must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx1d_u64 (0, 2048); /* { dg-error {argument [2-5] to '__builtin_arm_vcx1di' must be a constant immediate in range \[0-2047\]} } */ + res += __arm_vcx1da_u64 (0, a, 2048); /* { dg-error {argument [2-5] to '__builtin_arm_vcx1adi' must be a constant immediate in range \[0-2047\]} } */ + res += __arm_vcx2d_u64 (0, a, 64); /* { dg-error {argument [2-5] to '__builtin_arm_vcx2di' must be a constant immediate in range \[0-63\]} } */ + res += __arm_vcx2da_u64 (0, a, a, 64); /* { dg-error {argument [2-5] to '__builtin_arm_vcx2adi' must be a constant immediate in range \[0-63\]} } */ + res += __arm_vcx3d_u64 (0, a, a, 8); /* { dg-error {argument [2-5] to '__builtin_arm_vcx3di' must be a constant immediate in range \[0-7\]} } */ + res += __arm_vcx3da_u64 (0, a, a, a, 8); /* { dg-error {argument [2-5] to '__builtin_arm_vcx3adi' must be a constant immediate in range \[0-7\]} } */ return res; } diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vldrwq_gather_base_wb_z_f32.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vldrwq_gather_base_wb_z_f32.c index f1ba638..9fb47da 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vldrwq_gather_base_wb_z_f32.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vldrwq_gather_base_wb_z_f32.c @@ -11,7 +11,7 @@ foo (uint32x4_t * addr, mve_pred16_t p) } /* { dg-final { scan-assembler "vldrb.8 q\[0-9\]+, \\\[r\[0-9\]+\\\]" } } */ -/* { dg-final { scan-assembler "vmsr\tP0, r\[0-9\]+.*" } } */ +/* { dg-final { scan-assembler "vmsr\t P0, r\[0-9\]+.*" } } */ /* { dg-final { scan-assembler "vpst" } } */ /* { dg-final { scan-assembler "vldrwt.u32\tq\[0-9\]+, \\\[q\[0-9\]+, #\[0-9\]+\\\]!" } } */ /* { dg-final { scan-assembler "vstrb.8 q\[0-9\]+, \\\[r\[0-9\]+\\\]" } } */ -- cgit v1.1 From 70df40cab6f268ba7f05c6d1421928cca0834ee3 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Wed, 8 Apr 2020 17:16:55 +0200 Subject: Allow new/delete operator deletion only for replaceable. PR c++/94314 * gimple.c (gimple_call_operator_delete_p): Rename to... (gimple_call_replaceable_operator_delete_p): ... this. Use DECL_IS_REPLACEABLE_OPERATOR_DELETE_P. * gimple.h (gimple_call_operator_delete_p): Rename to ... (gimple_call_replaceable_operator_delete_p): ... this. * tree-core.h (tree_function_decl): Add replaceable_operator flag. * tree-ssa-dce.c (mark_all_reaching_defs_necessary_1): Use DECL_IS_REPLACEABLE_OPERATOR_DELETE_P. (propagate_necessity): Use gimple_call_replaceable_operator_delete_p. (eliminate_unnecessary_stmts): Likewise. * tree-streamer-in.c (unpack_ts_function_decl_value_fields): Pack DECL_IS_REPLACEABLE_OPERATOR. * tree-streamer-out.c (pack_ts_function_decl_value_fields): Unpack the field here. * tree.h (DECL_IS_REPLACEABLE_OPERATOR): New. (DECL_IS_REPLACEABLE_OPERATOR_NEW_P): New. (DECL_IS_REPLACEABLE_OPERATOR_DELETE_P): New. * cgraph.c (cgraph_node::dump): Dump if an operator is replaceable. * ipa-icf.c (sem_item::compare_referenced_symbol_properties): Compare replaceable operator flags. PR c++/94314 * decl.c (duplicate_decls): Duplicate also DECL_IS_REPLACEABLE_OPERATOR. (cxx_init_decl_processing): Mark replaceable all implicitly defined operators. PR c++/94314 * lto-common.c (compare_tree_sccs_1): Compare also DECL_IS_REPLACEABLE_OPERATOR. PR c++/94314 * g++.dg/pr94314-2.C: New test. * g++.dg/pr94314-3.C: New test. * g++.dg/pr94314.C: New test. --- gcc/ChangeLog | 25 ++++++++++++ gcc/cgraph.c | 7 ++-- gcc/cp/ChangeLog | 7 ++++ gcc/cp/decl.c | 14 +++++++ gcc/gimple.c | 6 +-- gcc/gimple.h | 2 +- gcc/ipa-icf.c | 4 ++ gcc/lto/ChangeLog | 6 +++ gcc/lto/lto-common.c | 1 + gcc/testsuite/ChangeLog | 7 ++++ gcc/testsuite/g++.dg/pr94314-2.C | 26 ++++++++++++ gcc/testsuite/g++.dg/pr94314-3.C | 55 ++++++++++++++++++++++++++ gcc/testsuite/g++.dg/pr94314.C | 85 ++++++++++++++++++++++++++++++++++++++++ gcc/tree-core.h | 3 +- gcc/tree-ssa-dce.c | 8 ++-- gcc/tree-streamer-in.c | 1 + gcc/tree-streamer-out.c | 1 + gcc/tree.h | 10 ++++- 18 files changed, 255 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr94314-2.C create mode 100644 gcc/testsuite/g++.dg/pr94314-3.C create mode 100644 gcc/testsuite/g++.dg/pr94314.C (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ffd4679..88e7952 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2020-04-08 Martin Liska + + PR c++/94314 + * gimple.c (gimple_call_operator_delete_p): Rename to... + (gimple_call_replaceable_operator_delete_p): ... this. + Use DECL_IS_REPLACEABLE_OPERATOR_DELETE_P. + * gimple.h (gimple_call_operator_delete_p): Rename to ... + (gimple_call_replaceable_operator_delete_p): ... this. + * tree-core.h (tree_function_decl): Add replaceable_operator + flag. + * tree-ssa-dce.c (mark_all_reaching_defs_necessary_1): + Use DECL_IS_REPLACEABLE_OPERATOR_DELETE_P. + (propagate_necessity): Use gimple_call_replaceable_operator_delete_p. + (eliminate_unnecessary_stmts): Likewise. + * tree-streamer-in.c (unpack_ts_function_decl_value_fields): + Pack DECL_IS_REPLACEABLE_OPERATOR. + * tree-streamer-out.c (pack_ts_function_decl_value_fields): + Unpack the field here. + * tree.h (DECL_IS_REPLACEABLE_OPERATOR): New. + (DECL_IS_REPLACEABLE_OPERATOR_NEW_P): New. + (DECL_IS_REPLACEABLE_OPERATOR_DELETE_P): New. + * cgraph.c (cgraph_node::dump): Dump if an operator is replaceable. + * ipa-icf.c (sem_item::compare_referenced_symbol_properties): Compare + replaceable operator flags. + 2020-04-08 Dennis Zhang Matthew Malcomson diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 6b780f8..ecb234d 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2157,10 +2157,11 @@ cgraph_node::dump (FILE *f) if (parallelized_function) fprintf (f, " parallelized_function"); if (DECL_IS_OPERATOR_NEW_P (decl)) - fprintf (f, " operator_new"); + fprintf (f, " %soperator_new", + DECL_IS_REPLACEABLE_OPERATOR (decl) ? "replaceable_" : ""); if (DECL_IS_OPERATOR_DELETE_P (decl)) - fprintf (f, " operator_delete"); - + fprintf (f, " %soperator_delete", + DECL_IS_REPLACEABLE_OPERATOR (decl) ? "replaceable_" : ""); fprintf (f, "\n"); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cedd157..7c5edc2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2020-04-08 Martin Liska + + PR c++/94314 + * decl.c (duplicate_decls): Duplicate also DECL_IS_REPLACEABLE_OPERATOR. + (cxx_init_decl_processing): Mark replaceable all implicitly defined + operators. + 2020-04-08 Patrick Palka Core issues 1001 and 1322 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0ea4b320..a6a1340 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2368,6 +2368,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) DECL_SET_IS_OPERATOR_NEW (newdecl, true); DECL_LOOPING_CONST_OR_PURE_P (newdecl) |= DECL_LOOPING_CONST_OR_PURE_P (olddecl); + DECL_IS_REPLACEABLE_OPERATOR (newdecl) + |= DECL_IS_REPLACEABLE_OPERATOR (olddecl); if (merge_attr) merge_attribute_bits (newdecl, olddecl); @@ -4438,13 +4440,17 @@ cxx_init_decl_processing (void) tree opnew = push_cp_library_fn (NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; DECL_SET_IS_OPERATOR_NEW (opnew, true); + DECL_IS_REPLACEABLE_OPERATOR (opnew) = 1; opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; DECL_SET_IS_OPERATOR_NEW (opnew, true); + DECL_IS_REPLACEABLE_OPERATOR (opnew) = 1; tree opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); DECL_SET_IS_OPERATOR_DELETE (opdel, true); + DECL_IS_REPLACEABLE_OPERATOR (opdel) = 1; opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); DECL_SET_IS_OPERATOR_DELETE (opdel, true); + DECL_IS_REPLACEABLE_OPERATOR (opdel) = 1; if (flag_sized_deallocation) { /* Also push the sized deallocation variants: @@ -4458,8 +4464,10 @@ cxx_init_decl_processing (void) deltype = build_exception_variant (deltype, empty_except_spec); opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); DECL_SET_IS_OPERATOR_DELETE (opdel, true); + DECL_IS_REPLACEABLE_OPERATOR (opdel) = 1; opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); DECL_SET_IS_OPERATOR_DELETE (opdel, true); + DECL_IS_REPLACEABLE_OPERATOR (opdel) = 1; } if (aligned_new_threshold) @@ -4478,9 +4486,11 @@ cxx_init_decl_processing (void) opnew = push_cp_library_fn (NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; DECL_SET_IS_OPERATOR_NEW (opnew, true); + DECL_IS_REPLACEABLE_OPERATOR (opnew) = 1; opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; DECL_SET_IS_OPERATOR_NEW (opnew, true); + DECL_IS_REPLACEABLE_OPERATOR (opnew) = 1; /* operator delete (void *, align_val_t); */ deltype = build_function_type_list (void_type_node, ptr_type_node, @@ -4489,8 +4499,10 @@ cxx_init_decl_processing (void) deltype = build_exception_variant (deltype, empty_except_spec); opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); DECL_SET_IS_OPERATOR_DELETE (opdel, true); + DECL_IS_REPLACEABLE_OPERATOR (opdel) = 1; opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); DECL_SET_IS_OPERATOR_DELETE (opdel, true); + DECL_IS_REPLACEABLE_OPERATOR (opdel) = 1; if (flag_sized_deallocation) { @@ -4502,8 +4514,10 @@ cxx_init_decl_processing (void) deltype = build_exception_variant (deltype, empty_except_spec); opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); DECL_SET_IS_OPERATOR_DELETE (opdel, true); + DECL_IS_REPLACEABLE_OPERATOR (opdel) = 1; opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); DECL_SET_IS_OPERATOR_DELETE (opdel, true); + DECL_IS_REPLACEABLE_OPERATOR (opdel) = 1; } } diff --git a/gcc/gimple.c b/gcc/gimple.c index 61a400b..10c562f 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -2730,15 +2730,15 @@ gimple_builtin_call_types_compatible_p (const gimple *stmt, tree fndecl) return true; } -/* Return true when STMT is operator delete call. */ +/* Return true when STMT is operator a replaceable delete call. */ bool -gimple_call_operator_delete_p (const gcall *stmt) +gimple_call_replaceable_operator_delete_p (const gcall *stmt) { tree fndecl; if ((fndecl = gimple_call_fndecl (stmt)) != NULL_TREE) - return DECL_IS_OPERATOR_DELETE_P (fndecl); + return DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (fndecl); return false; } diff --git a/gcc/gimple.h b/gcc/gimple.h index 305d98f..ca7fec6 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1615,7 +1615,7 @@ extern alias_set_type gimple_get_alias_set (tree); extern bool gimple_ior_addresses_taken (bitmap, gimple *); extern bool gimple_builtin_call_types_compatible_p (const gimple *, tree); extern combined_fn gimple_call_combined_fn (const gimple *); -extern bool gimple_call_operator_delete_p (const gcall *); +extern bool gimple_call_replaceable_operator_delete_p (const gcall *); extern bool gimple_call_builtin_p (const gimple *); extern bool gimple_call_builtin_p (const gimple *, enum built_in_class); extern bool gimple_call_builtin_p (const gimple *, enum built_in_function); diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 17a0ed9..069de9d 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -347,6 +347,10 @@ sem_item::compare_referenced_symbol_properties (symtab_node *used_by, if (DECL_IS_OPERATOR_NEW_P (n1->decl) != DECL_IS_OPERATOR_NEW_P (n2->decl)) return return_false_with_msg ("operator new flags are different"); + + if (DECL_IS_REPLACEABLE_OPERATOR (n1->decl) + != DECL_IS_REPLACEABLE_OPERATOR (n2->decl)) + return return_false_with_msg ("replaceable operator flags are different"); } /* Merging two definitions with a reference to equivalent vtables, but diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 4171a3d..829b26d 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Martin Liska + + PR c++/94314 + * lto-common.c (compare_tree_sccs_1): Compare also + DECL_IS_REPLACEABLE_OPERATOR. + 2020-03-25 Jakub Jelinek PR c++/94223 diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c index c95a9b0..e073abc 100644 --- a/gcc/lto/lto-common.c +++ b/gcc/lto/lto-common.c @@ -1236,6 +1236,7 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map) compare_values (DECL_DISREGARD_INLINE_LIMITS); compare_values (DECL_PURE_P); compare_values (DECL_LOOPING_CONST_OR_PURE_P); + compare_values (DECL_IS_REPLACEABLE_OPERATOR); compare_values (DECL_FINAL_P); compare_values (DECL_CXX_CONSTRUCTOR_P); compare_values (DECL_CXX_DESTRUCTOR_P); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9b2d1f6..a420dea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-04-08 Martin Liska + + PR c++/94314 + * g++.dg/pr94314-2.C: New test. + * g++.dg/pr94314-3.C: New test. + * g++.dg/pr94314.C: New test. + 2020-04-08 Dennis Zhang * gcc.target/arm/acle/cde_v_1.c: New test. diff --git a/gcc/testsuite/g++.dg/pr94314-2.C b/gcc/testsuite/g++.dg/pr94314-2.C new file mode 100644 index 0000000..36b93ed --- /dev/null +++ b/gcc/testsuite/g++.dg/pr94314-2.C @@ -0,0 +1,26 @@ +/* PR c++/94314. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-cddce-details" } */ +/* { dg-additional-options "-fdelete-null-pointer-checks" } */ + +#include + +struct A +{ + __attribute__((always_inline)) A(int x) + { + if (x == 123) + throw x; + } +}; + +int +main(int argc, char **argv) +{ + A *a = new A (argc); + delete a; + + return 0; +} + +/* { dg-final { scan-tree-dump-times "Deleting : operator delete" 2 "cddce1"} } */ diff --git a/gcc/testsuite/g++.dg/pr94314-3.C b/gcc/testsuite/g++.dg/pr94314-3.C new file mode 100644 index 0000000..a5b1013 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr94314-3.C @@ -0,0 +1,55 @@ +/* PR c++/94314. */ +/* { dg-do run } */ +/* { dg-options "-O2 --param early-inlining-insns=100 -fdump-tree-cddce-details" } */ +/* { dg-additional-options "-fdelete-null-pointer-checks" } */ + +#include + +volatile int idx; + +struct base +{ + __attribute__ ((malloc, noinline)) static void * + operator new (unsigned long sz) + { + return ::operator new (sz); + } + + __attribute__ ((noinline)) static void operator delete (void *ptr) + { + int c = count[idx]; + count[idx] = c - 1; + ::operator delete (ptr); + } + volatile static int count[2]; +}; + +volatile int base::count[2] = {0, 0}; + +struct B : base +{ + static void *operator new (unsigned long sz) + { + int c = count[idx]; + count[idx] = c + 1; + return base::operator new (sz); + } +}; + +volatile int c = 1; + +int +main () +{ + for (int i; i < c; i++) + { + idx = 0; + delete new B; + if (B::count[0] != 0) + __builtin_abort (); + } + + return 0; +} + +/* { dg-final { scan-tree-dump-not "Deleting : operator delete" "cddce1"} } */ diff --git a/gcc/testsuite/g++.dg/pr94314.C b/gcc/testsuite/g++.dg/pr94314.C new file mode 100644 index 0000000..a06800d2 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr94314.C @@ -0,0 +1,85 @@ +/* PR c++/94314. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-cddce-details" } */ +/* { dg-additional-options "-fdelete-null-pointer-checks" } */ + +#include + +struct A +{ + __attribute__((malloc,noinline)) + static void* operator new(unsigned long sz) + { + ++count; + return ::operator new(sz); + } + + static void operator delete(void* ptr) + { + --count; + ::operator delete(ptr); + } + + static int count; +}; + +int A::count = 0; + +struct B +{ + __attribute__((malloc,noinline)) + static void* operator new(unsigned long sz) + { + ++count; + return ::operator new(sz); + } + + __attribute__((noinline)) + static void operator delete(void* ptr) + { + --count; + ::operator delete(ptr); + } + + static int count; +}; + +int B::count = 0; + +struct C +{ + static void* operator new(unsigned long sz) + { + ++count; + return ::operator new(sz); + } + + static void operator delete(void* ptr) + { + --count; + ::operator delete(ptr); + } + + static int count; +}; + +int C::count = 0; + +int main(){ + delete new A; + if (A::count != 0) + __builtin_abort (); + + delete new B; + if (B::count != 0) + __builtin_abort (); + + delete new C; + if (C::count != 0) + __builtin_abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "Deleting : operator delete" 1 "cddce1"} } */ +/* { dg-final { scan-tree-dump-not "Deleting : B::operator delete" "cddce1"} } */ diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 765ea2a..d84fe95 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1896,8 +1896,9 @@ struct GTY(()) tree_function_decl { ENUM_BITFIELD(function_decl_type) decl_type: 2; unsigned has_debug_args_flag : 1; unsigned versioned_function : 1; + unsigned replaceable_operator : 1; - /* 12 bits left for future expansion. */ + /* 11 bits left for future expansion. */ }; struct GTY(()) tree_translation_unit_decl { diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index e4077b5..fd5f24c 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -614,7 +614,7 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED, if (callee != NULL_TREE && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee) - || DECL_IS_OPERATOR_DELETE_P (callee))) + || DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (callee))) return false; } @@ -806,7 +806,7 @@ propagate_necessity (bool aggressive) processing the argument. */ bool is_delete_operator = (is_gimple_call (stmt) - && gimple_call_operator_delete_p (as_a (stmt))); + && gimple_call_replaceable_operator_delete_p (as_a (stmt))); if (is_delete_operator || gimple_call_builtin_p (stmt, BUILT_IN_FREE)) { @@ -896,7 +896,7 @@ propagate_necessity (bool aggressive) if (callee != NULL_TREE && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee) - || DECL_IS_OPERATOR_DELETE_P (callee))) + || DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (callee))) continue; /* Calls implicitly load from memory, their arguments @@ -1321,7 +1321,7 @@ eliminate_unnecessary_stmts (void) if (gimple_plf (stmt, STMT_NECESSARY) && (gimple_call_builtin_p (stmt, BUILT_IN_FREE) || (is_gimple_call (stmt) - && gimple_call_operator_delete_p (as_a (stmt))))) + && gimple_call_replaceable_operator_delete_p (as_a (stmt))))) { tree ptr = gimple_call_arg (stmt, 0); if (TREE_CODE (ptr) == SSA_NAME) diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c index 4e035e9..0bfc272 100644 --- a/gcc/tree-streamer-in.c +++ b/gcc/tree-streamer-in.c @@ -343,6 +343,7 @@ unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr) DECL_DISREGARD_INLINE_LIMITS (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_LOOPING_CONST_OR_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1); + DECL_IS_REPLACEABLE_OPERATOR (expr) = (unsigned) bp_unpack_value (bp, 1); unsigned int fcode = 0; if (cl != NOT_BUILT_IN) { diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c index 8e5e135..5bbcebb 100644 --- a/gcc/tree-streamer-out.c +++ b/gcc/tree-streamer-out.c @@ -305,6 +305,7 @@ pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr) bp_pack_value (bp, DECL_DISREGARD_INLINE_LIMITS (expr), 1); bp_pack_value (bp, DECL_PURE_P (expr), 1); bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1); + bp_pack_value (bp, DECL_IS_REPLACEABLE_OPERATOR (expr), 1); if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN) bp_pack_value (bp, DECL_UNCHECKED_FUNCTION_CODE (expr), 32); } diff --git a/gcc/tree.h b/gcc/tree.h index 66dfa87..1c28785 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3037,6 +3037,11 @@ set_function_decl_type (tree decl, function_decl_type t, bool set) FUNCTION_DECL_DECL_TYPE (decl) = NONE; } +/* Nonzero in a FUNCTION_DECL means this function is a replaceable + function (like replaceable operators new or delete). */ +#define DECL_IS_REPLACEABLE_OPERATOR(NODE)\ + (FUNCTION_DECL_CHECK (NODE)->function_decl.replaceable_operator) + /* Nonzero in a FUNCTION_DECL means this function should be treated as C++ operator new, meaning that it returns a pointer for which we should not use type based aliasing. */ @@ -3044,7 +3049,7 @@ set_function_decl_type (tree decl, function_decl_type t, bool set) (FUNCTION_DECL_CHECK (NODE)->function_decl.decl_type == OPERATOR_NEW) #define DECL_IS_REPLACEABLE_OPERATOR_NEW_P(NODE) \ - (DECL_IS_OPERATOR_NEW_P (NODE) && DECL_IS_MALLOC (NODE)) + (DECL_IS_OPERATOR_NEW_P (NODE) && DECL_IS_REPLACEABLE_OPERATOR (NODE)) #define DECL_SET_IS_OPERATOR_NEW(NODE, VAL) \ set_function_decl_type (FUNCTION_DECL_CHECK (NODE), OPERATOR_NEW, VAL) @@ -3054,6 +3059,9 @@ set_function_decl_type (tree decl, function_decl_type t, bool set) #define DECL_IS_OPERATOR_DELETE_P(NODE) \ (FUNCTION_DECL_CHECK (NODE)->function_decl.decl_type == OPERATOR_DELETE) +#define DECL_IS_REPLACEABLE_OPERATOR_DELETE_P(NODE) \ + (DECL_IS_OPERATOR_DELETE_P (NODE) && DECL_IS_REPLACEABLE_OPERATOR (NODE)) + #define DECL_SET_IS_OPERATOR_DELETE(NODE, VAL) \ set_function_decl_type (FUNCTION_DECL_CHECK (NODE), OPERATOR_DELETE, VAL) -- cgit v1.1 From e4b84abcc46fb4270172584ac5a4b46d70e93259 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 8 Apr 2020 12:41:52 -0300 Subject: require tls_runtime for tls execution test All TLS execution tests require tls_runtime, not just tls; pr78796.c is the only exception that is not otherwise limited to platforms known to support it. I suppose that's an oversight. On a platform whose linker is configured to disregard TLS relocations, this test compiles and assembles successfully, but execution fails. The tls_runtime requirement target avoids the noise from the expected failure. for gcc/testsuite/ChangeLog * gcc.dg/tls/pr78796.c: Require tls_runtime. --- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/tls/pr78796.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a420dea..557c815 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-04-08 Alexandre Oliva + + * gcc.dg/tls/pr78796.c: Require tls_runtime. + 2020-04-08 Martin Liska PR c++/94314 diff --git a/gcc/testsuite/gcc.dg/tls/pr78796.c b/gcc/testsuite/gcc.dg/tls/pr78796.c index a0b23d6..038e536 100644 --- a/gcc/testsuite/gcc.dg/tls/pr78796.c +++ b/gcc/testsuite/gcc.dg/tls/pr78796.c @@ -2,7 +2,7 @@ /* { dg-do run } */ /* { dg-options "-O2" } */ /* { dg-additional-options "-mcmodel=large" { target aarch64-*-* } } */ -/* { dg-require-effective-target tls } */ +/* { dg-require-effective-target tls_runtime } */ /* { dg-add-options tls } */ struct S { int a, b, c, d, e; }; -- cgit v1.1 From faa0817311f43e0d4d223d53c816b0c74ec35c4e Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Wed, 8 Apr 2020 17:54:04 +0200 Subject: Move gfortran.dg/dec_math_5.f90 to ./ieee/ PR fortran/93871 * gfortran.dg/dec_math_5.f90: Move to ... * gfortran.dg/ieee/dec_math_1.f90: ... here; change dg-options to dg-additional-options. --- gcc/testsuite/ChangeLog | 7 + gcc/testsuite/gfortran.dg/dec_math_5.f90 | 228 ------------------------- gcc/testsuite/gfortran.dg/ieee/dec_math_1.f90 | 231 ++++++++++++++++++++++++++ 3 files changed, 238 insertions(+), 228 deletions(-) delete mode 100644 gcc/testsuite/gfortran.dg/dec_math_5.f90 create mode 100644 gcc/testsuite/gfortran.dg/ieee/dec_math_1.f90 (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 557c815..3471816 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-04-08 Tobias Burnus + + PR fortran/93871 + * gfortran.dg/dec_math_5.f90: Move to ... + * gfortran.dg/ieee/dec_math_1.f90: ... here; change + dg-options to dg-additional-options. + 2020-04-08 Alexandre Oliva * gcc.dg/tls/pr78796.c: Require tls_runtime. diff --git a/gcc/testsuite/gfortran.dg/dec_math_5.f90 b/gcc/testsuite/gfortran.dg/dec_math_5.f90 deleted file mode 100644 index d761e03..0000000 --- a/gcc/testsuite/gfortran.dg/dec_math_5.f90 +++ /dev/null @@ -1,228 +0,0 @@ -! { dg-options "-cpp -std=gnu" } -! { dg-do run } -! -! Test values for degree-valued trigonometric intrinsics. -! - -module dec_math_5 - - - ! Use the highest precision available. - ! Note however that if both __GFC_REAL_10__ and __GFC_REAL_16__ are defined, - ! the size of real(16) is actually that of REAL(10) (80 bits) in which case - ! we should not over-estimate the precision available, or the test will fail. -#if defined(__GFC_REAL_10__) - integer, parameter :: real_kind = 10 - real(real_kind), parameter :: eps = 5e-11_10 - - real(real_kind), parameter :: pi_2 = 1.57079632679489656_10 - real(real_kind), parameter :: pi = 3.14159265358979312_10 - real(real_kind), parameter :: tau = 6.28318530717958623_10 - -#elif defined(__GFC_REAL_16__) - integer, parameter :: real_kind = 16 - real(real_kind), parameter :: eps = 5e-16_16 - - real(real_kind), parameter :: pi_2 = 1.5707963267948966192313216916397514_16 - real(real_kind), parameter :: pi = 3.1415926535897932384626433832795_16 - real(real_kind), parameter :: tau = 6.28318530717958647692528676655900559_16 - -#else - integer, parameter :: real_kind = 8 - real(real_kind), parameter :: eps = 5e-10_8 - - real(real_kind), parameter :: pi_2 = 1.57079632679490_8 - real(real_kind), parameter :: pi = 3.14159265358979_8 - real(real_kind), parameter :: tau = 6.28318530717959_8 - -#endif - - ! Important angles in canonical form. - - integer, parameter :: nangle = 16 - - real(real_kind), dimension(nangle), parameter :: degrees = (/ & - 0, & ! 180 * 0 - 30, & ! 180 * 1/6 - 45, & ! 180 * 1/4 - 60, & ! 180 * 1/3 - 90, & ! 180 * 1/2 - 120, & ! 180 * 2/3 - 135, & ! 180 * 3/4 - 150, & ! 180 * 5/6 - 180, & ! 180 - 210, & ! 180 * 7/6 - 225, & ! 180 * 5/4 - 240, & ! 180 * 4/3 - 270, & ! 180 * 3/2 - 300, & ! 180 * 5/3 - 315, & ! 180 * 7/4 - 330 & ! 180 * 11/6 - /) - - real(real_kind), dimension(nangle), parameter :: radians = (/ & -#ifdef __GFC_REAL_10__ - 0.000000000000000000_10, & ! pi * 0 - 0.523598775598298873_10, & ! pi * 1/6 - 0.785398163397448310_10, & ! pi * 1/4 - 1.047197551196597750_10, & ! pi * 1/3 - 1.570796326794896620_10, & ! pi * 1/2 - 2.094395102393195490_10, & ! pi * 2/3 - 2.356194490192344930_10, & ! pi * 3/4 - 2.617993877991494370_10, & ! pi * 5/6 - 3.141592653589793240_10, & ! pi - 3.665191429188092110_10, & ! pi * 7/6 - 3.926990816987241550_10, & ! pi * 5/4 - 4.188790204786390980_10, & ! pi * 4/3 - 4.712388980384689860_10, & ! pi * 3/2 - 5.235987755982988730_10, & ! pi * 5/3 - 5.497787143782138170_10, & ! pi * 7/4 - 5.759586531581287600_10 & ! pi * 11/6 - -#elif defined(__GFC_REAL_16__) - 0.000000000000000000000000000000000_16, & ! pi * 0 - 0.523598775598298873077107230546584_16, & ! pi * 1/6 - 0.785398163397448309615660845819876_16, & ! pi * 1/4 - 1.047197551196597746154214461093170_16, & ! pi * 1/3 - 1.570796326794896619231321691639750_16, & ! pi * 1/2 - 2.094395102393195492308428922186330_16, & ! pi * 2/3 - 2.356194490192344928846982537459630_16, & ! pi * 3/4 - 2.617993877991494365385536152732920_16, & ! pi * 5/6 - 3.141592653589793238462643383279500_16, & ! pi - 3.665191429188092111539750613826090_16, & ! pi * 7/6 - 3.926990816987241548078304229099380_16, & ! pi * 5/4 - 4.188790204786390984616857844372670_16, & ! pi * 4/3 - 4.712388980384689857693965074919250_16, & ! pi * 3/2 - 5.235987755982988730771072305465840_16, & ! pi * 5/3 - 5.497787143782138167309625920739130_16, & ! pi * 7/4 - 5.759586531581287603848179536012420_16 & ! pi * 11/6 - -#else - 0.000000000000000_8, & ! pi * 0 - 0.523598775598299_8, & ! pi * 1/6 - 0.785398163397448_8, & ! pi * 1/4 - 1.047197551196600_8, & ! pi * 1/3 - 1.570796326794900_8, & ! pi * 1/2 - 2.094395102393200_8, & ! pi * 2/3 - 2.356194490192340_8, & ! pi * 3/4 - 2.617993877991490_8, & ! pi * 5/6 - 3.141592653589790_8, & ! pi - 3.665191429188090_8, & ! pi * 7/6 - 3.926990816987240_8, & ! pi * 5/4 - 4.188790204786390_8, & ! pi * 4/3 - 4.712388980384690_8, & ! pi * 3/2 - 5.235987755982990_8, & ! pi * 5/3 - 5.497787143782140_8, & ! pi * 7/4 - 5.759586531581290_8 & ! pi * 11/6 -#endif - /) - - ! sind, cosd, tand, cotand - - ! Ensure precision degrades minimally for large values. - integer, parameter :: nphase = 5 - - integer, dimension(nphase), parameter :: phases = (/ & - 0, 1, 5, 100, 10000 & - /) - -contains - - subroutine compare(strl, xl_in, xl_out, strr, xr_in, xr_out, eps) - use ieee_arithmetic - implicit none - character(*), intent(in) :: strl, strr - real(real_kind), intent(in) :: xl_in, xl_out, xr_in, xr_out, eps - - if ((ieee_is_nan(xl_out) .neqv. ieee_is_nan(xr_out)) & - .or. (ieee_is_finite(xl_out) .neqv. ieee_is_finite(xr_out)) & - .or. (abs(xl_out - xr_out) .gt. eps)) then - write (*, 100) strl, "(", xl_in, "): ", xl_out - write (*, 100) strr, "(", xr_in, "): ", xr_out - - if ((ieee_is_nan(xl_out) .eqv. ieee_is_nan(xr_out)) & - .and. ieee_is_finite(xl_out) .and. ieee_is_finite(xr_out)) then - write (*, 300) "|xl - xr| = ", abs(xl_out - xr_out) - write (*, 300) " > eps = ", eps - endif - - call abort() - endif - -#ifdef __GFC_REAL_16__ - 100 format((A8,A,F34.30,A,F34.30,F34.30)) - 200 format((A12,F34.30)) - !500 format((A8,A,G34.29,A,G34.29,G34.29)) -#elif defined(__GFC_REAL_10__) - 100 format((A8,A,F21.17,A,F21.17,F21.17)) - 200 format((A12,F21.17)) - !500 format((A8,A,G21.16,A,G21.16,G21.16)) -#else - 100 format((A8,A,F18.14,A,F18.14,F18.14)) - 200 format((A12,F18.14)) - !500 format((A8,A,G18.13,A,G18.13,G18.13)) -#endif - 300 format((A12,G8.2)) - endsubroutine - -endmodule - -use dec_math_5 -use ieee_arithmetic -implicit none - -integer :: phase_index, angle_index, phase -real(real_kind) :: deg_in, deg_out, deg_out2, rad_in, rad_out - -! Try every value in degrees, and make sure they are correct compared to the -! corresponding radian function. - -do phase_index = 1, size(phases) - phase = phases(phase_index) - - do angle_index = 1, size(degrees) - ! eqv to degrees(angle_index) modulo 360 - deg_in = degrees(angle_index) + phase * 360 - rad_in = radians(angle_index) + phase * tau - - ! sind vs. sin - deg_out = sind(deg_in) - rad_out = sin(rad_in) - call compare("sind", deg_in, deg_out, "sin", rad_in, rad_out, eps) - - ! cosd vs. cos - deg_out = cosd(deg_in) - rad_out = cos(rad_in) - call compare("cosd", deg_in, deg_out, "cos", rad_in, rad_out, eps) - - ! tand vs. tan - deg_out = tand(deg_in) - rad_out = tan(rad_in) - if ( ieee_is_finite(deg_out) ) then - call compare("tand", deg_in, deg_out, "tan", rad_in, rad_out, eps) - endif - - ! cotand vs. cotan - deg_out = cotand(deg_in) - rad_out = cotan(rad_in) - - ! Skip comparing infinity, because cotan does not return infinity - if ( ieee_is_finite(deg_out) ) then - call compare("cotand", deg_in, deg_out, "cotan", rad_in, rad_out, eps) - - ! cotand vs. tand - deg_out = cotand(deg_in) - deg_out2 = -tand(deg_in + 90) - - call compare("cotand", deg_in, deg_out, "-tand+90", deg_in, deg_out2, eps) - deg_out2 = 1 / tand(deg_in) - call compare("cotand", deg_in, deg_out, "1/tand", deg_in, deg_out2, eps) - endif - - enddo - - -enddo - - -end diff --git a/gcc/testsuite/gfortran.dg/ieee/dec_math_1.f90 b/gcc/testsuite/gfortran.dg/ieee/dec_math_1.f90 new file mode 100644 index 0000000..8587fd6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ieee/dec_math_1.f90 @@ -0,0 +1,231 @@ +! { dg-do run } +! { dg-additional-options "-cpp -std=gnu" } +! +! Test values for degree-valued trigonometric intrinsics. +! +! Run under ieee/ as +! use ieee_arithmetic +! (used for result checking) is not available on all platforms) + +module dec_math_5 + + + ! Use the highest precision available. + ! Note however that if both __GFC_REAL_10__ and __GFC_REAL_16__ are defined, + ! the size of real(16) is actually that of REAL(10) (80 bits) in which case + ! we should not over-estimate the precision available, or the test will fail. +#if defined(__GFC_REAL_10__) + integer, parameter :: real_kind = 10 + real(real_kind), parameter :: eps = 5e-11_10 + + real(real_kind), parameter :: pi_2 = 1.57079632679489656_10 + real(real_kind), parameter :: pi = 3.14159265358979312_10 + real(real_kind), parameter :: tau = 6.28318530717958623_10 + +#elif defined(__GFC_REAL_16__) + integer, parameter :: real_kind = 16 + real(real_kind), parameter :: eps = 5e-16_16 + + real(real_kind), parameter :: pi_2 = 1.5707963267948966192313216916397514_16 + real(real_kind), parameter :: pi = 3.1415926535897932384626433832795_16 + real(real_kind), parameter :: tau = 6.28318530717958647692528676655900559_16 + +#else + integer, parameter :: real_kind = 8 + real(real_kind), parameter :: eps = 5e-10_8 + + real(real_kind), parameter :: pi_2 = 1.57079632679490_8 + real(real_kind), parameter :: pi = 3.14159265358979_8 + real(real_kind), parameter :: tau = 6.28318530717959_8 + +#endif + + ! Important angles in canonical form. + + integer, parameter :: nangle = 16 + + real(real_kind), dimension(nangle), parameter :: degrees = (/ & + 0, & ! 180 * 0 + 30, & ! 180 * 1/6 + 45, & ! 180 * 1/4 + 60, & ! 180 * 1/3 + 90, & ! 180 * 1/2 + 120, & ! 180 * 2/3 + 135, & ! 180 * 3/4 + 150, & ! 180 * 5/6 + 180, & ! 180 + 210, & ! 180 * 7/6 + 225, & ! 180 * 5/4 + 240, & ! 180 * 4/3 + 270, & ! 180 * 3/2 + 300, & ! 180 * 5/3 + 315, & ! 180 * 7/4 + 330 & ! 180 * 11/6 + /) + + real(real_kind), dimension(nangle), parameter :: radians = (/ & +#ifdef __GFC_REAL_10__ + 0.000000000000000000_10, & ! pi * 0 + 0.523598775598298873_10, & ! pi * 1/6 + 0.785398163397448310_10, & ! pi * 1/4 + 1.047197551196597750_10, & ! pi * 1/3 + 1.570796326794896620_10, & ! pi * 1/2 + 2.094395102393195490_10, & ! pi * 2/3 + 2.356194490192344930_10, & ! pi * 3/4 + 2.617993877991494370_10, & ! pi * 5/6 + 3.141592653589793240_10, & ! pi + 3.665191429188092110_10, & ! pi * 7/6 + 3.926990816987241550_10, & ! pi * 5/4 + 4.188790204786390980_10, & ! pi * 4/3 + 4.712388980384689860_10, & ! pi * 3/2 + 5.235987755982988730_10, & ! pi * 5/3 + 5.497787143782138170_10, & ! pi * 7/4 + 5.759586531581287600_10 & ! pi * 11/6 + +#elif defined(__GFC_REAL_16__) + 0.000000000000000000000000000000000_16, & ! pi * 0 + 0.523598775598298873077107230546584_16, & ! pi * 1/6 + 0.785398163397448309615660845819876_16, & ! pi * 1/4 + 1.047197551196597746154214461093170_16, & ! pi * 1/3 + 1.570796326794896619231321691639750_16, & ! pi * 1/2 + 2.094395102393195492308428922186330_16, & ! pi * 2/3 + 2.356194490192344928846982537459630_16, & ! pi * 3/4 + 2.617993877991494365385536152732920_16, & ! pi * 5/6 + 3.141592653589793238462643383279500_16, & ! pi + 3.665191429188092111539750613826090_16, & ! pi * 7/6 + 3.926990816987241548078304229099380_16, & ! pi * 5/4 + 4.188790204786390984616857844372670_16, & ! pi * 4/3 + 4.712388980384689857693965074919250_16, & ! pi * 3/2 + 5.235987755982988730771072305465840_16, & ! pi * 5/3 + 5.497787143782138167309625920739130_16, & ! pi * 7/4 + 5.759586531581287603848179536012420_16 & ! pi * 11/6 + +#else + 0.000000000000000_8, & ! pi * 0 + 0.523598775598299_8, & ! pi * 1/6 + 0.785398163397448_8, & ! pi * 1/4 + 1.047197551196600_8, & ! pi * 1/3 + 1.570796326794900_8, & ! pi * 1/2 + 2.094395102393200_8, & ! pi * 2/3 + 2.356194490192340_8, & ! pi * 3/4 + 2.617993877991490_8, & ! pi * 5/6 + 3.141592653589790_8, & ! pi + 3.665191429188090_8, & ! pi * 7/6 + 3.926990816987240_8, & ! pi * 5/4 + 4.188790204786390_8, & ! pi * 4/3 + 4.712388980384690_8, & ! pi * 3/2 + 5.235987755982990_8, & ! pi * 5/3 + 5.497787143782140_8, & ! pi * 7/4 + 5.759586531581290_8 & ! pi * 11/6 +#endif + /) + + ! sind, cosd, tand, cotand + + ! Ensure precision degrades minimally for large values. + integer, parameter :: nphase = 5 + + integer, dimension(nphase), parameter :: phases = (/ & + 0, 1, 5, 100, 10000 & + /) + +contains + + subroutine compare(strl, xl_in, xl_out, strr, xr_in, xr_out, eps) + use ieee_arithmetic + implicit none + character(*), intent(in) :: strl, strr + real(real_kind), intent(in) :: xl_in, xl_out, xr_in, xr_out, eps + + if ((ieee_is_nan(xl_out) .neqv. ieee_is_nan(xr_out)) & + .or. (ieee_is_finite(xl_out) .neqv. ieee_is_finite(xr_out)) & + .or. (abs(xl_out - xr_out) .gt. eps)) then + write (*, 100) strl, "(", xl_in, "): ", xl_out + write (*, 100) strr, "(", xr_in, "): ", xr_out + + if ((ieee_is_nan(xl_out) .eqv. ieee_is_nan(xr_out)) & + .and. ieee_is_finite(xl_out) .and. ieee_is_finite(xr_out)) then + write (*, 300) "|xl - xr| = ", abs(xl_out - xr_out) + write (*, 300) " > eps = ", eps + endif + + call abort() + endif + +#ifdef __GFC_REAL_16__ + 100 format((A8,A,F34.30,A,F34.30,F34.30)) + 200 format((A12,F34.30)) + !500 format((A8,A,G34.29,A,G34.29,G34.29)) +#elif defined(__GFC_REAL_10__) + 100 format((A8,A,F21.17,A,F21.17,F21.17)) + 200 format((A12,F21.17)) + !500 format((A8,A,G21.16,A,G21.16,G21.16)) +#else + 100 format((A8,A,F18.14,A,F18.14,F18.14)) + 200 format((A12,F18.14)) + !500 format((A8,A,G18.13,A,G18.13,G18.13)) +#endif + 300 format((A12,G8.2)) + endsubroutine + +endmodule + +use dec_math_5 +use ieee_arithmetic +implicit none + +integer :: phase_index, angle_index, phase +real(real_kind) :: deg_in, deg_out, deg_out2, rad_in, rad_out + +! Try every value in degrees, and make sure they are correct compared to the +! corresponding radian function. + +do phase_index = 1, size(phases) + phase = phases(phase_index) + + do angle_index = 1, size(degrees) + ! eqv to degrees(angle_index) modulo 360 + deg_in = degrees(angle_index) + phase * 360 + rad_in = radians(angle_index) + phase * tau + + ! sind vs. sin + deg_out = sind(deg_in) + rad_out = sin(rad_in) + call compare("sind", deg_in, deg_out, "sin", rad_in, rad_out, eps) + + ! cosd vs. cos + deg_out = cosd(deg_in) + rad_out = cos(rad_in) + call compare("cosd", deg_in, deg_out, "cos", rad_in, rad_out, eps) + + ! tand vs. tan + deg_out = tand(deg_in) + rad_out = tan(rad_in) + if ( ieee_is_finite(deg_out) ) then + call compare("tand", deg_in, deg_out, "tan", rad_in, rad_out, eps) + endif + + ! cotand vs. cotan + deg_out = cotand(deg_in) + rad_out = cotan(rad_in) + + ! Skip comparing infinity, because cotan does not return infinity + if ( ieee_is_finite(deg_out) ) then + call compare("cotand", deg_in, deg_out, "cotan", rad_in, rad_out, eps) + + ! cotand vs. tand + deg_out = cotand(deg_in) + deg_out2 = -tand(deg_in + 90) + + call compare("cotand", deg_in, deg_out, "-tand+90", deg_in, deg_out2, eps) + deg_out2 = 1 / tand(deg_in) + call compare("cotand", deg_in, deg_out, "1/tand", deg_in, deg_out2, eps) + endif + + enddo + + +enddo + + +end -- cgit v1.1 From 8bf5faa9c463f0d53ffe835ba03d4502edfb959d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Apr 2020 18:24:12 +0200 Subject: i386: Don't use AVX512F integral masks for V*TImode [PR94438] The ix86_get_mask_mode hook uses int mask for 512-bit vectors or 128/256-bit vectors with AVX512VL (that is correct), and only for V*[SD][IF]mode if not AVX512BW (also correct), but with AVX512BW it would stop checking the elem_size altogether and pretend the hw has masking support for V*TImode etc., which it doesn't. That can lead to various ICEs later on. 2020-04-08 Jakub Jelinek PR target/94438 * config/i386/i386.c (ix86_get_mask_mode): Only use int mask for elem_size 1, 2, 4 and 8. * gcc.target/i386/avx512bw-pr94438.c: New test. * gcc.target/i386/avx512vlbw-pr94438.c: New test. --- gcc/ChangeLog | 6 ++++++ gcc/config/i386/i386.c | 4 +++- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.target/i386/avx512bw-pr94438.c | 13 +++++++++++++ gcc/testsuite/gcc.target/i386/avx512vlbw-pr94438.c | 13 +++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/avx512bw-pr94438.c create mode 100644 gcc/testsuite/gcc.target/i386/avx512vlbw-pr94438.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 88e7952..ec97a1e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Jakub Jelinek + + PR target/94438 + * config/i386/i386.c (ix86_get_mask_mode): Only use int mask for elem_size + 1, 2, 4 and 8. + 2020-04-08 Martin Liska PR c++/94314 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 049ca4f..ca3b7dc 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -21771,7 +21771,9 @@ ix86_get_mask_mode (machine_mode data_mode) if ((TARGET_AVX512F && vector_size == 64) || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16))) { - if (elem_size == 4 || elem_size == 8 || TARGET_AVX512BW) + if (elem_size == 4 + || elem_size == 8 + || (TARGET_AVX512BW && (elem_size == 1 || elem_size == 2))) return smallest_int_mode_for_size (nunits); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3471816..e3600e0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Jakub Jelinek + + PR target/94438 + * gcc.target/i386/avx512bw-pr94438.c: New test. + * gcc.target/i386/avx512vlbw-pr94438.c: New test. + 2020-04-08 Tobias Burnus PR fortran/93871 diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr94438.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr94438.c new file mode 100644 index 0000000..9e56f28 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr94438.c @@ -0,0 +1,13 @@ +/* PR target/94438 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-mavx512bw" } */ + +typedef __attribute__ ((__vector_size__ (4 * sizeof (__int128)))) __int128 V; +void bar (V); + +void +foo (V w) +{ + V v = 0 <= (0 >= w); + bar (v); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512vlbw-pr94438.c b/gcc/testsuite/gcc.target/i386/avx512vlbw-pr94438.c new file mode 100644 index 0000000..a0c52e4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512vlbw-pr94438.c @@ -0,0 +1,13 @@ +/* PR target/94438 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-mavx512bw -mavx512vl" } */ + +typedef __attribute__ ((__vector_size__ (sizeof (__int128)))) __int128 V; +void bar (V); + +void +foo (V w) +{ + V v = 0 <= (0 >= w); + bar (v); +} -- cgit v1.1 From c5f379653964a1d2c7037b2de3e947a48370a198 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 8 Apr 2020 09:47:35 -0700 Subject: x86: Insert ENDBR if function will be called indirectly Since constant_call_address_operand has ;; Test for a pc-relative call operand (define_predicate "constant_call_address_operand" (match_code "symbol_ref") { if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC || flag_force_indirect_call) return false; if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op)) return false; return true; }) even if cgraph_node::get (cfun->decl)->only_called_directly_p () returns false, the fuction may still be called indirectly. Copy the logic from constant_call_address_operand to rest_of_insert_endbranch to insert ENDBR at function entry if function will be called indirectly. gcc/ PR target/94417 * config/i386/i386-features.c (rest_of_insert_endbranch): Insert ENDBR at function entry if function will be called indirectly. gcc/testsuite/ PR target/94417 * gcc.target/i386/pr94417-1.c: New test. * gcc.target/i386/pr94417-2.c: Likewise. * gcc.target/i386/pr94417-3.c: Likewise. --- gcc/ChangeLog | 6 ++++++ gcc/config/i386/i386-features.c | 7 ++++++- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/gcc.target/i386/pr94417-1.c | 20 ++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr94417-2.c | 21 +++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr94417-3.c | 19 +++++++++++++++++++ 6 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr94417-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr94417-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr94417-3.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec97a1e..ffa8930 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 H.J. Lu + + PR target/94417 + * config/i386/i386-features.c (rest_of_insert_endbranch): Insert + ENDBR at function entry if function will be called indirectly. + 2020-04-08 Jakub Jelinek PR target/94438 diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c index 66b120d..78fb373 100644 --- a/gcc/config/i386/i386-features.c +++ b/gcc/config/i386/i386-features.c @@ -1963,7 +1963,12 @@ rest_of_insert_endbranch (void) && (!flag_manual_endbr || lookup_attribute ("cf_check", DECL_ATTRIBUTES (cfun->decl))) - && !cgraph_node::get (cfun->decl)->only_called_directly_p ()) + && (!cgraph_node::get (cfun->decl)->only_called_directly_p () + || ix86_cmodel == CM_LARGE + || ix86_cmodel == CM_LARGE_PIC + || flag_force_indirect_call + || (TARGET_DLLIMPORT_DECL_ATTRIBUTES + && DECL_DLLIMPORT_P (cfun->decl)))) { /* Queue ENDBR insertion to x86_function_profiler. */ if (crtl->profile && flag_fentry) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e3600e0..e8305cb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-04-08 H.J. Lu + + PR target/94417 + * gcc.target/i386/pr94417-1.c: New test. + * gcc.target/i386/pr94417-2.c: Likewise. + * gcc.target/i386/pr94417-3.c: Likewise. + 2020-04-08 Jakub Jelinek PR target/94438 diff --git a/gcc/testsuite/gcc.target/i386/pr94417-1.c b/gcc/testsuite/gcc.target/i386/pr94417-1.c new file mode 100644 index 0000000..5bbe057 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94417-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O2 -fcf-protection -mcmodel=large" } */ +/* { dg-final { scan-assembler-times {\mendbr} 2 } } */ + +extern void ext (void); + +__attribute((noclone, noinline)) +static +void +foo (void) +{ + ext (); +} + +void +bar (void) +{ + foo (); +} diff --git a/gcc/testsuite/gcc.target/i386/pr94417-2.c b/gcc/testsuite/gcc.target/i386/pr94417-2.c new file mode 100644 index 0000000..9eb0f5b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94417-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O2 -fpic -mcmodel=large -fcf-protection" } */ +/* { dg-final { scan-assembler-times {\mendbr} 2 } } */ + +extern void ext (void); + +__attribute((noclone, noinline)) +static +void +foo (void) +{ + ext (); +} + +void +bar (void) +{ + foo (); +} diff --git a/gcc/testsuite/gcc.target/i386/pr94417-3.c b/gcc/testsuite/gcc.target/i386/pr94417-3.c new file mode 100644 index 0000000..07c4517 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94417-3.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fcf-protection -mforce-indirect-call" } */ +/* { dg-final { scan-assembler-times {\mendbr} 2 } } */ + +extern void ext (void); + +__attribute((noclone, noinline)) +static +void +foo (void) +{ + ext (); +} + +void +bar (void) +{ + foo (); +} -- cgit v1.1 From 7dbfcb91a87f78446c5e10582d4ea9ea168f3f98 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 8 Apr 2020 14:24:29 -0300 Subject: add missing fp16 options dg-require-effective-target arm_fp16_alternative_ok may pass even when arm_fp16_ok doesn't, and the latter's failure inhibits dg-add-options arm_fp16_alternative. Requiring arm_fp16_ok would disable the test, but if we just pass it the -mfp16-format=alternative option, it passes even without arm_fp16_ok. Sibling test fp16-aapcs-4.c underwent a similar change, so I'm proposing the explicit option to fp16-aapcs-3.c as well. for gcc/testsuite/ChangeLog * gcc.target/arm/fp16-aapcs-3.c: Explicitly use the -mfp16-format=alternative option. --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/arm/fp16-aapcs-3.c | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e8305cb..db4f639 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-08 Alexandre Oliva + + * gcc.target/arm/fp16-aapcs-3.c: Explicitly use the + -mfp16-format=alternative option. + 2020-04-08 H.J. Lu PR target/94417 diff --git a/gcc/testsuite/gcc.target/arm/fp16-aapcs-3.c b/gcc/testsuite/gcc.target/arm/fp16-aapcs-3.c index 56a3ae2..858181c 100644 --- a/gcc/testsuite/gcc.target/arm/fp16-aapcs-3.c +++ b/gcc/testsuite/gcc.target/arm/fp16-aapcs-3.c @@ -1,8 +1,7 @@ /* { dg-do compile } */ /* { dg-require-effective-target arm_hard_vfp_ok } */ /* { dg-require-effective-target arm_fp16_alternative_ok } */ -/* { dg-options "-O2" } */ -/* { dg-add-options arm_fp16_alternative } */ +/* { dg-options "-O2 -mfp16-format=alternative" } */ /* Test __fp16 arguments and return value in registers (hard-float). */ -- cgit v1.1 From dd9ca9d770a18ce4b16d867f49fef3293b483ff5 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 8 Apr 2020 14:04:35 +0200 Subject: rtl-optimization/93946 - fix TBAA for redundant store removal in CSE It turns out RTL CSE tries to remove redundant stores but fails to do the usual validity check what such a change is TBAA neutral to later loads. This now triggers with the PR93946 testcases on nios2. 2020-04-08 Richard Biener PR rtl-optimization/93946 * cse.c (cse_insn): Record the tabled expression in src_related. Verify a redundant store removal is valid. --- gcc/ChangeLog | 6 ++++++ gcc/cse.c | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ffa8930..025a4a6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Richard Biener + + PR rtl-optimization/93946 + * cse.c (cse_insn): Record the tabled expression in + src_related. Verify a redundant store removal is valid. + 2020-04-08 H.J. Lu PR target/94417 diff --git a/gcc/cse.c b/gcc/cse.c index 3e8724b..f07bbdb 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -5074,7 +5074,7 @@ cse_insn (rtx_insn *insn) to prefer it. Copy it to src_related. The code below will then give it a negative cost. */ if (GET_CODE (dest) == code && rtx_equal_p (p->exp, dest)) - src_related = dest; + src_related = p->exp; } /* Find the cheapest valid equivalent, trying all the available @@ -5332,7 +5332,16 @@ cse_insn (rtx_insn *insn) && rtx_equal_p (trial, dest) && !side_effects_p (dest) && (cfun->can_delete_dead_exceptions - || insn_nothrow_p (insn))) + || insn_nothrow_p (insn)) + /* We can only remove the later store if the earlier aliases + at least all accesses the later one. */ + && (!MEM_P (trial) + || ((MEM_ALIAS_SET (dest) == MEM_ALIAS_SET (trial) + || alias_set_subset_of (MEM_ALIAS_SET (dest), + MEM_ALIAS_SET (trial))) + && (!MEM_EXPR (trial) + || refs_same_for_tbaa_p (MEM_EXPR (trial), + MEM_EXPR (dest)))))) { SET_SRC (sets[i].rtl) = trial; noop_insn = true; -- cgit v1.1 From 77d6dfc929832a542a25fc455b90f1a4bc83229c Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Mon, 6 Apr 2020 19:59:04 -0400 Subject: c++: Fix ICE-on-invalid with lambda template [PR94507] While reducing something else I noticed that we ICE on the following invalid code. In tsubst_lambda_expr, tsubst_template_decl has already reported an error and returned the error_mark_node, so make sure we don't ICE on that. I'm using a goto here because we still have to do finish_struct because it does popclass (). PR c++/94507 - ICE-on-invalid with lambda template. * pt.c (tsubst_lambda_expr): Cope when tsubst_template_decl or tsubst_function_decl returns error_mark_node. * g++.dg/cpp2a/lambda-generic7.C: New test. --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/pt.c | 11 +++++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/cpp2a/lambda-generic7.C | 10 ++++++++++ 4 files changed, 32 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-generic7.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7c5edc2..50f1857 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Marek Polacek + + PR c++/94507 - ICE-on-invalid with lambda template. + * pt.c (tsubst_lambda_expr): Cope when tsubst_template_decl or + tsubst_function_decl returns error_mark_node. + 2020-04-08 Martin Liska PR c++/94314 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 256a937..050a57b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18953,6 +18953,11 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (oldtmpl) { tmpl = tsubst_template_decl (oldtmpl, args, complain, fntype); + if (tmpl == error_mark_node) + { + r = error_mark_node; + goto out; + } fn = DECL_TEMPLATE_RESULT (tmpl); finish_member_declaration (tmpl); } @@ -18960,6 +18965,11 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) { tmpl = NULL_TREE; fn = tsubst_function_decl (oldfn, args, complain, fntype); + if (fn == error_mark_node) + { + r = error_mark_node; + goto out; + } finish_member_declaration (fn); } @@ -19025,6 +19035,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) maybe_add_lambda_conv_op (type); } +out: finish_struct (type, /*attr*/NULL_TREE); insert_pending_capture_proxies (); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index db4f639..6ed5114 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-08 Marek Polacek + + PR c++/94507 - ICE-on-invalid with lambda template. + * g++.dg/cpp2a/lambda-generic7.C: New test. + 2020-04-08 Alexandre Oliva * gcc.target/arm/fp16-aapcs-3.c: Explicitly use the diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-generic7.C b/gcc/testsuite/g++.dg/cpp2a/lambda-generic7.C new file mode 100644 index 0000000..bedba68 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-generic7.C @@ -0,0 +1,10 @@ +// PR c++/94507 - ICE-on-invalid with lambda template. +// { dg-do compile { target c++2a } } + +struct S { }; + +template +auto foo(T, U) +{ + [] <> () { foo (S{}, S{}); }; // { dg-error "expected" } +} -- cgit v1.1 From 08d1e7a5aabcf7eeac48bfd99deb80451b8f9974 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Apr 2020 19:54:35 +0200 Subject: openacc: Fix up declare-pr94120.C testcase [PR94533] This test has been put in a wrong directory, where OpenACC tests aren't tested with -fopenacc, and also contained trailing semicolons. I've moved it where it belongs, added dg-error directives and removed the extra semicolons. 2020-04-08 Jakub Jelinek PR middle-end/94120 PR testsuite/94533 * g++.dg/declare-pr94120.C: Move test to ... * g++.dg/goacc/declare-pr94120.C: ... here. Add dg-error directives. --- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/g++.dg/declare-pr94120.C | 30 ---------------------------- gcc/testsuite/g++.dg/goacc/declare-pr94120.C | 30 ++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 30 deletions(-) delete mode 100644 gcc/testsuite/g++.dg/declare-pr94120.C create mode 100644 gcc/testsuite/g++.dg/goacc/declare-pr94120.C (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6ed5114..dcf552f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-04-08 Jakub Jelinek + + PR middle-end/94120 + PR testsuite/94533 + * g++.dg/declare-pr94120.C: Move test to ... + * g++.dg/goacc/declare-pr94120.C: ... here. Add dg-error directives. + 2020-04-08 Marek Polacek PR c++/94507 - ICE-on-invalid with lambda template. diff --git a/gcc/testsuite/g++.dg/declare-pr94120.C b/gcc/testsuite/g++.dg/declare-pr94120.C deleted file mode 100644 index 8515c4f..0000000 --- a/gcc/testsuite/g++.dg/declare-pr94120.C +++ /dev/null @@ -1,30 +0,0 @@ -/* { dg-do compile } */ - -/* PR middle-end/94120 */ - -int b[8]; -#pragma acc declare create (b) - -namespace my { - int d[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - #pragma acc declare copyin (d) -}; - -namespace outer { - namespace inner { - int e[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - #pragma acc declare copyin (e) - }; -}; - -int f[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; -namespace my { - #pragma acc declare copyin (f) -}; - -namespace outer { - int g[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - namespace inner { - #pragma acc declare copyin (g) - }; -}; diff --git a/gcc/testsuite/g++.dg/goacc/declare-pr94120.C b/gcc/testsuite/g++.dg/goacc/declare-pr94120.C new file mode 100644 index 0000000..7aa5612 --- /dev/null +++ b/gcc/testsuite/g++.dg/goacc/declare-pr94120.C @@ -0,0 +1,30 @@ +/* { dg-do compile } */ + +/* PR middle-end/94120 */ + +int b[8]; +#pragma acc declare create (b) + +namespace my { + int d[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + #pragma acc declare copyin (d) +} + +namespace outer { + namespace inner { + int e[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + #pragma acc declare copyin (e) + } +} + +int f[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; +namespace my { + #pragma acc declare copyin (f) /* { dg-error "'f' must be a variable declared in the same scope as '#pragma acc declare'" } */ +} + +namespace outer { + int g[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + namespace inner { + #pragma acc declare copyin (g) /* { dg-error "'outer::g' must be a variable declared in the same scope as '#pragma acc declare'" } */ + } +} -- cgit v1.1 From 6c9a711575d8fdf9e75f01d7a0e84d558600df40 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Apr 2020 20:04:01 +0200 Subject: testsuite: Fix up pr94314*.C tests [PR94314] The test FAIL everywhere where size_t is not unsigned long. Fixed by using __SIZE_TYPE__ instead. 2020-04-08 Jakub Jelinek PR c++/94314 * g++.dg/pr94314.C (A::operator new, B::operator new, C::operator new): Use __SIZE_TYPE__ instead of unsigned long. * g++.dg/pr94314-3.C (base::operator new, B::operator new): Likewise. --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/pr94314-3.C | 4 ++-- gcc/testsuite/g++.dg/pr94314.C | 6 +++--- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dcf552f..8916b89 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2020-04-08 Jakub Jelinek + PR c++/94314 + * g++.dg/pr94314.C (A::operator new, B::operator new, C::operator new): + Use __SIZE_TYPE__ instead of unsigned long. + * g++.dg/pr94314-3.C (base::operator new, B::operator new): Likewise. + PR middle-end/94120 PR testsuite/94533 * g++.dg/declare-pr94120.C: Move test to ... diff --git a/gcc/testsuite/g++.dg/pr94314-3.C b/gcc/testsuite/g++.dg/pr94314-3.C index a5b1013..575ba9d 100644 --- a/gcc/testsuite/g++.dg/pr94314-3.C +++ b/gcc/testsuite/g++.dg/pr94314-3.C @@ -10,7 +10,7 @@ volatile int idx; struct base { __attribute__ ((malloc, noinline)) static void * - operator new (unsigned long sz) + operator new (__SIZE_TYPE__ sz) { return ::operator new (sz); } @@ -28,7 +28,7 @@ volatile int base::count[2] = {0, 0}; struct B : base { - static void *operator new (unsigned long sz) + static void *operator new (__SIZE_TYPE__ sz) { int c = count[idx]; count[idx] = c + 1; diff --git a/gcc/testsuite/g++.dg/pr94314.C b/gcc/testsuite/g++.dg/pr94314.C index a06800d2..86e651d 100644 --- a/gcc/testsuite/g++.dg/pr94314.C +++ b/gcc/testsuite/g++.dg/pr94314.C @@ -8,7 +8,7 @@ struct A { __attribute__((malloc,noinline)) - static void* operator new(unsigned long sz) + static void* operator new(__SIZE_TYPE__ sz) { ++count; return ::operator new(sz); @@ -28,7 +28,7 @@ int A::count = 0; struct B { __attribute__((malloc,noinline)) - static void* operator new(unsigned long sz) + static void* operator new(__SIZE_TYPE__ sz) { ++count; return ::operator new(sz); @@ -48,7 +48,7 @@ int B::count = 0; struct C { - static void* operator new(unsigned long sz) + static void* operator new(__SIZE_TYPE__ sz) { ++count; return ::operator new(sz); -- cgit v1.1 From f52eb4f988992d393c69ee4ab76f236dced80e36 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Apr 2020 21:22:05 +0200 Subject: vect: Fix up lowering of TRUNC_MOD_EXPR by negative constant [PR94524] The first testcase below is miscompiled, because for the division part of the lowering we canonicalize negative divisors to their absolute value (similarly how expmed.c canonicalizes it), but when multiplying the division result back by the VECTOR_CST, we use the original constant, which can contain negative divisors. Fixed by computing ABS_EXPR of the VECTOR_CST. Unfortunately, fold-const.c doesn't support const_unop (ABS_EXPR, VECTOR_CST) and I think it is too late in GCC 10 cycle to add it now. Furthermore, while modulo by most negative constant happens to return the right value, it does that only by invoking UB in the IL, because we then expand division by that 1U+INT_MAX and say for INT_MIN % INT_MIN compute the division as -1, and then multiply by INT_MIN, which is signed integer overflow. We in theory could do the computation in unsigned vector types instead, but is it worth bothering. People that are doing % INT_MIN are either testing for standard conformance, or doing something wrong. So, I've also added punting on % INT_MIN, both in vect lowering and vect pattern recognition (we punt already for / INT_MIN). 2020-04-08 Jakub Jelinek PR tree-optimization/94524 * tree-vect-generic.c (expand_vector_divmod): If any elt of op1 is negative for signed TRUNC_MOD_EXPR, multiply with absolute value of op1 rather than op1 itself at the end. Punt for signed modulo by most negative constant. * tree-vect-patterns.c (vect_recog_divmod_pattern): Punt for signed modulo by most negative constant. * gcc.c-torture/execute/pr94524-1.c: New test. * gcc.c-torture/execute/pr94524-2.c: New test. --- gcc/ChangeLog | 10 ++++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.c-torture/execute/pr94524-1.c | 19 +++++++++++++++++++ gcc/testsuite/gcc.c-torture/execute/pr94524-2.c | 25 +++++++++++++++++++++++++ gcc/tree-vect-generic.c | 25 +++++++++++++++++++++++-- gcc/tree-vect-patterns.c | 4 ++-- 6 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr94524-1.c create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr94524-2.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 025a4a6..dcdfae1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2020-04-08 Jakub Jelinek + + PR tree-optimization/94524 + * tree-vect-generic.c (expand_vector_divmod): If any elt of op1 is + negative for signed TRUNC_MOD_EXPR, multiply with absolute value of + op1 rather than op1 itself at the end. Punt for signed modulo by + most negative constant. + * tree-vect-patterns.c (vect_recog_divmod_pattern): Punt for signed + modulo by most negative constant. + 2020-04-08 Richard Biener PR rtl-optimization/93946 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8916b89..134280d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2020-04-08 Jakub Jelinek + PR tree-optimization/94524 + * gcc.c-torture/execute/pr94524-1.c: New test. + * gcc.c-torture/execute/pr94524-2.c: New test. + PR c++/94314 * g++.dg/pr94314.C (A::operator new, B::operator new, C::operator new): Use __SIZE_TYPE__ instead of unsigned long. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr94524-1.c b/gcc/testsuite/gcc.c-torture/execute/pr94524-1.c new file mode 100644 index 0000000..e7365ad --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr94524-1.c @@ -0,0 +1,19 @@ +/* PR tree-optimization/94524 */ + +typedef signed char __attribute__ ((__vector_size__ (16))) V; + +static __attribute__ ((__noinline__, __noclone__)) V +foo (V c) +{ + c %= (signed char) -19; + return (V) c; +} + +int +main () +{ + V x = foo ((V) { 31 }); + if (x[0] != 12) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr94524-2.c b/gcc/testsuite/gcc.c-torture/execute/pr94524-2.c new file mode 100644 index 0000000..9c74b7b --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr94524-2.c @@ -0,0 +1,25 @@ +/* PR tree-optimization/94524 */ + +typedef signed char __attribute__ ((__vector_size__ (16))) V; + +static __attribute__ ((__noinline__, __noclone__)) V +foo (V c) +{ + c %= (signed char) -128; + return (V) c; +} + +int +main () +{ + V x = foo ((V) { -128 }); + if (x[0] != 0) + __builtin_abort (); + x = foo ((V) { -127 }); + if (x[0] != -127) + __builtin_abort (); + x = foo ((V) { 127 }); + if (x[0] != 127) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 2f6fd5e..8b00f32 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -478,6 +478,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0, { bool use_pow2 = true; bool has_vector_shift = true; + bool use_abs_op1 = false; int mode = -1, this_mode; int pre_shift = -1, post_shift; unsigned int nunits = nunits_for_known_piecewise_op (type); @@ -618,8 +619,11 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0, /* n rem d = n rem -d */ if (code == TRUNC_MOD_EXPR && d < 0) - d = abs_d; - else if (abs_d == HOST_WIDE_INT_1U << (prec - 1)) + { + d = abs_d; + use_abs_op1 = true; + } + if (abs_d == HOST_WIDE_INT_1U << (prec - 1)) { /* This case is not handled correctly below. */ mode = -2; @@ -899,6 +903,23 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0, if (op == unknown_optab || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) return NULL_TREE; + if (use_abs_op1) + { + tree_vector_builder elts; + if (!elts.new_unary_operation (type, op1, false)) + return NULL_TREE; + unsigned int count = elts.encoded_nelts (); + for (unsigned int i = 0; i < count; ++i) + { + tree elem1 = VECTOR_CST_ELT (op1, i); + + tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1); + if (elt == NULL_TREE) + return NULL_TREE; + elts.quick_push (elt); + } + op1 = elts.build (); + } tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1); op = optab_for_tree_code (MINUS_EXPR, type, optab_default); if (op == unknown_optab diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 60dc1bf..dd0c19d 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -3365,8 +3365,8 @@ vect_recog_divmod_pattern (stmt_vec_info stmt_vinfo, tree *type_out) d = abs_d; oprnd1 = build_int_cst (itype, abs_d); } - else if (HOST_BITS_PER_WIDE_INT >= prec - && abs_d == HOST_WIDE_INT_1U << (prec - 1)) + if (HOST_BITS_PER_WIDE_INT >= prec + && abs_d == HOST_WIDE_INT_1U << (prec - 1)) /* This case is not handled correctly below. */ return NULL; -- cgit v1.1 From d0cc1b79b39994c917abb23f71064bb39eedcc70 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Apr 2020 21:23:58 +0200 Subject: cselib, reload: Fix cselib ICE on m68k/microblaze [PR94526] The following testcase ICEs on m68k (and another one Jeff mailed me privately on microblaze). The problem is that reload creates two DEBUG_INSNs with the same value of (plus:P (reg:P sp) (const_int 0)), we compute correctly the same hash value for them, but then don't find them in the cselib hash table, as rtx_equal_for_cselib_1 thinks it is different from (reg:P sp), and trigger an assertion failure that requires that from two different debug insns one doesn't add locations to VALUEs. The patch has two fixes for this, each fixes the ICE on both targets separately, but I think we want both. The cselib.c change ensures that rtx_equal_for_cselib_1 considers (value:P sp_derived_value) and (plus:P (reg:P sp) (const_int 0)) equivalent. The reload1.c change makes sure we don't create those bogus plus 0 expressions. I understand the reasons for creating them, but they don't really apply to DEBUG_INSNs; we don't have validity matching there, all we care is that the expressions aren't arbitrarily deep, but it is just fine to fold x + 0 into just x in there. 2020-04-08 Jakub Jelinek PR middle-end/94526 * cselib.c (autoinc_split): Handle e->val_rtx being SP_DERIVED_VALUE_P with zero offset. * reload1.c (eliminate_regs_1): Avoid creating (plus (reg) (const_int 0)) in DEBUG_INSNs. * gcc.dg/pr94526.c: New test. --- gcc/ChangeLog | 6 ++++++ gcc/cselib.c | 34 +++++++++++++++++++++------------- gcc/reload1.c | 5 +++-- gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/gcc.dg/pr94526.c | 21 +++++++++++++++++++++ 5 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr94526.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dcdfae1..20fe7e2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2020-04-08 Jakub Jelinek + PR middle-end/94526 + * cselib.c (autoinc_split): Handle e->val_rtx being SP_DERIVED_VALUE_P + with zero offset. + * reload1.c (eliminate_regs_1): Avoid creating + (plus (reg) (const_int 0)) in DEBUG_INSNs. + PR tree-optimization/94524 * tree-vect-generic.c (expand_vector_divmod): If any elt of op1 is negative for signed TRUNC_MOD_EXPR, multiply with absolute value of diff --git a/gcc/cselib.c b/gcc/cselib.c index 69c9ca5..0de6836 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -884,21 +884,29 @@ autoinc_split (rtx x, rtx *off, machine_mode memmode) else e = cselib_lookup (x, GET_MODE (x), 0, memmode); if (e) - for (struct elt_loc_list *l = e->locs; l; l = l->next) - if (GET_CODE (l->loc) == PLUS - && GET_CODE (XEXP (l->loc, 0)) == VALUE - && SP_DERIVED_VALUE_P (XEXP (l->loc, 0)) - && CONST_INT_P (XEXP (l->loc, 1))) + { + if (SP_DERIVED_VALUE_P (e->val_rtx) + && (*off == NULL_RTX || *off == const0_rtx)) { - if (*off == NULL_RTX) - *off = XEXP (l->loc, 1); - else - *off = plus_constant (Pmode, *off, - INTVAL (XEXP (l->loc, 1))); - if (*off == const0_rtx) - *off = NULL_RTX; - return XEXP (l->loc, 0); + *off = NULL_RTX; + return e->val_rtx; } + for (struct elt_loc_list *l = e->locs; l; l = l->next) + if (GET_CODE (l->loc) == PLUS + && GET_CODE (XEXP (l->loc, 0)) == VALUE + && SP_DERIVED_VALUE_P (XEXP (l->loc, 0)) + && CONST_INT_P (XEXP (l->loc, 1))) + { + if (*off == NULL_RTX) + *off = XEXP (l->loc, 1); + else + *off = plus_constant (Pmode, *off, + INTVAL (XEXP (l->loc, 1))); + if (*off == const0_rtx) + *off = NULL_RTX; + return XEXP (l->loc, 0); + } + } } return x; } diff --git a/gcc/reload1.c b/gcc/reload1.c index 2f02c3e..88f4727 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -2607,8 +2607,9 @@ eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn, structure of the insn in a way that reload can't handle. We special-case the commonest situation in eliminate_regs_in_insn, so just replace a PLUS with a - PLUS here, unless inside a MEM. */ - if (mem_mode != 0 + PLUS here, unless inside a MEM. In DEBUG_INSNs, it is + always ok to replace a PLUS with just a REG. */ + if ((mem_mode != 0 || (insn && DEBUG_INSN_P (insn))) && CONST_INT_P (XEXP (x, 1)) && known_eq (INTVAL (XEXP (x, 1)), -ep->previous_offset)) return ep->to_rtx; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 134280d..6f26fc6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2020-04-08 Jakub Jelinek + PR middle-end/94526 + * gcc.dg/pr94526.c: New test. + PR tree-optimization/94524 * gcc.c-torture/execute/pr94524-1.c: New test. * gcc.c-torture/execute/pr94524-2.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr94526.c b/gcc/testsuite/gcc.dg/pr94526.c new file mode 100644 index 0000000..9864c4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94526.c @@ -0,0 +1,21 @@ +/* PR middle-end/94526 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -g" } */ + +struct S { int val[8 * sizeof (int)]; }; + +void +foo (struct S *x) +{ + struct S *a = x; +} + +void baz (struct S); + +void +bar (void) +{ + struct S b; + foo (&b); + baz (b); +} -- cgit v1.1 From 48242b2c3ac96c0bd5265e77013583ac9ceee97d Mon Sep 17 00:00:00 2001 From: Clement Chigot Date: Wed, 8 Apr 2020 16:58:36 -0400 Subject: rs6000: Link with libc128.a for long-double-128. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AIX applications using 128-bit long double must be linked with libc128.a, in order to have 128-bit compatible routines. AIX 7.2, 7.1, 6.1: Build/Tests: OK 2020-04-03 Clément Chigot * config/rs6000/aix61.h (LIB_SPEC): Add -lc128 with -mlong-double-128. * config/rs6000/aix71.h (LIB_SPEC): Likewise. * config/rs6000/aix72.h (LIB_SPEC): Likewise. --- gcc/ChangeLog | 6 ++++++ gcc/config/rs6000/aix61.h | 1 + gcc/config/rs6000/aix71.h | 1 + gcc/config/rs6000/aix72.h | 1 + 4 files changed, 9 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 20fe7e2..d1819da 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Clement Chigot + + * config/rs6000/aix61.h (LIB_SPEC): Add -lc128 with -mlong-double-128. + * config/rs6000/aix71.h (LIB_SPEC): Likewise. + * config/rs6000/aix72.h (LIB_SPEC): Likewise. + 2020-04-08 Jakub Jelinek PR middle-end/94526 diff --git a/gcc/config/rs6000/aix61.h b/gcc/config/rs6000/aix61.h index 13c3e09..5b652d7 100644 --- a/gcc/config/rs6000/aix61.h +++ b/gcc/config/rs6000/aix61.h @@ -154,6 +154,7 @@ do { \ %{!maix64:%{!shared:%{g*:-lg}}}\ %{fprofile-arcs|fprofile-generate*|coverage:-lpthreads}\ %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\ + %{mlong-double-128:-lc128}\ %{pthread:-lpthreads} -lc" #undef LINK_SPEC diff --git a/gcc/config/rs6000/aix71.h b/gcc/config/rs6000/aix71.h index 3be0cbe..5f98eb0 100644 --- a/gcc/config/rs6000/aix71.h +++ b/gcc/config/rs6000/aix71.h @@ -162,6 +162,7 @@ do { \ %{!maix64:%{!shared:%{g*:-lg}}}\ %{fprofile-arcs|fprofile-generate*|coverage:-lpthreads}\ %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\ + %{mlong-double-128:-lc128}\ %{pthread:-lpthreads} -lc" #undef LINK_SPEC diff --git a/gcc/config/rs6000/aix72.h b/gcc/config/rs6000/aix72.h index 292e67f..6cb1673 100644 --- a/gcc/config/rs6000/aix72.h +++ b/gcc/config/rs6000/aix72.h @@ -163,6 +163,7 @@ do { \ %{!maix64:%{!shared:%{g*:-lg}}}\ %{fprofile-arcs|fprofile-generate*|coverage:-lpthreads}\ %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\ + %{mlong-double-128:-lc128}\ %{pthread:-lpthreads} -lc" #undef LINK_SPEC -- cgit v1.1 From 4049edc23e4165dc18b7f720f6587d6ebbfb59d5 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 9 Apr 2020 00:16:16 +0000 Subject: Daily bump. --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 24b62cf..ef1034d 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20200408 +20200409 -- cgit v1.1 From e7c4084d11b957d925ba586f86db2f346fb3bfe0 Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Wed, 8 Apr 2020 21:52:00 -0500 Subject: [testsuite] Fix PR94079 by respecting vect_hw_misalign [PR94079] This is another vect case which requires special handling with vect_hw_misalign. The alignment of the second part requires misaligned vector access supports. This patch is to adjust the related guard condition and comments. Verified it on ppc64-redhat-linux (Power7 BE). 2020-04-09 Kewen Lin gcc/testsuite/ChangeLog PR testsuite/94023 * gfortran.dg/vect/pr83232.f90: Expect 2 rather than 3 times SLP on non-vect_hw_misalign targets. --- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gfortran.dg/vect/pr83232.f90 | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6f26fc6..b0ebeb4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-09 Kewen Lin + + PR testsuite/94023 + * gfortran.dg/vect/pr83232.f90: Expect 2 rather than 3 times SLP on + non-vect_hw_misalign targets. + 2020-04-08 Jakub Jelinek PR middle-end/94526 diff --git a/gcc/testsuite/gfortran.dg/vect/pr83232.f90 b/gcc/testsuite/gfortran.dg/vect/pr83232.f90 index a353578..af88342 100644 --- a/gcc/testsuite/gfortran.dg/vect/pr83232.f90 +++ b/gcc/testsuite/gfortran.dg/vect/pr83232.f90 @@ -27,5 +27,7 @@ call foo (Einc) END SUBROUTINE -! We should vectorize (1), (2) and (3) -! { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "slp1" } } +! We should vectorize (1), (2) and (3) under vect_hw_misalign. +! { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "slp1" { target vect_hw_misalign } } } +! But only (1) and (3) under !vect_hw_misalign due to the alignment of (2). +! { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "slp1" { target { ! vect_hw_misalign } } } } -- cgit v1.1 From b4e8cd08326b727b6b65604461d9b4f795efbcd9 Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Wed, 8 Apr 2020 21:57:52 -0500 Subject: Whoops, fix wrong PR number in the changelog --- gcc/testsuite/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b0ebeb4..d597508 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,6 @@ 2020-04-09 Kewen Lin - PR testsuite/94023 + PR testsuite/94079 * gfortran.dg/vect/pr83232.f90: Expect 2 rather than 3 times SLP on non-vect_hw_misalign targets. -- cgit v1.1 From fe1837143f1bf1d6b072a3973b00576ee17c30a9 Mon Sep 17 00:00:00 2001 From: Sandra Loosemore Date: Wed, 8 Apr 2020 20:55:20 -0700 Subject: Require pthread effective target for test case using -pthread option. 2020-04-08 Sandra Loosemore gcc/testsuite/ * g++.dg/tree-ssa/pr93940.C: Require pthread target. --- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/g++.dg/tree-ssa/pr93940.C | 1 + 2 files changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d597508..45e7005 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-04-08 Sandra Loosemore + + * g++.dg/tree-ssa/pr93940.C: Require pthread target. + 2020-04-09 Kewen Lin PR testsuite/94079 diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr93940.C b/gcc/testsuite/g++.dg/tree-ssa/pr93940.C index b656aad..111b33e 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr93940.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr93940.C @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target pthread } */ /* { dg-options "-Og --coverage -pthread -fdump-tree-optimized -std=c++17" } */ using uint16_t = unsigned short; -- cgit v1.1 From 926d39c3816772acde857a8510480d9b287ef760 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Wed, 8 Apr 2020 08:15:00 +0100 Subject: coroutines: Add cleanups, where required, to statements with captured references. When we promote captured temporaries to local variables, we also remove their initializers from the relevant call expression. This means that we should recompute the need for a cleanup expression once the set of temporaries that remains becomes known. gcc/cp/ChangeLog: 2020-04-08 Iain Sandoe Jun Ma * coroutines.cc (maybe_promote_captured_temps): Add a cleanup expression, if needed, to any call from which we promoted temporaries captured by reference. --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/coroutines.cc | 20 +++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 50f1857..e63f30b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2020-04-08 Iain Sandoe + Jun Ma + + * coroutines.cc (maybe_promote_captured_temps): Add a cleanup + expression, if needed, to any call from which we promoted + temporaries captured by reference. + 2020-04-08 Marek Polacek PR c++/94507 - ICE-on-invalid with lambda template. diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 983fa65..936be06 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -2798,11 +2798,13 @@ maybe_promote_captured_temps (tree *stmt, void *d) location_t sloc = EXPR_LOCATION (*stmt); tree aw_bind = build3_loc (sloc, BIND_EXPR, void_type_node, NULL, NULL, NULL); - tree aw_statement_current; - if (TREE_CODE (*stmt) == CLEANUP_POINT_EXPR) - aw_statement_current = TREE_OPERAND (*stmt, 0); - else - aw_statement_current = *stmt; + + /* Any cleanup point expression might no longer be necessary, since we + are removing one or more temporaries. */ + tree aw_statement_current = *stmt; + if (TREE_CODE (aw_statement_current) == CLEANUP_POINT_EXPR) + aw_statement_current = TREE_OPERAND (aw_statement_current, 0); + /* Collected the scope vars we need move the temps to regular. */ tree aw_bind_body = push_stmt_list (); tree varlist = NULL_TREE; @@ -2843,8 +2845,12 @@ maybe_promote_captured_temps (tree *stmt, void *d) /* Replace all instances of that temp in the original expr. */ cp_walk_tree (&aw_statement_current, replace_proxy, &pr, NULL); } - /* What's left should be the original statement with any temporaries - broken out. */ + + /* What's left should be the original statement with any co_await + captured temporaries broken out. Other temporaries might remain + so see if we need to wrap the revised statement in a cleanup. */ + aw_statement_current = + maybe_cleanup_point_expr_void (aw_statement_current); add_stmt (aw_statement_current); BIND_EXPR_BODY (aw_bind) = pop_stmt_list (aw_bind_body); awpts->captured_temps.empty (); -- cgit v1.1 From ed80b385418f97ef087f3f2bbe1abecffb5c9775 Mon Sep 17 00:00:00 2001 From: Bin Cheng Date: Thu, 9 Apr 2020 16:42:48 +0800 Subject: Add unsigned type iv_cand for iv_use with non mode-precision type Precisely, for iv_use if it's not integer/pointer type, or non-mode precision type, add candidate for the corresponding scev in unsigned type with the same precision, rather than its original type. gcc/ PR tree-optimization/93674 * tree-ssa-loop-ivopts.c (langhooks.h): New include. (add_iv_candidate_for_use): For iv_use of non integer or pointer type, or non-mode precision type, add candidate in unsigned type with the same precision. gcc/testsuite/ PR tree-optimization/93674 * g++.dg/pr93674.C: New test. --- gcc/ChangeLog | 9 +++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/pr93674.C | 16 ++++++++++++++++ gcc/tree-ssa-loop-ivopts.c | 18 +++++++++++++++++- 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/pr93674.C (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1819da..d45d272 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2020-04-09 Bin Cheng + Richard Biener + + PR tree-optimization/93674 + * tree-ssa-loop-ivopts.c (langhooks.h): New include. + (add_iv_candidate_for_use): For iv_use of non integer or pointer type, + or non-mode precision type, add candidate in unsigned type with the + same precision. + 2020-04-08 Clement Chigot * config/rs6000/aix61.h (LIB_SPEC): Add -lc128 with -mlong-double-128. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 45e7005..960eae4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-09 Bin Cheng + + PR tree-optimization/93674 + * g++.dg/pr93674.C: New test. + 2020-04-08 Sandra Loosemore * g++.dg/tree-ssa/pr93940.C: Require pthread target. diff --git a/gcc/testsuite/g++.dg/pr93674.C b/gcc/testsuite/g++.dg/pr93674.C new file mode 100644 index 0000000..8c59f1b --- /dev/null +++ b/gcc/testsuite/g++.dg/pr93674.C @@ -0,0 +1,16 @@ +// { dg-do compile } +// { dg-options "-O3 -std=c++14 -fstrict-enums -pedantic -fdump-tree-optimized" } +enum some_enum { x = 1000 }; +void sink(some_enum); + +int __attribute__((noinline)) func() { + int sum = 0; + for (int i = 0; i < 3; ++i) { + for (int j = 3; j >= 0; --j) { + sink((some_enum)(i + j)); + } + } + return sum; +} + +// { dg-final { scan-tree-dump-not "some_enum ivtmp" "optimized" } } diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 1ce6d8b..1d2697a 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -132,6 +132,9 @@ along with GCC; see the file COPYING3. If not see #include "tree-vectorizer.h" #include "dbgcnt.h" +/* For lang_hooks.types.type_for_mode. */ +#include "langhooks.h" + /* FIXME: Expressions are expanded to RTL in this pass to determine the cost of different addressing modes. This should be moved to a TBD interface between the GIMPLE and RTL worlds. */ @@ -3479,8 +3482,21 @@ add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use) { poly_uint64 offset; tree base; - tree basetype; struct iv *iv = use->iv; + tree basetype = TREE_TYPE (iv->base); + + /* Don't add candidate for iv_use with non integer, pointer or non-mode + precision types, instead, add candidate for the corresponding scev in + unsigned type with the same precision. See PR93674 for more info. */ + if ((TREE_CODE (basetype) != INTEGER_TYPE && !POINTER_TYPE_P (basetype)) + || !type_has_mode_precision_p (basetype)) + { + basetype = lang_hooks.types.type_for_mode (TYPE_MODE (basetype), + TYPE_UNSIGNED (basetype)); + add_candidate (data, fold_convert (basetype, iv->base), + fold_convert (basetype, iv->step), false, NULL); + return; + } add_candidate (data, iv->base, iv->step, false, use); -- cgit v1.1 From af19e4d0e23e5f61fc15e44a58bfa3b047854b1e Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Wed, 8 Apr 2020 13:38:28 +0100 Subject: PR target/94530 gcc/ChangeLog 2020-04-09 Andrea Corallo PR target/94530 * config/aarch64/falkor-tag-collision-avoidance.c (valid_src_p): Fix missing rtx type check. gcc/testsuite/ChangeLog 2020-04-09 Andrea Corallo * gcc.target/aarch64/pr94530.c: New test. --- gcc/ChangeLog | 6 ++++++ gcc/config/aarch64/falkor-tag-collision-avoidance.c | 3 +++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.target/aarch64/pr94530.c | 9 +++++++++ 4 files changed, 22 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/pr94530.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d45d272..80492ef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-04-09 Andrea Corallo + + PR target/94530 + * config/aarch64/falkor-tag-collision-avoidance.c + (valid_src_p): Fix missing rtx type check. + 2020-04-09 Bin Cheng Richard Biener diff --git a/gcc/config/aarch64/falkor-tag-collision-avoidance.c b/gcc/config/aarch64/falkor-tag-collision-avoidance.c index 719df48..f850153 100644 --- a/gcc/config/aarch64/falkor-tag-collision-avoidance.c +++ b/gcc/config/aarch64/falkor-tag-collision-avoidance.c @@ -538,6 +538,9 @@ valid_src_p (rtx src, rtx_insn *insn, struct loop *loop, bool *pre_post, if (!aarch64_classify_address (&addr, XEXP (x, 0), mode, true)) return false; + if (!REG_P (addr.base)) + return false; + unsigned regno = REGNO (addr.base); if (global_regs[regno] || fixed_regs[regno]) return false; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 960eae4..fde4e0f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-04-09 Andrea Corallo + + * gcc.target/aarch64/pr94530.c: New test. + 2020-04-09 Bin Cheng PR tree-optimization/93674 diff --git a/gcc/testsuite/gcc.target/aarch64/pr94530.c b/gcc/testsuite/gcc.target/aarch64/pr94530.c new file mode 100644 index 0000000..1f98201 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr94530.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mcpu=falkor -mpc-relative-literal-loads -mcmodel=large" } */ + +extern void bar(const char *); + +void foo(void) { + for (;;) + bar(""); +} -- cgit v1.1 From bb40460646ce4e6ad27a2f6795106d004d405314 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 9 Apr 2020 13:54:01 +0200 Subject: testsuite/93369 - use -shared to avoid issue with ODR violation The testcase contains an ODR violation and thus the observed link failure is an accepted outcome (it originally was for an ICE during WPA). Thus the following adds -shared to the link. 2020-04-09 Richard Biener PR testsuite/93369 * g++.dg/lto/pr64076_0.C: Add -shared -fPIC. * g++.dg/lto/pr64076_1.C: Add -fPIC. --- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/lto/pr64076_0.C | 4 ++++ gcc/testsuite/g++.dg/lto/pr64076_1.C | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fde4e0f..ba530077 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-09 Richard Biener + + PR testsuite/93369 + * g++.dg/lto/pr64076_0.C: Add -shared -fPIC. + * g++.dg/lto/pr64076_1.C: Add -fPIC. + 2020-04-09 Andrea Corallo * gcc.target/aarch64/pr94530.c: New test. diff --git a/gcc/testsuite/g++.dg/lto/pr64076_0.C b/gcc/testsuite/g++.dg/lto/pr64076_0.C index fb9b060..57d0fd6 100644 --- a/gcc/testsuite/g++.dg/lto/pr64076_0.C +++ b/gcc/testsuite/g++.dg/lto/pr64076_0.C @@ -1,4 +1,8 @@ // { dg-lto-do link } +// { dg-lto-options { { -O0 -flto -shared -fPIC } } } +// { dg-require-effective-target fpic } +// { dg-require-effective-target shared } +// { dg-extra-ld-options "-shared" } #define XXX #include "pr64076.H" diff --git a/gcc/testsuite/g++.dg/lto/pr64076_1.C b/gcc/testsuite/g++.dg/lto/pr64076_1.C index 4bd0081..c9c58b7 100644 --- a/gcc/testsuite/g++.dg/lto/pr64076_1.C +++ b/gcc/testsuite/g++.dg/lto/pr64076_1.C @@ -1,4 +1,4 @@ -// { dg-options -fno-lto } +// { dg-options "-fno-lto -fPIC" } #include "pr64076.H" -- cgit v1.1 From 7ed2d6cbd094871a0dd23f2d433b962d5f462936 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 17 Mar 2020 15:26:22 +0000 Subject: testsuite: Tweak check-function-bodies interface In g:2171a9207f51bc486ed9c502cb4da706f594615e I'd tried to fix various ILP32 testsuite failures by restricting some tests to LP64. Unfortunately, I messed up the check-function-bodies syntax and passed the target selector as the "option" parameter, which had the effect of disabling the tests for both ILP32 and LP64. The fix ought to have been to add "" as the option parameter. However, check-function-bodies wasn't treating "" in the same way as an omitted argument. The easiest fix seemed to be turn the argument into a list of options, which also makes the interface a bit more general. Having done that, it seemed a good idea to check for things that look like target/xfail selectors, so that the mistake isn't silent next time. 2020-04-09 Richard Sandiford gcc/ * doc/sourcebuild.texi (check-function-bodies): Treat the third parameter as a list of option regexps and require each regexp to match. gcc/testsuite/ * lib/scanasm.exp (check-function-bodies): Treat the third parameter as a list of option regexps and require each regexp to match. Check for cases in which a target/xfail selector was mistakenly passed to the options argument. * gcc.target/aarch64/sve/pcs/args_1.c: Add an empty options list to the invocation of check-function-bodies. * gcc.target/aarch64/sve/pcs/args_2.c: Likewise. * gcc.target/aarch64/sve/pcs/args_3.c: Likewise. * gcc.target/aarch64/sve/pcs/args_4.c: Likewise. * gcc.target/aarch64/sve/pcs/return_1.c: Likewise. * gcc.target/aarch64/sve/pcs/return_1_1024.c: Likewise. * gcc.target/aarch64/sve/pcs/return_1_128.c: Likewise. * gcc.target/aarch64/sve/pcs/return_1_2048.c: Likewise. * gcc.target/aarch64/sve/pcs/return_1_256.c: Likewise. * gcc.target/aarch64/sve/pcs/return_1_512.c: Likewise. * gcc.target/aarch64/sve/pcs/return_2.c: Likewise. * gcc.target/aarch64/sve/pcs/return_3.c: Likewise. * gcc.target/aarch64/sve/pcs/return_4.c: Likewise. * gcc.target/aarch64/sve/pcs/return_4_1024.c: Likewise. * gcc.target/aarch64/sve/pcs/return_4_128.c: Likewise. * gcc.target/aarch64/sve/pcs/return_4_2048.c: Likewise. * gcc.target/aarch64/sve/pcs/return_4_256.c: Likewise. * gcc.target/aarch64/sve/pcs/return_4_512.c: Likewise. * gcc.target/aarch64/sve/pcs/return_5.c: Likewise. * gcc.target/aarch64/sve/pcs/return_5_1024.c: Likewise. * gcc.target/aarch64/sve/pcs/return_5_128.c: Likewise. * gcc.target/aarch64/sve/pcs/return_5_2048.c: Likewise. * gcc.target/aarch64/sve/pcs/return_5_256.c: Likewise. * gcc.target/aarch64/sve/pcs/return_5_512.c: Likewise. * gcc.target/aarch64/sve/pcs/return_6.c: Likewise. * gcc.target/aarch64/sve/pcs/return_6_1024.c: Likewise. * gcc.target/aarch64/sve/pcs/return_6_128.c: Likewise. * gcc.target/aarch64/sve/pcs/return_6_2048.c: Likewise. * gcc.target/aarch64/sve/pcs/return_6_256.c: Likewise. * gcc.target/aarch64/sve/pcs/return_6_512.c: Likewise. * gcc.target/aarch64/sve/pcs/saves_2_be_nowrap.c: Likewise. * gcc.target/aarch64/sve/pcs/saves_2_be_wrap.c: Likewise. * gcc.target/aarch64/sve/pcs/saves_2_le_nowrap.c: Likewise. * gcc.target/aarch64/sve/pcs/saves_2_le_wrap.c: Likewise. * gcc.target/aarch64/sve/pcs/saves_3.c: Likewise. * gcc.target/aarch64/sve/pcs/saves_4_be.c: Likewise. * gcc.target/aarch64/sve/pcs/saves_4_le.c: Likewise. * gcc.target/aarch64/sve/pcs/stack_clash_2_128.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_1.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_f16.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_f32.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_f64.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_s16.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_s32.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_s64.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_s8.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_u16.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_u32.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_u64.c: Likewise. * gcc.target/aarch64/sve/pcs/varargs_2_u8.c: Likewise. --- gcc/ChangeLog | 6 +++ gcc/doc/sourcebuild.texi | 12 +++-- gcc/testsuite/ChangeLog | 58 ++++++++++++++++++++++ gcc/testsuite/gcc.target/aarch64/sve/pcs/args_1.c | 2 +- gcc/testsuite/gcc.target/aarch64/sve/pcs/args_2.c | 2 +- gcc/testsuite/gcc.target/aarch64/sve/pcs/args_3.c | 2 +- gcc/testsuite/gcc.target/aarch64/sve/pcs/args_4.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_1.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_1_1024.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_1_128.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_1_2048.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_1_256.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_1_512.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_2.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_3.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_4.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_4_1024.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_4_128.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_4_2048.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_4_256.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_4_512.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_5.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_5_1024.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_5_128.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_5_2048.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_5_256.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_5_512.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_6.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_6_1024.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_6_128.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_6_2048.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_6_256.c | 2 +- .../gcc.target/aarch64/sve/pcs/return_6_512.c | 2 +- .../gcc.target/aarch64/sve/pcs/saves_2_be_nowrap.c | 2 +- .../gcc.target/aarch64/sve/pcs/saves_2_be_wrap.c | 2 +- .../gcc.target/aarch64/sve/pcs/saves_2_le_nowrap.c | 2 +- .../gcc.target/aarch64/sve/pcs/saves_2_le_wrap.c | 2 +- gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_3.c | 2 +- .../gcc.target/aarch64/sve/pcs/saves_4_be.c | 2 +- .../gcc.target/aarch64/sve/pcs/saves_4_le.c | 2 +- .../gcc.target/aarch64/sve/pcs/stack_clash_2_128.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_1.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_f16.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_f32.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_f64.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_s16.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_s32.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_s64.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_s8.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_u16.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_u32.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_u64.c | 2 +- .../gcc.target/aarch64/sve/pcs/varargs_2_u8.c | 2 +- gcc/testsuite/lib/scanasm.exp | 16 ++++-- 54 files changed, 134 insertions(+), 58 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 80492ef..d211d73 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-04-09 Richard Sandiford + + * doc/sourcebuild.texi (check-function-bodies): Treat the third + parameter as a list of option regexps and require each regexp + to match. + 2020-04-09 Andrea Corallo PR target/94530 diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 26a57e3..0bccae8 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2754,17 +2754,19 @@ assembly output. Passes if @var{symbol} is not defined as a hidden symbol in the test's assembly output. -@item check-function-bodies @var{prefix} @var{terminator} [@var{option} [@{ target/xfail @var{selector} @}]] +@item check-function-bodies @var{prefix} @var{terminator} [@var{options} [@{ target/xfail @var{selector} @}]] Looks through the source file for comments that give the expected assembly output for selected functions. Each line of expected output starts with the prefix string @var{prefix} and the expected output for a function as a whole is followed by a line that starts with the string @var{terminator}. Specifying an empty terminator is equivalent to specifying @samp{"*/"}. -If @var{option} is specified, the test only applies to command lines -that contain @var{option}. This can be useful if a source file is compiled -both with and without optimization, since it is rarely useful to check the -assembly output for unoptimized code. +@var{options}, if specified, is a list of regular expressions, each of +which matches a full command-line option. A non-empty list prevents +the test from running unless all of the given options are present on the +command line. This can help if a source file is compiled both with +and without optimization, since it is rarely useful to check the full +function body for unoptimized code. The first line of the expected output for a function @var{fn} has the form: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ba530077..991241e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,61 @@ +2020-04-09 Richard Sandiford + + * lib/scanasm.exp (check-function-bodies): Treat the third + parameter as a list of option regexps and require each regexp + to match. Check for cases in which a target/xfail selector + was mistakenly passed to the options argument. + * gcc.target/aarch64/sve/pcs/args_1.c: Add an empty options list + to the invocation of check-function-bodies. + * gcc.target/aarch64/sve/pcs/args_2.c: Likewise. + * gcc.target/aarch64/sve/pcs/args_3.c: Likewise. + * gcc.target/aarch64/sve/pcs/args_4.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_1.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_1_1024.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_1_128.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_1_2048.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_1_256.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_1_512.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_2.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_3.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_4.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_4_1024.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_4_128.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_4_2048.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_4_256.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_4_512.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_5.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_5_1024.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_5_128.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_5_2048.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_5_256.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_5_512.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_6.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_6_1024.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_6_128.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_6_2048.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_6_256.c: Likewise. + * gcc.target/aarch64/sve/pcs/return_6_512.c: Likewise. + * gcc.target/aarch64/sve/pcs/saves_2_be_nowrap.c: Likewise. + * gcc.target/aarch64/sve/pcs/saves_2_be_wrap.c: Likewise. + * gcc.target/aarch64/sve/pcs/saves_2_le_nowrap.c: Likewise. + * gcc.target/aarch64/sve/pcs/saves_2_le_wrap.c: Likewise. + * gcc.target/aarch64/sve/pcs/saves_3.c: Likewise. + * gcc.target/aarch64/sve/pcs/saves_4_be.c: Likewise. + * gcc.target/aarch64/sve/pcs/saves_4_le.c: Likewise. + * gcc.target/aarch64/sve/pcs/stack_clash_2_128.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_1.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_f16.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_f32.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_f64.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_s16.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_s32.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_s64.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_s8.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_u16.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_u32.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_u64.c: Likewise. + * gcc.target/aarch64/sve/pcs/varargs_2_u8.c: Likewise. + 2020-04-09 Richard Biener PR testsuite/93369 diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_1.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_1.c index ab7c4a1..4509fff 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_2.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_2.c index 43a5088..29e80dc 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_2.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_3.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_3.c index 49fdfc9..611f3d0 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_3.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_3.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_4.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_4.c index 4f15fdd..c40d63e 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_4.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/args_4.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1.c index f6328c9..8ad1604 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ /* ** callee_pred: diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_1024.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_1024.c index 450a3f0..d351a1d 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_1024.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_1024.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=1024 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ /* ** callee_pred: diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_128.c index 75d1e22..c164c01 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_128.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_128.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=128 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target { aarch64_little_endian && lp64 } } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target { aarch64_little_endian && lp64 } } } } */ /* ** callee_pred: diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_2048.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_2048.c index c9ea268..cb0f2f0 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_2048.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_2048.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=2048 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ /* ** callee_pred: diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_256.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_256.c index 62bc695..c5d7181 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_256.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_256.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=256 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ /* ** callee_pred: diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_512.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_512.c index f687689..41b3eff 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_512.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_1_512.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=512 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ /* ** callee_pred: diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_2.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_2.c index efaa813..676be9d 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_2.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_3.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_3.c index 7104644..2bb6c79 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_3.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_3.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4.c index 00eb2cb..1e38371 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #define CALLEE(SUFFIX, TYPE) \ TYPE __attribute__((noipa)) \ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_1024.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_1024.c index 4351963..491c35a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_1024.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_1024.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=1024 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #define CALLEE(SUFFIX, TYPE) \ TYPE __attribute__((noipa)) \ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_128.c index 6b49022..eebb913 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_128.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_128.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=128 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target { aarch64_little_endian && lp64 } } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target { aarch64_little_endian && lp64 } } } } */ #define CALLEE(SUFFIX, TYPE) \ TYPE __attribute__((noipa)) \ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_2048.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_2048.c index 8256645..73c3b2e 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_2048.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_2048.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=2048 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #define CALLEE(SUFFIX, TYPE) \ TYPE __attribute__((noipa)) \ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_256.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_256.c index 1e0f6bb..29744c8 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_256.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_256.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=256 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #define CALLEE(SUFFIX, TYPE) \ TYPE __attribute__((noipa)) \ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_512.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_512.c index 5b58ed7..cf25c31 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_512.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_4_512.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=512 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #define CALLEE(SUFFIX, TYPE) \ TYPE __attribute__((noipa)) \ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5.c index 55c78e1..9ad3e22 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_1024.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_1024.c index 52e9916..d573e5f 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_1024.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_1024.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=1024 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_128.c index cfb2f38..200b0eb 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_128.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_128.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=128 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target { aarch64_little_endian && lp64 } } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target { aarch64_little_endian && lp64 } } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_2048.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_2048.c index 6f37d9d..f6f8858 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_2048.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_2048.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=2048 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_256.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_256.c index 7ba094e..e62f59c 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_256.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_256.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=256 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_512.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_512.c index 36b14d4..483558c 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_512.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_5_512.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=512 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6.c index 72468ea..1bc2f43 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_1024.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_1024.c index b6f267e..de69d9a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_1024.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_1024.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=1024 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_128.c index fd83845..4f190fd 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_128.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_128.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=128 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target { aarch64_little_endian && lp64 } } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target { aarch64_little_endian && lp64 } } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_2048.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_2048.c index 46b7d68..0b64ff2 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_2048.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_2048.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=2048 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_256.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_256.c index 0487249..9eb71e3 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_256.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_256.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=256 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_512.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_512.c index 9817d85..8b8d0c7 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_512.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/return_6_512.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -msve-vector-bits=512 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_be_nowrap.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_be_nowrap.c index 7c4884d..f9532d3 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_be_nowrap.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_be_nowrap.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -mbig-endian -fno-shrink-wrap -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ void standard_callee (void); __attribute__((aarch64_vector_pcs)) void vpcs_callee (void); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_be_wrap.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_be_wrap.c index 872364f..bbc4f84 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_be_wrap.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_be_wrap.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -mbig-endian -fshrink-wrap -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ void standard_callee (void); __attribute__((aarch64_vector_pcs)) void vpcs_callee (void); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_le_nowrap.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_le_nowrap.c index 4ba71c0..8e734d4 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_le_nowrap.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_le_nowrap.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -mlittle-endian -fno-shrink-wrap -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ void standard_callee (void); __attribute__((aarch64_vector_pcs)) void vpcs_callee (void); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_le_wrap.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_le_wrap.c index c3acd40..fab393a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_le_wrap.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_2_le_wrap.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -mlittle-endian -fshrink-wrap -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ void standard_callee (void); __attribute__((aarch64_vector_pcs)) void vpcs_callee (void); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_3.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_3.c index 1fe86b0..2d29ce2 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_3.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_3.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_4_be.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_4_be.c index aa67bee..38a414c 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_4_be.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_4_be.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -mbig-endian -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ void standard_callee (__SVInt8_t *); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_4_le.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_4_le.c index ab232d7..f8fe5d1 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_4_le.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/saves_4_le.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -mlittle-endian -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ void standard_callee (__SVInt8_t *); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_128.c index e41de10..41193b4 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_128.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_128.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -fshrink-wrap -fstack-clash-protection -msve-vector-bits=128 -g" } */ -/* { dg-final { check-function-bodies "**" "" { target { aarch64_little_endian && lp64 } } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target { aarch64_little_endian && lp64 } } } } */ #pragma GCC aarch64 "arm_sve.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_1.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_1.c index 6987245..72960fd 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f16.c index 7909885..9b91620 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f16.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f32.c index 325b0b2..b979f43 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f32.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f64.c index 07a6c70..6f2235f 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_f64.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s16.c index 1730638..523d3be 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s16.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s32.c index d93db8f..afde5a7 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s32.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s64.c index b8c7745..d119d0a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s64.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s8.c index de7cbe3..ce6d663 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s8.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_s8.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u16.c index 59c9ca7..50ae7ba 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u16.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u32.c index 3050ad5..d726c72 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u32.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u64.c index 94322a3..ef1265c 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u64.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u8.c index cf8ac21..e6a82fe 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u8.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/varargs_2_u8.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-stack-clash-protection -g" } */ -/* { dg-final { check-function-bodies "**" "" { target lp64 } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include #include diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index f7d2773..8d2364f 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -617,7 +617,7 @@ proc check-function-bodies { args } { } if { [llength $args] >= 3 } { - set required_flag [lindex $args 2] + set required_flags [lindex $args 2] upvar 2 dg-extra-tool-flags extra_tool_flags set flags $extra_tool_flags @@ -626,8 +626,18 @@ proc check-function-bodies { args } { if { [info exists torture_current_flags] } { append flags " " $torture_current_flags } - if { ![regexp " $required_flag " $flags] } { - return + foreach required_flag $required_flags { + switch -- $required_flag { + target - + xfail { + error "misplaced $required_flag in check-function-bodies" + } + } + } + foreach required_flag $required_flags { + if { ![regexp " $required_flag " $flags] } { + return + } } } -- cgit v1.1 From f60979edbfcf6ce2cbf2cb09b8af8c125ff7774f Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 9 Apr 2020 14:12:36 +0200 Subject: Avoid g++.dg/lto/alias-4_0.C test failure on ARM [PR91322] PR tree-optimization/91322 * g++.dg/lto/alias-4_0.C: Avoid conflict with va_list on ARM and add a template testing that. --- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/lto/alias-4_0.C | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 991241e..fac41ca 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-09 Jan Hubicka + + PR tree-optimization/91322 + * g++.dg/lto/alias-4_0.C: Avoid conflict with va_list on ARM and add + a template testing that + 2020-04-09 Richard Sandiford * lib/scanasm.exp (check-function-bodies): Treat the third diff --git a/gcc/testsuite/g++.dg/lto/alias-4_0.C b/gcc/testsuite/g++.dg/lto/alias-4_0.C index 410c314..3d38632 100644 --- a/gcc/testsuite/g++.dg/lto/alias-4_0.C +++ b/gcc/testsuite/g++.dg/lto/alias-4_0.C @@ -1,11 +1,14 @@ /* { dg-lto-do run } */ -/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */ +/* { dg-lto-options { { -O3 -flto -fno-early-inlining -fdump-ipa-cgraph} } } */ __attribute__ ((used)) short *ptr_init, **ptr=&ptr_init; __attribute__ ((used)) struct a { int *aptr; + /* On ARM va_list is an anonymous structure containing pointer. + This disable ODR TBAA on it. */ + short b; } a, *aptr=&a; void @@ -29,3 +32,6 @@ main() test (); return 0; } +/* On ARM the testcase used to fial because struct a got in conflict with builtin + va_list type. Check that this does not happen. */ +/* { dg-final { scan-wpa-ipa-dump-not "ODR and non-ODR type conflict" "cgraph" } } */ -- cgit v1.1 From 148289004696940ea5828d19e63a1e3791a2fb70 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 9 Apr 2020 14:16:34 +0200 Subject: Fix typo in my previous change. --- gcc/testsuite/ChangeLog | 1 + gcc/testsuite/g++.dg/lto/alias-4_0.C | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fac41ca..6a97221 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,7 @@ 2020-04-09 Jan Hubicka PR tree-optimization/91322 + * g++.dg/lto/alias-4_0.C: Fix typo. * g++.dg/lto/alias-4_0.C: Avoid conflict with va_list on ARM and add a template testing that diff --git a/gcc/testsuite/g++.dg/lto/alias-4_0.C b/gcc/testsuite/g++.dg/lto/alias-4_0.C index 3d38632..240c4d0 100644 --- a/gcc/testsuite/g++.dg/lto/alias-4_0.C +++ b/gcc/testsuite/g++.dg/lto/alias-4_0.C @@ -32,6 +32,6 @@ main() test (); return 0; } -/* On ARM the testcase used to fial because struct a got in conflict with builtin +/* On ARM the testcase used to fail because struct a got in conflict with builtin va_list type. Check that this does not happen. */ /* { dg-final { scan-wpa-ipa-dump-not "ODR and non-ODR type conflict" "cgraph" } } */ -- cgit v1.1 From 830c572428758f134bd001e699a08e622e2452c3 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 8 Apr 2020 17:03:53 -0400 Subject: c++: Fix wrong paren-init of aggregates interference [PR93790] This PR points out that we are rejecting valid code in C++20. The problem is that we were surreptitiously transforming T& t(e) into T& t{e} which is wrong, because the type of e had a conversion function to T, while aggregate initialization of t from e doesn't work. Therefore, I was violating a design principle of P0960, which says that any existing meaning of A(b) should not change. So I think we should only attempt to aggregate-initialize if the original expression was ill-formed. Another design principle is that () should work where {} works, so this: struct S { int i; }; const S& s(1); has to keep working. Thus the special handling for paren-lists with one element. (A paren-list with more than one element would give you "error: expression list treated as compound expression in initializer" C++17.) PR c++/93790 * call.c (initialize_reference): If the reference binding failed, maybe try initializing from { }. * decl.c (grok_reference_init): For T& t(e), set LOOKUP_AGGREGATE_PAREN_INIT but don't build up a constructor yet. * g++.dg/cpp2a/paren-init23.C: New test. * g++.dg/init/aggr14.C: New test. --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/call.c | 14 ++++++++++++++ gcc/cp/decl.c | 19 ++++++++++++++++--- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/cpp2a/paren-init23.C | 19 +++++++++++++++++++ gcc/testsuite/g++.dg/init/aggr14.C | 14 ++++++++++++++ 6 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/paren-init23.C create mode 100644 gcc/testsuite/g++.dg/init/aggr14.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e63f30b..cdd9b52 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2020-04-09 Marek Polacek + + PR c++/93790 + * call.c (initialize_reference): If the reference binding failed, maybe + try initializing from { }. + * decl.c (grok_reference_init): For T& t(e), set + LOOKUP_AGGREGATE_PAREN_INIT but don't build up a constructor yet. + 2020-04-08 Iain Sandoe Jun Ma diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 02220ff..1f3d9d2 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -12196,6 +12196,20 @@ initialize_reference (tree type, tree expr, conv = reference_binding (type, TREE_TYPE (expr), expr, /*c_cast_p=*/false, flags, complain); + /* If this conversion failed, we're in C++20, and we have something like + A& a(b) where A is an aggregate, try again, this time as A& a{b}. */ + if ((!conv || conv->bad_p) + && (flags & LOOKUP_AGGREGATE_PAREN_INIT)) + { + tree e = build_constructor_single (init_list_type_node, NULL_TREE, expr); + CONSTRUCTOR_IS_DIRECT_INIT (e) = true; + CONSTRUCTOR_IS_PAREN_INIT (e) = true; + conversion *c = reference_binding (type, TREE_TYPE (e), e, + /*c_cast_p=*/false, flags, complain); + /* If this worked, use it. */ + if (c && !c->bad_p) + expr = e, conv = c; + } if (!conv || conv->bad_p) { if (complain & tf_error) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a6a1340..1447b89 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5568,9 +5568,22 @@ grok_reference_init (tree decl, tree type, tree init, int flags) && !DECL_DECOMPOSITION_P (decl) && (cxx_dialect >= cxx2a)) { - init = build_constructor_from_list (init_list_type_node, init); - CONSTRUCTOR_IS_DIRECT_INIT (init) = true; - CONSTRUCTOR_IS_PAREN_INIT (init) = true; + /* We don't know yet if we should treat const A& r(1) as + const A& r{1}. */ + if (list_length (init) == 1) + { + flags |= LOOKUP_AGGREGATE_PAREN_INIT; + init = build_x_compound_expr_from_list (init, ELK_INIT, + tf_warning_or_error); + } + /* If the list had more than one element, the code is ill-formed + pre-C++20, so we can build a constructor right away. */ + else + { + init = build_constructor_from_list (init_list_type_node, init); + CONSTRUCTOR_IS_DIRECT_INIT (init) = true; + CONSTRUCTOR_IS_PAREN_INIT (init) = true; + } } else init = build_x_compound_expr_from_list (init, ELK_INIT, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6a97221..a5bd561 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-09 Marek Polacek + + PR c++/93790 + * g++.dg/cpp2a/paren-init23.C: New test. + * g++.dg/init/aggr14.C: New test. + 2020-04-09 Jan Hubicka PR tree-optimization/91322 diff --git a/gcc/testsuite/g++.dg/cpp2a/paren-init23.C b/gcc/testsuite/g++.dg/cpp2a/paren-init23.C new file mode 100644 index 0000000..6038f63 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/paren-init23.C @@ -0,0 +1,19 @@ +// PR c++/93790 - wrong paren-init of aggregates interference. +// { dg-do compile { target c++2a } } + +struct S { + int i; +}; +const S& s(1); + +struct A { + int i; + A(int); +}; +const A& a(1); + +struct B { + int i; + B(int) = delete; +}; +const B& b(1); // { dg-error "use of deleted function" } diff --git a/gcc/testsuite/g++.dg/init/aggr14.C b/gcc/testsuite/g++.dg/init/aggr14.C new file mode 100644 index 0000000..538b467 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/aggr14.C @@ -0,0 +1,14 @@ +// PR c++/93790 - wrong paren-init of aggregates interference. +// { dg-do compile } + +struct S {}; +class S_refwrap { + S& Sref_; +public: + S_refwrap(S& Sref) : Sref_(Sref) {} + operator S&() { return Sref_; } +}; + +S s; +S_refwrap r(s); +S& s2(r); -- cgit v1.1 From 2111d5406a4ec56d6335bde779a995914d0a36d1 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Thu, 9 Apr 2020 14:37:21 +0200 Subject: sra: Fix sra_modify_expr handling of partial writes (PR 94482) when sra_modify_expr is invoked on an expression that modifies only part of the underlying replacement, such as a BIT_FIELD_REF on a LHS of an assignment and the SRA replacement's type is not compatible with what is being replaced (0th operand of the B_F_R in the above example), it does not work properly, basically throwing away the partd of the expr that should have stayed intact. This is fixed in two ways. For BIT_FIELD_REFs, which operate on the binary image of the replacement (and so in a way serve as a VIEW_CONVERT_EXPR) we just do not bother with convertsing. For REALPART_EXPRs and IMAGPART_EXPRs, if the replacement is not a register, we insert a VIEW_CONVERT_EXPR under the complex partial access expression, which is always OK, for loads from registers we take the extra step of converting it to a temporary. This revealed a bug in fwprop which is fixed with the hunk from Richi. The testcase for handling REALPART_EXPR and IMAGPART_EXPR is a bit fragile because SRA prefers complex and vector types over anything else (and in between the two it decides based on TYPE_UID which in my testing today always preferred complex types) and so I only run it at -O1 (which is the only level where the the test fails for me). Bootstrapped and tested on x86_64-linux, i686-linux and aarch64-linux. 2020-04-09 Martin Jambor Richard Biener PR tree-optimization/94482 * tree-sra.c (create_access_replacement): Dump new replacement with TDF_UID. (sra_modify_expr): Fix handling of cases when the original EXPR writes to only part of the replacement. * tree-ssa-forwprop.c (pass_forwprop::execute): Properly verify the first operand of combinations into REAL/IMAGPART_EXPR and BIT_FIELD_REF. testsuite/ * gcc.dg/torture/pr94482.c: New test. * gcc.dg/tree-ssa/pr94482-2.c: Likewise. --- gcc/ChangeLog | 12 ++++++++ gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gcc.dg/torture/pr94482.c | 36 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr94482-2.c | 50 +++++++++++++++++++++++++++++++ gcc/tree-sra.c | 31 ++++++++++++++++--- gcc/tree-ssa-forwprop.c | 6 ++-- 6 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr94482.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94482-2.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d211d73..368dfd6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2020-04-09 Martin Jambor + Richard Biener + + PR tree-optimization/94482 + * tree-sra.c (create_access_replacement): Dump new replacement with + TDF_UID. + (sra_modify_expr): Fix handling of cases when the original EXPR writes + to only part of the replacement. + * tree-ssa-forwprop.c (pass_forwprop::execute): Properly verify + the first operand of combinations into REAL/IMAGPART_EXPR and + BIT_FIELD_REF. + 2020-04-09 Richard Sandiford * doc/sourcebuild.texi (check-function-bodies): Treat the third diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a5bd561..e01fdb0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-09 Martin Jambor + + PR tree-optimization/94482 + * gcc.dg/torture/pr94482.c: New test. + * gcc.dg/tree-ssa/pr94482-2.c: Likewise. + 2020-04-09 Marek Polacek PR c++/93790 diff --git a/gcc/testsuite/gcc.dg/torture/pr94482.c b/gcc/testsuite/gcc.dg/torture/pr94482.c new file mode 100644 index 0000000..d9ccaf3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr94482.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-options "-msse" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-require-effective-target sse_runtime { target { i?86-*-* x86_64-*-* } } } */ + +typedef unsigned V __attribute__ ((__vector_size__ (16))); +union U +{ + V j; + unsigned long long i __attribute__ ((__vector_size__ (16))); +}; + +static inline __attribute__((always_inline)) V +foo (unsigned long long a) +{ + union U z = { .j = (V) {} }; + for (unsigned long i = 0; i < 1; i++) + z.i[i] = a; + return z.j; +} + +static inline __attribute__((always_inline)) V +bar (V a, unsigned long long i, int q) +{ + union U z = { .j = a }; + z.i[q] = i; + return z.j; +} + +int +main () +{ + union U z = { .j = bar (foo (1729), 2, 1) }; + if (z.i[0] != 1729) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94482-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94482-2.c new file mode 100644 index 0000000..fcac9d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94482-2.c @@ -0,0 +1,50 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +typedef unsigned long V __attribute__ ((__vector_size__ (8))); +typedef _Complex int Ci; +typedef _Complex float Cf; + +union U +{ + Ci ci; + Cf cf; +}; + +volatile Ci vgi; + +Cf foo (Cf c) +{ + __real c = 0x1ffp10; + return c; +} + +Ci ioo (Ci c) +{ + __real c = 50; + return c; +} + + +int main (int argc, char *argv[]) +{ + union U u; + + __real u.ci = 500; + __imag u.ci = 1000; + vgi = u.ci; + + u.ci = ioo (u.ci); + __imag u.ci = 100; + + if (__real u.ci != 50 || __imag u.ci != 100) + __builtin_abort(); + + u.cf = foo (u.cf); + __imag u.cf = 0x1p3; + + if (__real u.cf != 0x1ffp10 || __imag u.cf != 0x1p3) + __builtin_abort(); + + return 0; +} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index b2056b5..84c113c 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -2257,7 +2257,7 @@ create_access_replacement (struct access *access, tree reg_type = NULL_TREE) print_generic_expr (dump_file, access->base); fprintf (dump_file, " offset: %u, size: %u: ", (unsigned) access->offset, (unsigned) access->size); - print_generic_expr (dump_file, repl); + print_generic_expr (dump_file, repl, TDF_UID); fprintf (dump_file, "\n"); } } @@ -3698,6 +3698,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) location_t loc; struct access *access; tree type, bfr, orig_expr; + bool partial_cplx_access = false; if (TREE_CODE (*expr) == BIT_FIELD_REF) { @@ -3708,7 +3709,10 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) bfr = NULL_TREE; if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR) - expr = &TREE_OPERAND (*expr, 0); + { + expr = &TREE_OPERAND (*expr, 0); + partial_cplx_access = true; + } access = get_access_for_expr (*expr); if (!access) return false; @@ -3736,13 +3740,32 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) be accessed as a different type too, potentially creating a need for type conversion (see PR42196) and when scalarized unions are involved in assembler statements (see PR42398). */ - if (!useless_type_conversion_p (type, access->type)) + if (!bfr && !useless_type_conversion_p (type, access->type)) { tree ref; ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false); - if (write) + if (partial_cplx_access) + { + /* VIEW_CONVERT_EXPRs in partial complex access are always fine in + the case of a write because in such case the replacement cannot + be a gimple register. In the case of a load, we have to + differentiate in between a register an non-register + replacement. */ + tree t = build1 (VIEW_CONVERT_EXPR, type, repl); + gcc_checking_assert (!write || access->grp_partial_lhs); + if (!access->grp_partial_lhs) + { + tree tmp = make_ssa_name (type); + gassign *stmt = gimple_build_assign (tmp, t); + /* This is always a read. */ + gsi_insert_before (gsi, stmt, GSI_SAME_STMT); + t = tmp; + } + *expr = t; + } + else if (write) { gassign *stmt; diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index e7eaa18..3d8acf7 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -2815,7 +2815,8 @@ pass_forwprop::execute (function *fun) continue; if (!is_gimple_assign (use_stmt) || (gimple_assign_rhs_code (use_stmt) != REALPART_EXPR - && gimple_assign_rhs_code (use_stmt) != IMAGPART_EXPR)) + && gimple_assign_rhs_code (use_stmt) != IMAGPART_EXPR) + || TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) != lhs) { rewrite = false; break; @@ -2877,7 +2878,8 @@ pass_forwprop::execute (function *fun) if (is_gimple_debug (use_stmt)) continue; if (!is_gimple_assign (use_stmt) - || gimple_assign_rhs_code (use_stmt) != BIT_FIELD_REF) + || gimple_assign_rhs_code (use_stmt) != BIT_FIELD_REF + || TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) != lhs) { rewrite = false; break; -- cgit v1.1 From 93674a72309f986c9ace2d6060916053a00da2a1 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Thu, 9 Apr 2020 13:56:44 +0000 Subject: [testsuite] scanasm.exp: Fix target-selector handling in check-function-bodies {target { ! a } } does not work because the greedy regexp extracts "! a }" instead of "target { ! a }". This patch replaces it with a non-greedy regexp. 2020-04-09 Christophe Lyon * lib/scanasm.exp (check-function-bodies): Use non-greedy regexp when extracting the target selector. --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/lib/scanasm.exp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e01fdb0..e692a7f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-09 Christophe Lyon + + * lib/scanasm.exp (check-function-bodies): Use non-greedy regexp + when extracting the target selector. + 2020-04-09 Martin Jambor PR tree-optimization/94482 diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index 8d2364f..d5f2be4 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -689,7 +689,7 @@ proc check-function-bodies { args } { if { [string equal -length $prefix_len $line $prefix] } { set line [string trim [string range $line $prefix_len end]] if { !$in_function } { - if { [regexp "^(.*\\S)\\s+{(.*)}\$" $line dummy \ + if { [regexp "^(.*?\\S)\\s+{(.*)}\$" $line dummy \ line selector] } { set selector [dg-process-target $selector] } else { -- cgit v1.1 From 8b5bc7d12de344707e89c5111649dcc1ae4cd1cd Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Thu, 9 Apr 2020 14:01:22 +0000 Subject: [testsuite][arm] Fix cmse-15.c expected output The cmse-15.c testcase fails at -Os because ICF means that we generate nonsecure2: b nonsecure0 which is OK, but does not match the currently expected nonsecure2: ... bl __gnu_cmse_nonsecure_call (see https://gcc.gnu.org/pipermail/gcc-patches/2020-April/543190.html) The test has already different expectations for v8-M and v8.1-M. This patch uses check-function-bodies to account for the different possibilities: - v8-M vs v8.1-M via different target selectors where needed - code generation variants (-0?) via multiple regexps I've tested that the test now passes with --target-board=-march=armv8-m.main and --target-board=-march=armv8.1-m.main. --- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.target/arm/cmse/cmse-15.c | 152 ++++++++++++++++++++++++++-- 2 files changed, 150 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e692a7f..5e56c38 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2020-04-09 Christophe Lyon + * gcc.target/arm/cmse/cmse-15.c: Use check-function-bodies. + +2020-04-09 Christophe Lyon + * lib/scanasm.exp (check-function-bodies): Use non-greedy regexp when extracting the target selector. diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c index 0e37b50..b0fefe5 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c @@ -1,5 +1,8 @@ /* { dg-do compile } */ /* { dg-options "-mcmse" } */ +/* ARMv8-M expectation with target { ! arm_cmse_clear_ok }. */ +/* ARMv8.1-M expectation with target arm_cmse_clear_ok. */ +/* { dg-final { check-function-bodies "**" "" "" } } */ int __attribute__ ((cmse_nonsecure_call)) (*ns_foo) (void); int (*s_bar) (void); @@ -11,67 +14,204 @@ typedef int s_bar_t (void); typedef int __attribute__ ((cmse_nonsecure_call)) (* ns_foo_ptr) (void); typedef int (*s_bar_ptr) (void); +/* +** nonsecure0: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +*/ +/* +** nonsecure0: { target { ! arm_cmse_clear_ok } } +** ... +** bl __gnu_cmse_nonsecure_call +** ... +*/ int nonsecure0 (ns_foo_t * ns_foo_p) { return ns_foo_p (); } +/* +** nonsecure1: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +*/ +/* +** nonsecure1: { target { ! arm_cmse_clear_ok } } +** ... +** bl __gnu_cmse_nonsecure_call +** ... +*/ int nonsecure1 (ns_foo_t ** ns_foo_p) { return (*ns_foo_p) (); } +/* +** nonsecure2: { target arm_cmse_clear_ok } +** ... +** ( +** blxns r[0-3] +** | +** b nonsecure0 +** ) +** ... +*/ +/* +** nonsecure2: { target { ! arm_cmse_clear_ok } } +** ... +** ( +** bl __gnu_cmse_nonsecure_call +** | +** b nonsecure0 +** ) +** ... +*/ int nonsecure2 (ns_foo_ptr ns_foo_p) { return ns_foo_p (); } + +/* +** nonsecure3: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +*/ +/* +** nonsecure3: { target { ! arm_cmse_clear_ok } } +** ... +** bl __gnu_cmse_nonsecure_call +** ... +*/ int nonsecure3 (ns_foo_ptr * ns_foo_p) { return (*ns_foo_p) (); } +/* +** secure0: +** ... +** ( +** bx r[0-3] +** | +** blx r[0-3] +** ) +** ... +*/ int secure0 (s_bar_t * s_bar_p) { return s_bar_p (); } +/* +** secure1: +** ... +** ( +** bx r[0-3] +** | +** blx r[0-3] +** ) +** ... +*/ int secure1 (s_bar_t ** s_bar_p) { return (*s_bar_p) (); } +/* +** secure2: +** ... +** ( +** bx r[0-3] +** | +** blx r[0-3] +** | +** b secure0 +** ) +** ... +*/ int secure2 (s_bar_ptr s_bar_p) { return s_bar_p (); } +/* +** secure3: +** ... +** ( +** bx r[0-3] +** | +** blx r[0-3] +** ) +** ... +*/ int secure3 (s_bar_ptr * s_bar_p) { return (*s_bar_p) (); } +/* +** nonsecure4: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +*/ +/* +** nonsecure4: { target { ! arm_cmse_clear_ok } } +** ... +** bl __gnu_cmse_nonsecure_call +** ... +*/ int nonsecure4 (void) { return ns_foo (); } +/* +** nonsecure5: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +*/ +/* +** nonsecure5: { target { ! arm_cmse_clear_ok } } +** ... +** bl __gnu_cmse_nonsecure_call +** ... +*/ int nonsecure5 (void) { return (*ns_foo2) (); } +/* +** secure4: +** ... +** ( +** bx r[0-3] +** | +** blx r[0-3] +** ) +** ... +*/ int secure4 (void) { return s_bar (); } +/* +** secure5: +** ... +** ( +** bx r[0-3] +** | +** blx r[0-3] +** ) +** ... +*/ int secure5 (void) { return (*s_bar2) (); } - -/* ARMv8-M expectation. */ -/* { dg-final { scan-assembler-times "bl\\s+__gnu_cmse_nonsecure_call" 6 { target { ! arm_cmse_clear_ok } } } } */ - -/* ARMv8.1-M expectation. */ -/* { dg-final { scan-assembler-times "blxns" 6 { target arm_cmse_clear_ok } } } */ -- cgit v1.1 From a4d2774c9c1e213cb129c8b81a591297669838c8 Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Thu, 9 Apr 2020 16:11:09 +0100 Subject: [Arm] Allow the use of arm_cde.h for C++ arm_cde.h includes the arm_mve_types.h header, which declares some C++ overloaded functions. There is a superfluous `extern "C"` statement in arm_cde.h, which encompasses these functions. This means that if compiling for C++, the overloaded functions are declared, but are declared without name mangling. Hence all the function names are the same and we have many conflicting declarations. Testing Done: Regression tested for arm-none-eabi. gcc/ChangeLog: 2020-04-09 Matthew Malcomson * config/arm/arm_cde.h: Remove `extern "C"` when compiling for C++. gcc/testsuite/ChangeLog: 2020-04-09 Matthew Malcomson * g++.target/arm/cde_mve.C: New test. --- gcc/ChangeLog | 5 +++++ gcc/config/arm/arm_cde.h | 8 -------- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/g++.target/arm/cde_mve.C | 10 ++++++++++ 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.target/arm/cde_mve.C (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 368dfd6..d081003 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2020-04-09 Matthew Malcomson + + * config/arm/arm_cde.h: Remove `extern "C"` when compiling for + C++. + 2020-04-09 Martin Jambor Richard Biener diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h index d8ddda6..0ba3ee0 100644 --- a/gcc/config/arm/arm_cde.h +++ b/gcc/config/arm/arm_cde.h @@ -27,10 +27,6 @@ #ifndef _GCC_ARM_CDE_H #define _GCC_ARM_CDE_H 1 -#ifdef __cplusplus -extern "C" { -#endif - #include #if defined (__ARM_FEATURE_CDE) @@ -177,8 +173,4 @@ extern "C" { #endif -#ifdef __cplusplus -} -#endif - #endif diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5e56c38..d79c4db 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-04-09 Matthew Malcomson + + * g++.target/arm/cde_mve.C: New test. + 2020-04-09 Christophe Lyon * gcc.target/arm/cmse/cmse-15.c: Use check-function-bodies. diff --git a/gcc/testsuite/g++.target/arm/cde_mve.C b/gcc/testsuite/g++.target/arm/cde_mve.C new file mode 100644 index 0000000..897cbd2 --- /dev/null +++ b/gcc/testsuite/g++.target/arm/cde_mve.C @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_main_cde_mve_fp } */ + +/* Ensure this compiles. */ +#include "arm_cde.h" +int foo () +{ + return 1; +} -- cgit v1.1 From 5002dae3df4efa7a2db1869ae6f8edd329df8486 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 13 Mar 2020 11:32:53 +0000 Subject: aarch64: Add a separate "SVE sizeless type" attribute It's more convenient for a later patch if sizelessness is represented separately from "SVEness". "SVEness" is an ABI property that carries forward into gimple and beyond, and continues to matter during LTO. Sizelessness is just a frontend restriction and can be ignored after that. 2020-04-09 Richard Sandiford gcc/ * config/aarch64/aarch64.c (aarch64_attribute_table): Add "SVE sizeless type". * config/aarch64/aarch64-sve-builtins.cc (make_type_sizeless) (sizeless_type_p): New functions. (register_builtin_types): Apply make_type_sizeless to the type. (register_tuple_type): Likewise. (verify_type_context): Use sizeless_type_p instead of builin_type_p. --- gcc/ChangeLog | 10 ++++++++++ gcc/config/aarch64/aarch64-sve-builtins.cc | 21 ++++++++++++++++++++- gcc/config/aarch64/aarch64.c | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d081003..0ee6c7d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2020-04-09 Richard Sandiford + + * config/aarch64/aarch64.c (aarch64_attribute_table): Add + "SVE sizeless type". + * config/aarch64/aarch64-sve-builtins.cc (make_type_sizeless) + (sizeless_type_p): New functions. + (register_builtin_types): Apply make_type_sizeless to the type. + (register_tuple_type): Likewise. + (verify_type_context): Use sizeless_type_p instead of builin_type_p. + 2020-04-09 Matthew Malcomson * config/arm/arm_cde.h: Remove `extern "C"` when compiling for diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index 2c5543b..bcd60e9 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -585,6 +585,23 @@ lookup_sve_type_attribute (const_tree type) return lookup_attribute ("SVE type", TYPE_ATTRIBUTES (type)); } +/* Force TYPE to be a sizeless type. */ +static void +make_type_sizeless (tree type) +{ + TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("SVE sizeless type"), + NULL_TREE, TYPE_ATTRIBUTES (type)); +} + +/* Return true if TYPE is a sizeless type. */ +static bool +sizeless_type_p (const_tree type) +{ + if (type == error_mark_node) + return NULL_TREE; + return lookup_attribute ("SVE sizeless type", TYPE_ATTRIBUTES (type)); +} + /* If TYPE is a valid SVE element type, return the corresponding type suffix, otherwise return NUM_TYPE_SUFFIXES. */ static type_suffix_index @@ -3293,6 +3310,7 @@ register_builtin_types () TYPE_INDIVISIBLE_P (vectype) = 1; add_sve_type_attribute (vectype, num_zr, num_pr, vector_types[i].mangled_name); + make_type_sizeless (vectype); abi_vector_types[i] = vectype; lang_hooks.types.register_builtin_type (vectype, vector_types[i].abi_name); @@ -3361,6 +3379,7 @@ register_tuple_type (unsigned int num_vectors, vector_type_index type) DECL_FIELD_CONTEXT (field) = tuple_type; TYPE_FIELDS (tuple_type) = field; add_sve_type_attribute (tuple_type, num_vectors, 0, NULL); + make_type_sizeless (tuple_type); layout_type (tuple_type); gcc_assert (VECTOR_MODE_P (TYPE_MODE (tuple_type)) && TYPE_MODE_RAW (tuple_type) == TYPE_MODE (tuple_type) @@ -3578,7 +3597,7 @@ bool verify_type_context (location_t loc, type_context_kind context, const_tree type, bool silent_p) { - if (!builtin_type_p (type)) + if (!sizeless_type_p (type)) return true; switch (context) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 25eccc7..0a46717 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1247,6 +1247,7 @@ static const struct attribute_spec aarch64_attribute_table[] = { "aarch64_vector_pcs", 0, 0, false, true, true, true, handle_aarch64_vector_pcs_attribute, NULL }, { "SVE type", 3, 3, false, true, false, true, NULL, NULL }, + { "SVE sizeless type", 0, 0, false, true, false, true, NULL, NULL }, { NULL, 0, 0, false, false, false, false, NULL, NULL } }; -- cgit v1.1 From 38e62001c576b8c6ba2e08eb4673d69ec4c5b0f9 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 7 Mar 2020 11:52:33 +0000 Subject: aarch64: Add support for arm_sve_vector_bits This patch implements the "arm_sve_vector_bits" attribute, which can be used to create fixed-length versions of an SVE type while maintaining their "SVEness". For example, when __ARM_FEATURE_SVE_BITS==256: typedef svint32_t vec __attribute__((arm_sve_vector_bits(256))); creates a 256-bit version of svint32_t. The attribute itself is quite simple. However, it means that we now need to implement the full PCS rules for scalable types, whereas previously we only needed to handle scalable types that were built directly into the compiler. See: https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst for more information about these rules. 2020-04-09 Richard Sandiford gcc/ * doc/sourcebuild.texi (aarch64_sve_hw, aarch64_sve128_hw) (aarch64_sve256_hw, aarch64_sve512_hw, aarch64_sve1024_hw) (aarch64_sve2048_hw): Document. * config/aarch64/aarch64-protos.h (aarch64_sve::handle_arm_sve_vector_bits_attribute): Declare. * config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Define __ARM_FEATURE_SVE_VECTOR_OPERATIONS when SVE is enabled. * config/aarch64/aarch64-sve-builtins.cc (matches_type_p): New function. (find_type_suffix_for_scalar_type): Use it instead of comparing TYPE_MAIN_VARIANTs. (function_resolver::infer_vector_or_tuple_type): Likewise. (function_resolver::require_vector_type): Likewise. (handle_arm_sve_vector_bits_attribute): New function. * config/aarch64/aarch64.c (pure_scalable_type_info): New class. (aarch64_attribute_table): Add arm_sve_vector_bits. (aarch64_return_in_memory_1): (pure_scalable_type_info::piece::get_rtx): New function. (pure_scalable_type_info::num_zr): Likewise. (pure_scalable_type_info::num_pr): Likewise. (pure_scalable_type_info::get_rtx): Likewise. (pure_scalable_type_info::analyze): Likewise. (pure_scalable_type_info::analyze_registers): Likewise. (pure_scalable_type_info::analyze_array): Likewise. (pure_scalable_type_info::analyze_record): Likewise. (pure_scalable_type_info::add_piece): Likewise. (aarch64_some_values_include_pst_objects_p): Likewise. (aarch64_returns_value_in_sve_regs_p): Use pure_scalable_type_info to analyze whether the type is returned in SVE registers. (aarch64_takes_arguments_in_sve_regs_p): Likwise whether the type is passed in SVE registers. (aarch64_pass_by_reference_1): New function, extracted from... (aarch64_pass_by_reference): ...here. Use pure_scalable_type_info to analyze whether the type is a pure scalable type and, if so, whether it should be passed by reference. (aarch64_return_in_msb): Return false for pure scalable types. (aarch64_function_value_1): Fold back into... (aarch64_function_value): ...this function. Use pure_scalable_type_info to analyze whether the type is a pure scalable type and, if so, which registers it should use. Handle types that include pure scalable types but are not themselves pure scalable types. (aarch64_return_in_memory_1): New function, split out from... (aarch64_return_in_memory): ...here. Use pure_scalable_type_info to analyze whether the type is a pure scalable type and, if so, whether it should be returned by reference. (aarch64_layout_arg): Remove orig_mode argument. Use pure_scalable_type_info to analyze whether the type is a pure scalable type and, if so, which registers it should use. Handle types that include pure scalable types but are not themselves pure scalable types. (aarch64_function_arg): Update call accordingly. (aarch64_function_arg_advance): Likewise. (aarch64_pad_reg_upward): On big-endian targets, return false for pure scalable types that are smaller than 16 bytes. (aarch64_member_type_forces_blk): New function. (aapcs_vfp_sub_candidate): Exit early for built-in SVE types. (aarch64_short_vector_p): Return false for VECTOR_TYPEs that correspond to built-in SVE types. Do not rely on a vector mode if the type includes an pure scalable type. When returning true, assert that the mode is not an SVE mode. (aarch64_vfp_is_call_or_return_candidate): Do not check for SVE built-in types here. When returning true, assert that the type does not have an SVE mode. (aarch64_can_change_mode_class): Don't allow anything to change between a predicate mode and a non-predicate mode. Also don't allow changes between SVE vector modes and other modes that might be bigger than 128 bits. (aarch64_invalid_binary_op): Reject binary operations that mix SVE and GNU vector types. (TARGET_MEMBER_TYPE_FORCES_BLK): Define. gcc/testsuite/ * gcc.target/aarch64/sve/acle/general/attributes_1.c: New test. * gcc.target/aarch64/sve/acle/general/attributes_2.c: Likewise. * gcc.target/aarch64/sve/acle/general/attributes_3.c: Likewise. * gcc.target/aarch64/sve/acle/general/attributes_4.c: Likewise. * gcc.target/aarch64/sve/acle/general/attributes_5.c: Likewise. * gcc.target/aarch64/sve/acle/general/attributes_6.c: Likewise. * gcc.target/aarch64/sve/acle/general/attributes_7.c: Likewise. * gcc.target/aarch64/sve/pcs/struct.h: New file. * gcc.target/aarch64/sve/pcs/struct_1_128.c: New test. * gcc.target/aarch64/sve/pcs/struct_1_256.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_1_512.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_1_1024.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_1_2048.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_2_128.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_2_256.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_2_512.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_2_1024.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_2_2048.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_3_128.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_3_256.c: Likewise. * gcc.target/aarch64/sve/pcs/struct_3_512.c: Likewise. * lib/target-supports.exp (check_effective_target_aarch64_sve128_hw) (check_effective_target_aarch64_sve512_hw) (check_effective_target_aarch64_sve1024_hw) (check_effective_target_aarch64_sve2048_hw): New procedures. --- gcc/ChangeLog | 74 ++ gcc/config/aarch64/aarch64-c.c | 2 + gcc/config/aarch64/aarch64-protos.h | 1 + gcc/config/aarch64/aarch64-sve-builtins.cc | 83 +- gcc/config/aarch64/aarch64.c | 829 ++++++++++--- gcc/doc/sourcebuild.texi | 9 + gcc/testsuite/ChangeLog | 28 + .../aarch64/sve/acle/general/attributes_1.c | 205 ++++ .../aarch64/sve/acle/general/attributes_2.c | 3 + .../aarch64/sve/acle/general/attributes_3.c | 3 + .../aarch64/sve/acle/general/attributes_4.c | 3 + .../aarch64/sve/acle/general/attributes_5.c | 7 + .../aarch64/sve/acle/general/attributes_6.c | 97 ++ .../aarch64/sve/acle/general/attributes_7.c | 181 +++ gcc/testsuite/gcc.target/aarch64/sve/pcs/struct.h | 77 ++ .../gcc.target/aarch64/sve/pcs/struct_1_1024.c | 4 + .../gcc.target/aarch64/sve/pcs/struct_1_128.c | 405 +++++++ .../gcc.target/aarch64/sve/pcs/struct_1_2048.c | 4 + .../gcc.target/aarch64/sve/pcs/struct_1_256.c | 4 + .../gcc.target/aarch64/sve/pcs/struct_1_512.c | 4 + .../gcc.target/aarch64/sve/pcs/struct_2_1024.c | 4 + .../gcc.target/aarch64/sve/pcs/struct_2_128.c | 701 +++++++++++ .../gcc.target/aarch64/sve/pcs/struct_2_2048.c | 4 + .../gcc.target/aarch64/sve/pcs/struct_2_256.c | 4 + .../gcc.target/aarch64/sve/pcs/struct_2_512.c | 4 + .../gcc.target/aarch64/sve/pcs/struct_3_128.c | 1092 +++++++++++++++++ .../gcc.target/aarch64/sve/pcs/struct_3_256.c | 1231 ++++++++++++++++++++ .../gcc.target/aarch64/sve/pcs/struct_3_512.c | 1197 +++++++++++++++++++ gcc/testsuite/lib/target-supports.exp | 8 +- 29 files changed, 6093 insertions(+), 175 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_2.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_3.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_4.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_5.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_6.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct.h create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_1024.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_128.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_2048.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_256.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_512.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_1024.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_128.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_2048.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_256.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_512.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_128.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_256.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_512.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0ee6c7d..1066146 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,79 @@ 2020-04-09 Richard Sandiford + * doc/sourcebuild.texi (aarch64_sve_hw, aarch64_sve128_hw) + (aarch64_sve256_hw, aarch64_sve512_hw, aarch64_sve1024_hw) + (aarch64_sve2048_hw): Document. + * config/aarch64/aarch64-protos.h + (aarch64_sve::handle_arm_sve_vector_bits_attribute): Declare. + * config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Define + __ARM_FEATURE_SVE_VECTOR_OPERATIONS when SVE is enabled. + * config/aarch64/aarch64-sve-builtins.cc (matches_type_p): New + function. + (find_type_suffix_for_scalar_type): Use it instead of comparing + TYPE_MAIN_VARIANTs. + (function_resolver::infer_vector_or_tuple_type): Likewise. + (function_resolver::require_vector_type): Likewise. + (handle_arm_sve_vector_bits_attribute): New function. + * config/aarch64/aarch64.c (pure_scalable_type_info): New class. + (aarch64_attribute_table): Add arm_sve_vector_bits. + (aarch64_return_in_memory_1): + (pure_scalable_type_info::piece::get_rtx): New function. + (pure_scalable_type_info::num_zr): Likewise. + (pure_scalable_type_info::num_pr): Likewise. + (pure_scalable_type_info::get_rtx): Likewise. + (pure_scalable_type_info::analyze): Likewise. + (pure_scalable_type_info::analyze_registers): Likewise. + (pure_scalable_type_info::analyze_array): Likewise. + (pure_scalable_type_info::analyze_record): Likewise. + (pure_scalable_type_info::add_piece): Likewise. + (aarch64_some_values_include_pst_objects_p): Likewise. + (aarch64_returns_value_in_sve_regs_p): Use pure_scalable_type_info + to analyze whether the type is returned in SVE registers. + (aarch64_takes_arguments_in_sve_regs_p): Likwise whether the type + is passed in SVE registers. + (aarch64_pass_by_reference_1): New function, extracted from... + (aarch64_pass_by_reference): ...here. Use pure_scalable_type_info + to analyze whether the type is a pure scalable type and, if so, + whether it should be passed by reference. + (aarch64_return_in_msb): Return false for pure scalable types. + (aarch64_function_value_1): Fold back into... + (aarch64_function_value): ...this function. Use + pure_scalable_type_info to analyze whether the type is a pure + scalable type and, if so, which registers it should use. Handle + types that include pure scalable types but are not themselves + pure scalable types. + (aarch64_return_in_memory_1): New function, split out from... + (aarch64_return_in_memory): ...here. Use pure_scalable_type_info + to analyze whether the type is a pure scalable type and, if so, + whether it should be returned by reference. + (aarch64_layout_arg): Remove orig_mode argument. Use + pure_scalable_type_info to analyze whether the type is a pure + scalable type and, if so, which registers it should use. Handle + types that include pure scalable types but are not themselves + pure scalable types. + (aarch64_function_arg): Update call accordingly. + (aarch64_function_arg_advance): Likewise. + (aarch64_pad_reg_upward): On big-endian targets, return false for + pure scalable types that are smaller than 16 bytes. + (aarch64_member_type_forces_blk): New function. + (aapcs_vfp_sub_candidate): Exit early for built-in SVE types. + (aarch64_short_vector_p): Return false for VECTOR_TYPEs that + correspond to built-in SVE types. Do not rely on a vector mode + if the type includes an pure scalable type. When returning true, + assert that the mode is not an SVE mode. + (aarch64_vfp_is_call_or_return_candidate): Do not check for SVE + built-in types here. When returning true, assert that the type + does not have an SVE mode. + (aarch64_can_change_mode_class): Don't allow anything to change + between a predicate mode and a non-predicate mode. Also don't + allow changes between SVE vector modes and other modes that + might be bigger than 128 bits. + (aarch64_invalid_binary_op): Reject binary operations that mix + SVE and GNU vector types. + (TARGET_MEMBER_TYPE_FORCES_BLK): Define. + +2020-04-09 Richard Sandiford + * config/aarch64/aarch64.c (aarch64_attribute_table): Add "SVE sizeless type". * config/aarch64/aarch64-sve-builtins.cc (make_type_sizeless) diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c index e7b4ed7..e1c1cd4 100644 --- a/gcc/config/aarch64/aarch64-c.c +++ b/gcc/config/aarch64/aarch64-c.c @@ -149,6 +149,8 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) bits = 0; builtin_define_with_int_value ("__ARM_FEATURE_SVE_BITS", bits); } + aarch64_def_or_undef (TARGET_SVE, "__ARM_FEATURE_SVE_VECTOR_OPERATIONS", + pfile); aarch64_def_or_undef (TARGET_SVE_I8MM, "__ARM_FEATURE_SVE_MATMUL_INT8", pfile); aarch64_def_or_undef (TARGET_SVE_F32MM, diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index d6d668e..9e43adb 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -716,6 +716,7 @@ namespace aarch64_sve { tree, unsigned int, tree *); gimple *gimple_fold_builtin (unsigned int, gimple_stmt_iterator *, gcall *); rtx expand_builtin (unsigned int, tree, rtx); + tree handle_arm_sve_vector_bits_attribute (tree *, tree, tree, int, bool *); #ifdef GCC_TARGET_H bool verify_type_context (location_t, type_context_kind, const_tree, bool); #endif diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index bcd60e9..ca4a0eb 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -602,6 +602,26 @@ sizeless_type_p (const_tree type) return lookup_attribute ("SVE sizeless type", TYPE_ATTRIBUTES (type)); } +/* Return true if CANDIDATE is equivalent to MODEL_TYPE for overloading + purposes. */ +static bool +matches_type_p (const_tree model_type, const_tree candidate) +{ + if (VECTOR_TYPE_P (model_type)) + { + if (!VECTOR_TYPE_P (candidate) + || maybe_ne (TYPE_VECTOR_SUBPARTS (model_type), + TYPE_VECTOR_SUBPARTS (candidate)) + || TYPE_MODE (model_type) != TYPE_MODE (candidate)) + return false; + + model_type = TREE_TYPE (model_type); + candidate = TREE_TYPE (candidate); + } + return (candidate != error_mark_node + && TYPE_MAIN_VARIANT (model_type) == TYPE_MAIN_VARIANT (candidate)); +} + /* If TYPE is a valid SVE element type, return the corresponding type suffix, otherwise return NUM_TYPE_SUFFIXES. */ static type_suffix_index @@ -609,12 +629,11 @@ find_type_suffix_for_scalar_type (const_tree type) { /* A linear search should be OK here, since the code isn't hot and the number of types is only small. */ - type = TYPE_MAIN_VARIANT (type); for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i) if (!type_suffixes[suffix_i].bool_p) { vector_type_index vector_i = type_suffixes[suffix_i].vector_type; - if (type == TYPE_MAIN_VARIANT (scalar_types[vector_i])) + if (matches_type_p (scalar_types[vector_i], type)) return type_suffix_index (suffix_i); } return NUM_TYPE_SUFFIXES; @@ -1273,7 +1292,7 @@ function_resolver::infer_vector_or_tuple_type (unsigned int argno, { vector_type_index type_i = type_suffixes[suffix_i].vector_type; tree type = acle_vector_types[size_i][type_i]; - if (type && TYPE_MAIN_VARIANT (actual) == TYPE_MAIN_VARIANT (type)) + if (type && matches_type_p (type, actual)) { if (size_i + 1 == num_vectors) return type_suffix_index (suffix_i); @@ -1411,8 +1430,7 @@ function_resolver::require_vector_type (unsigned int argno, { tree expected = acle_vector_types[0][type]; tree actual = get_argument_type (argno); - if (actual != error_mark_node - && TYPE_MAIN_VARIANT (expected) != TYPE_MAIN_VARIANT (actual)) + if (!matches_type_p (expected, actual)) { error_at (location, "passing %qT to argument %d of %qE, which" " expects %qT", actual, argno + 1, fndecl, expected); @@ -3592,6 +3610,61 @@ builtin_type_p (const_tree type, unsigned int *num_zr, unsigned int *num_pr) return false; } +/* An attribute callback for the "arm_sve_vector_bits" attribute. */ +tree +handle_arm_sve_vector_bits_attribute (tree *node, tree, tree args, int, + bool *no_add_attrs) +{ + *no_add_attrs = true; + + tree type = *node; + if (!VECTOR_TYPE_P (type) || !builtin_type_p (type)) + { + error ("%qs applied to non-SVE type %qT", "arm_sve_vector_bits", type); + return NULL_TREE; + } + + tree size = TREE_VALUE (args); + if (TREE_CODE (size) != INTEGER_CST) + { + error ("%qs requires an integer constant expression", + "arm_sve_vector_bits"); + return NULL_TREE; + } + + unsigned HOST_WIDE_INT value = tree_to_uhwi (size); + if (maybe_ne (value, BITS_PER_SVE_VECTOR)) + { + warning (OPT_Wattributes, "unsupported SVE vector size"); + return NULL_TREE; + } + + /* FIXME: The type ought to be a distinct copy in all cases, but + currently that makes the C frontend reject conversions between + svbool_t and its fixed-length variants. Using a type variant + avoids that but means that we treat some ambiguous combinations + as valid. */ + if (lang_GNU_C () && VECTOR_BOOLEAN_TYPE_P (type)) + type = build_variant_type_copy (type); + else + type = build_distinct_type_copy (type); + + /* The new type is a normal sized type; it doesn't have the same + restrictions as sizeless types. */ + TYPE_ATTRIBUTES (type) + = remove_attribute ("SVE sizeless type", + copy_list (TYPE_ATTRIBUTES (type))); + + /* Allow the GNU vector extensions to be applied to vectors. + The extensions aren't yet defined for packed predicates, + so continue to treat them as abstract entities for now. */ + if (!VECTOR_BOOLEAN_TYPE_P (type)) + TYPE_INDIVISIBLE_P (type) = 0; + + *node = type; + return NULL_TREE; +} + /* Implement TARGET_VERIFY_TYPE_CONTEXT for SVE types. */ bool verify_type_context (location_t loc, type_context_kind context, diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 0a46717..4af562a 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -174,6 +174,102 @@ inline simd_immediate_info u.pattern = pattern_in; } +namespace { + +/* Describes types that map to Pure Scalable Types (PSTs) in the AAPCS64. */ +class pure_scalable_type_info +{ +public: + /* Represents the result of analyzing a type. All values are nonzero, + in the possibly forlorn hope that accidental conversions to bool + trigger a warning. */ + enum analysis_result + { + /* The type does not have an ABI identity; i.e. it doesn't contain + at least one object whose type is a Fundamental Data Type. */ + NO_ABI_IDENTITY = 1, + + /* The type is definitely a Pure Scalable Type. */ + IS_PST, + + /* The type is definitely not a Pure Scalable Type. */ + ISNT_PST, + + /* It doesn't matter for PCS purposes whether the type is a Pure + Scalable Type or not, since the type will be handled the same + way regardless. + + Specifically, this means that if the type is a Pure Scalable Type, + there aren't enough argument registers to hold it, and so it will + need to be passed or returned in memory. If the type isn't a + Pure Scalable Type, it's too big to be passed or returned in core + or SIMD&FP registers, and so again will need to go in memory. */ + DOESNT_MATTER + }; + + /* Aggregates of 17 bytes or more are normally passed and returned + in memory, so aggregates of that size can safely be analyzed as + DOESNT_MATTER. We need to be able to collect enough pieces to + represent a PST that is smaller than that. Since predicates are + 2 bytes in size for -msve-vector-bits=128, that means we need to be + able to store at least 8 pieces. + + We also need to be able to store enough pieces to represent + a single vector in each vector argument register and a single + predicate in each predicate argument register. This means that + we need at least 12 pieces. */ + static const unsigned int MAX_PIECES = NUM_FP_ARG_REGS + NUM_PR_ARG_REGS; +#if __cplusplus >= 201103L + static_assert (MAX_PIECES >= 8, "Need to store at least 8 predicates"); +#endif + + /* Describes one piece of a PST. Each piece is one of: + + - a single Scalable Vector Type (SVT) + - a single Scalable Predicate Type (SPT) + - a PST containing 2, 3 or 4 SVTs, with no padding + + It either represents a single built-in type or a PST formed from + multiple homogeneous built-in types. */ + struct piece + { + rtx get_rtx (unsigned int, unsigned int) const; + + /* The number of vector and predicate registers that the piece + occupies. One of the two is always zero. */ + unsigned int num_zr; + unsigned int num_pr; + + /* The mode of the registers described above. */ + machine_mode mode; + + /* If this piece is formed from multiple homogeneous built-in types, + this is the mode of the built-in types, otherwise it is MODE. */ + machine_mode orig_mode; + + /* The offset in bytes of the piece from the start of the type. */ + poly_uint64_pod offset; + }; + + /* Divides types analyzed as IS_PST into individual pieces. The pieces + are in memory order. */ + auto_vec pieces; + + unsigned int num_zr () const; + unsigned int num_pr () const; + + rtx get_rtx (machine_mode mode, unsigned int, unsigned int) const; + + analysis_result analyze (const_tree); + bool analyze_registers (const_tree); + +private: + analysis_result analyze_array (const_tree); + analysis_result analyze_record (const_tree); + void add_piece (const piece &); +}; +} + /* The current code model. */ enum aarch64_code_model aarch64_cmodel; @@ -186,6 +282,7 @@ poly_uint16 aarch64_sve_vg; #endif static bool aarch64_composite_type_p (const_tree, machine_mode); +static bool aarch64_return_in_memory_1 (const_tree); static bool aarch64_vfp_is_call_or_return_candidate (machine_mode, const_tree, machine_mode *, int *, @@ -1246,6 +1343,9 @@ static const struct attribute_spec aarch64_attribute_table[] = affects_type_identity, handler, exclude } */ { "aarch64_vector_pcs", 0, 0, false, true, true, true, handle_aarch64_vector_pcs_attribute, NULL }, + { "arm_sve_vector_bits", 1, 1, false, true, false, true, + aarch64_sve::handle_arm_sve_vector_bits_attribute, + NULL }, { "SVE type", 3, 3, false, true, false, true, NULL, NULL }, { "SVE sizeless type", 0, 0, false, true, false, true, NULL, NULL }, { NULL, 0, 0, false, false, false, false, NULL, NULL } @@ -1396,6 +1496,287 @@ svpattern_token (enum aarch64_svpattern pattern) gcc_unreachable (); } +/* Return the location of a piece that is known to be passed or returned + in registers. FIRST_ZR is the first unused vector argument register + and FIRST_PR is the first unused predicate argument register. */ + +rtx +pure_scalable_type_info::piece::get_rtx (unsigned int first_zr, + unsigned int first_pr) const +{ + gcc_assert (VECTOR_MODE_P (mode) + && first_zr + num_zr <= V0_REGNUM + NUM_FP_ARG_REGS + && first_pr + num_pr <= P0_REGNUM + NUM_PR_ARG_REGS); + + if (num_zr > 0 && num_pr == 0) + return gen_rtx_REG (mode, first_zr); + + if (num_zr == 0 && num_pr == 1) + return gen_rtx_REG (mode, first_pr); + + gcc_unreachable (); +} + +/* Return the total number of vector registers required by the PST. */ + +unsigned int +pure_scalable_type_info::num_zr () const +{ + unsigned int res = 0; + for (unsigned int i = 0; i < pieces.length (); ++i) + res += pieces[i].num_zr; + return res; +} + +/* Return the total number of predicate registers required by the PST. */ + +unsigned int +pure_scalable_type_info::num_pr () const +{ + unsigned int res = 0; + for (unsigned int i = 0; i < pieces.length (); ++i) + res += pieces[i].num_pr; + return res; +} + +/* Return the location of a PST that is known to be passed or returned + in registers. FIRST_ZR is the first unused vector argument register + and FIRST_PR is the first unused predicate argument register. */ + +rtx +pure_scalable_type_info::get_rtx (machine_mode mode, + unsigned int first_zr, + unsigned int first_pr) const +{ + /* Try to return a single REG if possible. This leads to better + code generation; it isn't required for correctness. */ + if (mode == pieces[0].mode) + { + gcc_assert (pieces.length () == 1); + return pieces[0].get_rtx (first_zr, first_pr); + } + + /* Build up a PARALLEL that contains the individual pieces. */ + rtvec rtxes = rtvec_alloc (pieces.length ()); + for (unsigned int i = 0; i < pieces.length (); ++i) + { + rtx reg = pieces[i].get_rtx (first_zr, first_pr); + rtx offset = gen_int_mode (pieces[i].offset, Pmode); + RTVEC_ELT (rtxes, i) = gen_rtx_EXPR_LIST (VOIDmode, reg, offset); + first_zr += pieces[i].num_zr; + first_pr += pieces[i].num_pr; + } + return gen_rtx_PARALLEL (mode, rtxes); +} + +/* Analyze whether TYPE is a Pure Scalable Type according to the rules + in the AAPCS64. */ + +pure_scalable_type_info::analysis_result +pure_scalable_type_info::analyze (const_tree type) +{ + /* Prevent accidental reuse. */ + gcc_assert (pieces.is_empty ()); + + /* No code will be generated for erroneous types, so we won't establish + an ABI mapping. */ + if (type == error_mark_node) + return NO_ABI_IDENTITY; + + /* Zero-sized types disappear in the language->ABI mapping. */ + if (TYPE_SIZE (type) && integer_zerop (TYPE_SIZE (type))) + return NO_ABI_IDENTITY; + + /* Check for SVTs, SPTs, and built-in tuple types that map to PSTs. */ + piece p = {}; + if (aarch64_sve::builtin_type_p (type, &p.num_zr, &p.num_pr)) + { + machine_mode mode = TYPE_MODE_RAW (type); + gcc_assert (VECTOR_MODE_P (mode) + && (!TARGET_SVE || aarch64_sve_mode_p (mode))); + + p.mode = p.orig_mode = mode; + add_piece (p); + return IS_PST; + } + + /* Check for user-defined PSTs. */ + if (TREE_CODE (type) == ARRAY_TYPE) + return analyze_array (type); + if (TREE_CODE (type) == RECORD_TYPE) + return analyze_record (type); + + return ISNT_PST; +} + +/* Analyze a type that is known not to be passed or returned in memory. + Return true if it has an ABI identity and is a Pure Scalable Type. */ + +bool +pure_scalable_type_info::analyze_registers (const_tree type) +{ + analysis_result result = analyze (type); + gcc_assert (result != DOESNT_MATTER); + return result == IS_PST; +} + +/* Subroutine of analyze for handling ARRAY_TYPEs. */ + +pure_scalable_type_info::analysis_result +pure_scalable_type_info::analyze_array (const_tree type) +{ + /* Analyze the element type. */ + pure_scalable_type_info element_info; + analysis_result result = element_info.analyze (TREE_TYPE (type)); + if (result != IS_PST) + return result; + + /* An array of unknown, flexible or variable length will be passed and + returned by reference whatever we do. */ + tree nelts_minus_one = array_type_nelts (type); + if (!tree_fits_uhwi_p (nelts_minus_one)) + return DOESNT_MATTER; + + /* Likewise if the array is constant-sized but too big to be interesting. + The double checks against MAX_PIECES are to protect against overflow. */ + unsigned HOST_WIDE_INT count = tree_to_uhwi (nelts_minus_one); + if (count > MAX_PIECES) + return DOESNT_MATTER; + count += 1; + if (count * element_info.pieces.length () > MAX_PIECES) + return DOESNT_MATTER; + + /* The above checks should have weeded out elements of unknown size. */ + poly_uint64 element_bytes; + if (!poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (type)), &element_bytes)) + gcc_unreachable (); + + /* Build up the list of individual vectors and predicates. */ + gcc_assert (!element_info.pieces.is_empty ()); + for (unsigned int i = 0; i < count; ++i) + for (unsigned int j = 0; j < element_info.pieces.length (); ++j) + { + piece p = element_info.pieces[j]; + p.offset += i * element_bytes; + add_piece (p); + } + return IS_PST; +} + +/* Subroutine of analyze for handling RECORD_TYPEs. */ + +pure_scalable_type_info::analysis_result +pure_scalable_type_info::analyze_record (const_tree type) +{ + for (tree field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + + /* Zero-sized fields disappear in the language->ABI mapping. */ + if (DECL_SIZE (field) && integer_zerop (DECL_SIZE (field))) + continue; + + /* All fields with an ABI identity must be PSTs for the record as + a whole to be a PST. If any individual field is too big to be + interesting then the record is too. */ + pure_scalable_type_info field_info; + analysis_result subresult = field_info.analyze (TREE_TYPE (field)); + if (subresult == NO_ABI_IDENTITY) + continue; + if (subresult != IS_PST) + return subresult; + + /* Since all previous fields are PSTs, we ought to be able to track + the field offset using poly_ints. */ + tree bitpos = bit_position (field); + gcc_assert (poly_int_tree_p (bitpos)); + + /* For the same reason, it shouldn't be possible to create a PST field + whose offset isn't byte-aligned. */ + poly_widest_int wide_bytepos = exact_div (wi::to_poly_widest (bitpos), + BITS_PER_UNIT); + + /* Punt if the record is too big to be interesting. */ + poly_uint64 bytepos; + if (!wide_bytepos.to_uhwi (&bytepos) + || pieces.length () + field_info.pieces.length () > MAX_PIECES) + return DOESNT_MATTER; + + /* Add the individual vectors and predicates in the field to the + record's list. */ + gcc_assert (!field_info.pieces.is_empty ()); + for (unsigned int i = 0; i < field_info.pieces.length (); ++i) + { + piece p = field_info.pieces[i]; + p.offset += bytepos; + add_piece (p); + } + } + /* Empty structures disappear in the language->ABI mapping. */ + return pieces.is_empty () ? NO_ABI_IDENTITY : IS_PST; +} + +/* Add P to the list of pieces in the type. */ + +void +pure_scalable_type_info::add_piece (const piece &p) +{ + /* Try to fold the new piece into the previous one to form a + single-mode PST. For example, if we see three consecutive vectors + of the same mode, we can represent them using the corresponding + 3-tuple mode. + + This is purely an optimization. */ + if (!pieces.is_empty ()) + { + piece &prev = pieces.last (); + gcc_assert (VECTOR_MODE_P (p.mode) && VECTOR_MODE_P (prev.mode)); + unsigned int nelems1, nelems2; + if (prev.orig_mode == p.orig_mode + && known_eq (prev.offset + GET_MODE_SIZE (prev.mode), p.offset) + && constant_multiple_p (GET_MODE_NUNITS (prev.mode), + GET_MODE_NUNITS (p.orig_mode), &nelems1) + && constant_multiple_p (GET_MODE_NUNITS (p.mode), + GET_MODE_NUNITS (p.orig_mode), &nelems2) + && targetm.array_mode (p.orig_mode, + nelems1 + nelems2).exists (&prev.mode)) + { + prev.num_zr += p.num_zr; + prev.num_pr += p.num_pr; + return; + } + } + pieces.quick_push (p); +} + +/* Return true if at least one possible value of type TYPE includes at + least one object of Pure Scalable Type, in the sense of the AAPCS64. + + This is a relatively expensive test for some types, so it should + generally be made as late as possible. */ + +static bool +aarch64_some_values_include_pst_objects_p (const_tree type) +{ + if (TYPE_SIZE (type) && integer_zerop (TYPE_SIZE (type))) + return false; + + if (aarch64_sve::builtin_type_p (type)) + return true; + + if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == COMPLEX_TYPE) + return aarch64_some_values_include_pst_objects_p (TREE_TYPE (type)); + + if (RECORD_OR_UNION_TYPE_P (type)) + for (tree field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL + && aarch64_some_values_include_pst_objects_p (TREE_TYPE (field))) + return true; + + return false; +} + /* Return the descriptor of the SIMD ABI. */ static const predefined_function_abi & @@ -2045,11 +2426,6 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode) return false; } -/* Return true if TYPE is a type that should be passed or returned in - SVE registers, assuming enough registers are available. When returning - true, set *NUM_ZR and *NUM_PR to the number of required Z and P registers - respectively. */ - /* Return true if a function with type FNTYPE returns its value in SVE vector or predicate registers. */ @@ -2057,8 +2433,23 @@ static bool aarch64_returns_value_in_sve_regs_p (const_tree fntype) { tree return_type = TREE_TYPE (fntype); - return (return_type != error_mark_node - && aarch64_sve::builtin_type_p (return_type)); + + pure_scalable_type_info pst_info; + switch (pst_info.analyze (return_type)) + { + case pure_scalable_type_info::IS_PST: + return (pst_info.num_zr () <= NUM_FP_ARG_REGS + && pst_info.num_pr () <= NUM_PR_ARG_REGS); + + case pure_scalable_type_info::DOESNT_MATTER: + gcc_assert (aarch64_return_in_memory_1 (return_type)); + return false; + + case pure_scalable_type_info::NO_ABI_IDENTITY: + case pure_scalable_type_info::ISNT_PST: + return false; + } + gcc_unreachable (); } /* Return true if a function with type FNTYPE takes arguments in @@ -2082,8 +2473,14 @@ aarch64_takes_arguments_in_sve_regs_p (const_tree fntype) function_arg_info arg (arg_type, /*named=*/true); apply_pass_by_reference_rules (&args_so_far_v, arg); - if (aarch64_sve::builtin_type_p (arg.type)) - return true; + pure_scalable_type_info pst_info; + if (pst_info.analyze_registers (arg.type)) + { + unsigned int end_zr = args_so_far_v.aapcs_nvrn + pst_info.num_zr (); + unsigned int end_pr = args_so_far_v.aapcs_nprn + pst_info.num_pr (); + gcc_assert (end_zr <= NUM_FP_ARG_REGS && end_pr <= NUM_PR_ARG_REGS); + return true; + } targetm.calls.function_arg_advance (args_so_far, arg); } @@ -4884,33 +5281,16 @@ aarch64_function_ok_for_sibcall (tree, tree exp) return true; } -/* Implement TARGET_PASS_BY_REFERENCE. */ +/* Subroutine of aarch64_pass_by_reference for arguments that are not + passed in SVE registers. */ static bool -aarch64_pass_by_reference (cumulative_args_t pcum_v, - const function_arg_info &arg) +aarch64_pass_by_reference_1 (const function_arg_info &arg) { - CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); HOST_WIDE_INT size; machine_mode dummymode; int nregs; - unsigned int num_zr, num_pr; - if (arg.type && aarch64_sve::builtin_type_p (arg.type, &num_zr, &num_pr)) - { - if (pcum && !pcum->silent_p && !TARGET_SVE) - /* We can't gracefully recover at this point, so make this a - fatal error. */ - fatal_error (input_location, "arguments of type %qT require" - " the SVE ISA extension", arg.type); - - /* Variadic SVE types are passed by reference. Normal non-variadic - arguments are too if we've run out of registers. */ - return (!arg.named - || pcum->aapcs_nvrn + num_zr > NUM_FP_ARG_REGS - || pcum->aapcs_nprn + num_pr > NUM_PR_ARG_REGS); - } - /* GET_MODE_SIZE (BLKmode) is useless since it is 0. */ if (arg.mode == BLKmode && arg.type) size = int_size_in_bytes (arg.type); @@ -4939,6 +5319,44 @@ aarch64_pass_by_reference (cumulative_args_t pcum_v, return size > 2 * UNITS_PER_WORD; } +/* Implement TARGET_PASS_BY_REFERENCE. */ + +static bool +aarch64_pass_by_reference (cumulative_args_t pcum_v, + const function_arg_info &arg) +{ + CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); + + if (!arg.type) + return aarch64_pass_by_reference_1 (arg); + + pure_scalable_type_info pst_info; + switch (pst_info.analyze (arg.type)) + { + case pure_scalable_type_info::IS_PST: + if (pcum && !pcum->silent_p && !TARGET_SVE) + /* We can't gracefully recover at this point, so make this a + fatal error. */ + fatal_error (input_location, "arguments of type %qT require" + " the SVE ISA extension", arg.type); + + /* Variadic SVE types are passed by reference. Normal non-variadic + arguments are too if we've run out of registers. */ + return (!arg.named + || pcum->aapcs_nvrn + pst_info.num_zr () > NUM_FP_ARG_REGS + || pcum->aapcs_nprn + pst_info.num_pr () > NUM_PR_ARG_REGS); + + case pure_scalable_type_info::DOESNT_MATTER: + gcc_assert (aarch64_pass_by_reference_1 (arg)); + return true; + + case pure_scalable_type_info::NO_ABI_IDENTITY: + case pure_scalable_type_info::ISNT_PST: + return aarch64_pass_by_reference_1 (arg); + } + gcc_unreachable (); +} + /* Return TRUE if VALTYPE is padded to its least significant bits. */ static bool aarch64_return_in_msb (const_tree valtype) @@ -4965,37 +5383,36 @@ aarch64_return_in_msb (const_tree valtype) &dummy_mode, &dummy_int, NULL)) return false; + /* Likewise pure scalable types for SVE vector and predicate registers. */ + pure_scalable_type_info pst_info; + if (pst_info.analyze_registers (valtype)) + return false; + return true; } -/* Subroutine of aarch64_function_value. MODE is the mode of the argument - after promotion, and after partial SVE types have been replaced by - their integer equivalents. */ +/* Implement TARGET_FUNCTION_VALUE. + Define how to find the value returned by a function. */ + static rtx -aarch64_function_value_1 (const_tree type, machine_mode mode) +aarch64_function_value (const_tree type, const_tree func, + bool outgoing ATTRIBUTE_UNUSED) { - unsigned int num_zr, num_pr; - if (type && aarch64_sve::builtin_type_p (type, &num_zr, &num_pr)) - { - /* Don't raise an error here if we're called when SVE is disabled, - since this is really just a query function. Other code must - do that where appropriate. */ - mode = TYPE_MODE_RAW (type); - gcc_assert (VECTOR_MODE_P (mode) - && (!TARGET_SVE || aarch64_sve_mode_p (mode))); - - if (num_zr > 0 && num_pr == 0) - return gen_rtx_REG (mode, V0_REGNUM); + machine_mode mode; + int unsignedp; - if (num_zr == 0 && num_pr == 1) - return gen_rtx_REG (mode, P0_REGNUM); + mode = TYPE_MODE (type); + if (INTEGRAL_TYPE_P (type)) + mode = promote_function_mode (type, mode, &unsignedp, func, 1); - gcc_unreachable (); - } + pure_scalable_type_info pst_info; + if (type && pst_info.analyze_registers (type)) + return pst_info.get_rtx (mode, V0_REGNUM, P0_REGNUM); - /* Generic vectors that map to SVE modes with -msve-vector-bits=N are - returned in memory, not by value. */ - gcc_assert (!aarch64_sve_mode_p (mode)); + /* Generic vectors that map to full SVE modes with -msve-vector-bits=N + are returned in memory, not by value. */ + unsigned int vec_flags = aarch64_classify_vector_mode (mode); + bool sve_p = (vec_flags & VEC_ANY_SVE); if (aarch64_return_in_msb (type)) { @@ -5013,6 +5430,7 @@ aarch64_function_value_1 (const_tree type, machine_mode mode) if (aarch64_vfp_is_call_or_return_candidate (mode, type, &ag_mode, &count, NULL)) { + gcc_assert (!sve_p); if (!aarch64_composite_type_p (type, mode)) { gcc_assert (count == 1 && mode == ag_mode); @@ -5035,43 +5453,29 @@ aarch64_function_value_1 (const_tree type, machine_mode mode) } } else - return gen_rtx_REG (mode, R0_REGNUM); -} - -/* Implement TARGET_FUNCTION_VALUE. - Define how to find the value returned by a function. */ - -static rtx -aarch64_function_value (const_tree type, const_tree func, - bool outgoing ATTRIBUTE_UNUSED) -{ - machine_mode mode; - int unsignedp; - - mode = TYPE_MODE (type); - if (INTEGRAL_TYPE_P (type)) - mode = promote_function_mode (type, mode, &unsignedp, func, 1); - - /* Vector types can acquire a partial SVE mode using things like - __attribute__((vector_size(N))), and this is potentially useful. - However, the choice of mode doesn't affect the type's ABI identity, - so we should treat the types as though they had the associated - integer mode, just like they did before SVE was introduced. - - We know that the vector must be 128 bits or smaller, otherwise we'd - have returned it in memory instead. */ - unsigned int vec_flags = aarch64_classify_vector_mode (mode); - if ((vec_flags & VEC_ANY_SVE) && (vec_flags & VEC_PARTIAL)) { - scalar_int_mode int_mode = int_mode_for_mode (mode).require (); - rtx reg = aarch64_function_value_1 (type, int_mode); - /* Vector types are never returned in the MSB and are never split. */ - gcc_assert (REG_P (reg) && GET_MODE (reg) == int_mode); - rtx pair = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx); - return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, pair)); + if (sve_p) + { + /* Vector types can acquire a partial SVE mode using things like + __attribute__((vector_size(N))), and this is potentially useful. + However, the choice of mode doesn't affect the type's ABI + identity, so we should treat the types as though they had + the associated integer mode, just like they did before SVE + was introduced. + + We know that the vector must be 128 bits or smaller, + otherwise we'd have returned it in memory instead. */ + gcc_assert (type + && (aarch64_some_values_include_pst_objects_p (type) + || (vec_flags & VEC_PARTIAL))); + + scalar_int_mode int_mode = int_mode_for_mode (mode).require (); + rtx reg = gen_rtx_REG (int_mode, R0_REGNUM); + rtx pair = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx); + return gen_rtx_PARALLEL (mode, gen_rtvec (1, pair)); + } + return gen_rtx_REG (mode, R0_REGNUM); } - - return aarch64_function_value_1 (type, mode); } /* Implements TARGET_FUNCTION_VALUE_REGNO_P. @@ -5095,17 +5499,11 @@ aarch64_function_value_regno_p (const unsigned int regno) return false; } -/* Implement TARGET_RETURN_IN_MEMORY. - - If the type T of the result of a function is such that - void func (T arg) - would require that arg be passed as a value in a register (or set of - registers) according to the parameter passing rules, then the result - is returned in the same registers as would be used for such an - argument. */ +/* Subroutine for aarch64_return_in_memory for types that are not returned + in SVE registers. */ static bool -aarch64_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) +aarch64_return_in_memory_1 (const_tree type) { HOST_WIDE_INT size; machine_mode ag_mode; @@ -5117,16 +5515,6 @@ aarch64_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) /* Simple scalar types always returned in registers. */ return false; - unsigned int num_zr, num_pr; - if (type && aarch64_sve::builtin_type_p (type, &num_zr, &num_pr)) - { - /* All SVE types we support fit in registers. For example, it isn't - yet possible to define an aggregate of 9+ SVE vectors or 5+ SVE - predicates. */ - gcc_assert (num_zr <= NUM_FP_ARG_REGS && num_pr <= NUM_PR_ARG_REGS); - return false; - } - if (aarch64_vfp_is_call_or_return_candidate (TYPE_MODE (type), type, &ag_mode, @@ -5139,6 +5527,36 @@ aarch64_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) return (size < 0 || size > 2 * UNITS_PER_WORD); } +/* Implement TARGET_RETURN_IN_MEMORY. + + If the type T of the result of a function is such that + void func (T arg) + would require that arg be passed as a value in a register (or set of + registers) according to the parameter passing rules, then the result + is returned in the same registers as would be used for such an + argument. */ + +static bool +aarch64_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) +{ + pure_scalable_type_info pst_info; + switch (pst_info.analyze (type)) + { + case pure_scalable_type_info::IS_PST: + return (pst_info.num_zr () > NUM_FP_ARG_REGS + || pst_info.num_pr () > NUM_PR_ARG_REGS); + + case pure_scalable_type_info::DOESNT_MATTER: + gcc_assert (aarch64_return_in_memory_1 (type)); + return true; + + case pure_scalable_type_info::NO_ABI_IDENTITY: + case pure_scalable_type_info::ISNT_PST: + return aarch64_return_in_memory_1 (type); + } + gcc_unreachable (); +} + static bool aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode, const_tree type, int *nregs) @@ -5205,8 +5623,7 @@ aarch64_function_arg_alignment (machine_mode mode, const_tree type, the equivalent integer mode. */ static void -aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg, - machine_mode orig_mode) +aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) { CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); tree type = arg.type; @@ -5220,33 +5637,10 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg, if (pcum->aapcs_arg_processed) return; - /* Vector types can acquire a partial SVE mode using things like - __attribute__((vector_size(N))), and this is potentially useful. - However, the choice of mode doesn't affect the type's ABI identity, - so we should treat the types as though they had the associated - integer mode, just like they did before SVE was introduced. - - We know that the vector must be 128 bits or smaller, otherwise we'd - have passed it by reference instead. */ - unsigned int vec_flags = aarch64_classify_vector_mode (mode); - if ((vec_flags & VEC_ANY_SVE) && (vec_flags & VEC_PARTIAL)) - { - function_arg_info tmp_arg = arg; - tmp_arg.mode = int_mode_for_mode (mode).require (); - aarch64_layout_arg (pcum_v, tmp_arg, orig_mode); - if (rtx reg = pcum->aapcs_reg) - { - gcc_assert (REG_P (reg) && GET_MODE (reg) == tmp_arg.mode); - rtx pair = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx); - pcum->aapcs_reg = gen_rtx_PARALLEL (mode, gen_rtvec (1, pair)); - } - return; - } - pcum->aapcs_arg_processed = true; - unsigned int num_zr, num_pr; - if (type && aarch64_sve::builtin_type_p (type, &num_zr, &num_pr)) + pure_scalable_type_info pst_info; + if (type && pst_info.analyze_registers (type)) { /* The PCS says that it is invalid to pass an SVE value to an unprototyped function. There is no ABI-defined location we @@ -5264,26 +5658,34 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg, /* We would have converted the argument into pass-by-reference form if it didn't fit in registers. */ - pcum->aapcs_nextnvrn = pcum->aapcs_nvrn + num_zr; - pcum->aapcs_nextnprn = pcum->aapcs_nprn + num_pr; + pcum->aapcs_nextnvrn = pcum->aapcs_nvrn + pst_info.num_zr (); + pcum->aapcs_nextnprn = pcum->aapcs_nprn + pst_info.num_pr (); gcc_assert (arg.named && pcum->pcs_variant == ARM_PCS_SVE - && aarch64_sve_mode_p (mode) && pcum->aapcs_nextnvrn <= NUM_FP_ARG_REGS && pcum->aapcs_nextnprn <= NUM_PR_ARG_REGS); - - if (num_zr > 0 && num_pr == 0) - pcum->aapcs_reg = gen_rtx_REG (mode, V0_REGNUM + pcum->aapcs_nvrn); - else if (num_zr == 0 && num_pr == 1) - pcum->aapcs_reg = gen_rtx_REG (mode, P0_REGNUM + pcum->aapcs_nprn); - else - gcc_unreachable (); + pcum->aapcs_reg = pst_info.get_rtx (mode, V0_REGNUM + pcum->aapcs_nvrn, + P0_REGNUM + pcum->aapcs_nprn); return; } - /* Generic vectors that map to SVE modes with -msve-vector-bits=N are - passed by reference, not by value. */ - gcc_assert (!aarch64_sve_mode_p (mode)); + /* Generic vectors that map to full SVE modes with -msve-vector-bits=N + are passed by reference, not by value. */ + unsigned int vec_flags = aarch64_classify_vector_mode (mode); + bool sve_p = (vec_flags & VEC_ANY_SVE); + if (sve_p) + /* Vector types can acquire a partial SVE mode using things like + __attribute__((vector_size(N))), and this is potentially useful. + However, the choice of mode doesn't affect the type's ABI + identity, so we should treat the types as though they had + the associated integer mode, just like they did before SVE + was introduced. + + We know that the vector must be 128 bits or smaller, + otherwise we'd have passed it in memory instead. */ + gcc_assert (type + && (aarch64_some_values_include_pst_objects_p (type) + || (vec_flags & VEC_PARTIAL))); /* Size in bytes, rounded to the nearest multiple of 8 bytes. */ if (type) @@ -5299,6 +5701,7 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg, mode, type, &nregs); + gcc_assert (!sve_p || !allocate_nvrn); /* allocate_ncrn may be false-positive, but allocate_nvrn is quite reliable. The following code thus handles passing by SIMD/FP registers first. */ @@ -5364,7 +5767,7 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg, comparison is there because for > 16 * BITS_PER_UNIT alignment nregs should be > 2 and therefore it should be passed by reference rather than value. */ - && (aarch64_function_arg_alignment (orig_mode, type, &abi_break) + && (aarch64_function_arg_alignment (mode, type, &abi_break) == 16 * BITS_PER_UNIT)) { if (abi_break && warn_psabi && currently_expanding_gimple_stmt) @@ -5374,10 +5777,24 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg, gcc_assert (ncrn + nregs <= NUM_ARG_REGS); } + /* If an argument with an SVE mode needs to be shifted up to the + high part of the register, treat it as though it had an integer mode. + Using the normal (parallel [...]) would suppress the shifting. */ + if (sve_p + && BYTES_BIG_ENDIAN + && maybe_ne (GET_MODE_SIZE (mode), nregs * UNITS_PER_WORD) + && aarch64_pad_reg_upward (mode, type, false)) + { + mode = int_mode_for_mode (mode).require (); + sve_p = false; + } + /* NREGS can be 0 when e.g. an empty structure is to be passed. A reg is still generated for it, but the caller should be smart enough not to use it. */ - if (nregs == 0 || nregs == 1 || GET_MODE_CLASS (mode) == MODE_INT) + if (nregs == 0 + || (nregs == 1 && !sve_p) + || GET_MODE_CLASS (mode) == MODE_INT) pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn); else { @@ -5387,7 +5804,10 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg, par = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs)); for (i = 0; i < nregs; i++) { - rtx tmp = gen_rtx_REG (word_mode, R0_REGNUM + ncrn + i); + scalar_int_mode reg_mode = word_mode; + if (nregs == 1) + reg_mode = int_mode_for_mode (mode).require (); + rtx tmp = gen_rtx_REG (reg_mode, R0_REGNUM + ncrn + i); tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, GEN_INT (i * UNITS_PER_WORD)); XVECEXP (par, 0, i) = tmp; @@ -5407,7 +5827,7 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg, on_stack: pcum->aapcs_stack_words = size / UNITS_PER_WORD; - if (aarch64_function_arg_alignment (orig_mode, type, &abi_break) + if (aarch64_function_arg_alignment (mode, type, &abi_break) == 16 * BITS_PER_UNIT) { int new_size = ROUND_UP (pcum->aapcs_stack_size, 16 / UNITS_PER_WORD); @@ -5435,7 +5855,7 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg) if (arg.end_marker_p ()) return gen_int_mode (pcum->pcs_variant, DImode); - aarch64_layout_arg (pcum_v, arg, arg.mode); + aarch64_layout_arg (pcum_v, arg); return pcum->aapcs_reg; } @@ -5500,7 +5920,7 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v, || pcum->pcs_variant == ARM_PCS_SIMD || pcum->pcs_variant == ARM_PCS_SVE) { - aarch64_layout_arg (pcum_v, arg, arg.mode); + aarch64_layout_arg (pcum_v, arg); gcc_assert ((pcum->aapcs_reg != NULL_RTX) != (pcum->aapcs_stack_words != 0)); pcum->aapcs_arg_processed = false; @@ -5609,7 +6029,8 @@ aarch64_pad_reg_upward (machine_mode mode, const_tree type, bool first ATTRIBUTE_UNUSED) { - /* Small composite types are always padded upward. */ + /* Aside from pure scalable types, small composite types are always + padded upward. */ if (BYTES_BIG_ENDIAN && aarch64_composite_type_p (type, mode)) { HOST_WIDE_INT size; @@ -5620,7 +6041,12 @@ aarch64_pad_reg_upward (machine_mode mode, const_tree type, shouldn't be asked to pass or return them. */ size = GET_MODE_SIZE (mode).to_constant (); if (size < 2 * UNITS_PER_WORD) - return true; + { + pure_scalable_type_info pst_info; + if (pst_info.analyze_registers (type)) + return false; + return true; + } } /* Otherwise, use the default padding. */ @@ -15913,6 +16339,30 @@ aarch64_conditional_register_usage (void) } } +/* Implement TARGET_MEMBER_TYPE_FORCES_BLK. */ + +bool +aarch64_member_type_forces_blk (const_tree field_or_array, machine_mode mode) +{ + /* For records we're passed a FIELD_DECL, for arrays we're passed + an ARRAY_TYPE. In both cases we're interested in the TREE_TYPE. */ + const_tree type = TREE_TYPE (field_or_array); + + /* Assign BLKmode to anything that contains multiple SVE predicates. + For structures, the "multiple" case is indicated by MODE being + VOIDmode. */ + unsigned int num_zr, num_pr; + if (aarch64_sve::builtin_type_p (type, &num_zr, &num_pr) && num_pr != 0) + { + if (TREE_CODE (field_or_array) == ARRAY_TYPE) + return !simple_cst_equal (TYPE_SIZE (field_or_array), + TYPE_SIZE (type)); + return mode == VOIDmode; + } + + return default_member_type_forces_blk (field_or_array, mode); +} + /* Walk down the type tree of TYPE counting consecutive base elements. If *MODEP is VOIDmode, then set it to the first valid floating point type. If a non-floating point type is found, or if a floating point @@ -15924,9 +16374,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep) machine_mode mode; HOST_WIDE_INT size; - /* SVE types (and types containing SVE types) must be handled - before calling this function. */ - gcc_assert (!aarch64_sve::builtin_type_p (type)); + if (aarch64_sve::builtin_type_p (type)) + return -1; switch (TREE_CODE (type)) { @@ -16099,16 +16548,29 @@ aarch64_short_vector_p (const_tree type, { poly_int64 size = -1; - if (type && aarch64_sve::builtin_type_p (type)) - return false; - if (type && TREE_CODE (type) == VECTOR_TYPE) - size = int_size_in_bytes (type); + { + if (aarch64_sve::builtin_type_p (type)) + return false; + size = int_size_in_bytes (type); + } else if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT - || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) - size = GET_MODE_SIZE (mode); - - return known_eq (size, 8) || known_eq (size, 16); + || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) + { + /* Rely only on the type, not the mode, when processing SVE types. */ + if (type && aarch64_some_values_include_pst_objects_p (type)) + gcc_assert (aarch64_sve_mode_p (mode)); + else + size = GET_MODE_SIZE (mode); + } + if (known_eq (size, 8) || known_eq (size, 16)) + { + /* 64-bit and 128-bit vectors should only acquire an SVE mode if + they are being treated as scalable AAPCS64 types. */ + gcc_assert (!aarch64_sve_mode_p (mode)); + return true; + } + return false; } /* Return TRUE if the type, as described by TYPE and MODE, is a composite @@ -16164,9 +16626,6 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode, { if (is_ha != NULL) *is_ha = false; - if (type && aarch64_sve::builtin_type_p (type)) - return false; - machine_mode new_mode = VOIDmode; bool composite_p = aarch64_composite_type_p (type, mode); @@ -16197,6 +16656,7 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode, else return false; + gcc_assert (!aarch64_sve_mode_p (new_mode)); *base_mode = new_mode; return true; } @@ -21695,6 +22155,16 @@ aarch64_can_change_mode_class (machine_mode from, bool from_partial_sve_p = from_sve_p && (from_flags & VEC_PARTIAL); bool to_partial_sve_p = to_sve_p && (to_flags & VEC_PARTIAL); + bool from_pred_p = (from_flags & VEC_SVE_PRED); + bool to_pred_p = (to_flags & VEC_SVE_PRED); + + /* Don't allow changes between predicate modes and other modes. + Only predicate registers can hold predicate modes and only + non-predicate registers can hold non-predicate modes, so any + attempt to mix them would require a round trip through memory. */ + if (from_pred_p != to_pred_p) + return false; + /* Don't allow changes between partial SVE modes and other modes. The contents of partial SVE modes are distributed evenly across the register, whereas GCC expects them to be clustered together. */ @@ -21708,6 +22178,18 @@ aarch64_can_change_mode_class (machine_mode from, || GET_MODE_UNIT_SIZE (from) != GET_MODE_UNIT_SIZE (to))) return false; + if (maybe_ne (BITS_PER_SVE_VECTOR, 128u)) + { + /* Don't allow changes between SVE modes and other modes that might + be bigger than 128 bits. In particular, OImode, CImode and XImode + divide into 128-bit quantities while SVE modes divide into + BITS_PER_SVE_VECTOR quantities. */ + if (from_sve_p && !to_sve_p && maybe_gt (GET_MODE_BITSIZE (to), 128)) + return false; + if (to_sve_p && !from_sve_p && maybe_gt (GET_MODE_BITSIZE (from), 128)) + return false; + } + if (BYTES_BIG_ENDIAN) { /* Don't allow changes between SVE data modes and non-SVE modes. @@ -22003,6 +22485,14 @@ aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, || element_mode (type2) == BFmode) return N_("operation not permitted on type %"); + if (VECTOR_TYPE_P (type1) + && VECTOR_TYPE_P (type2) + && !TYPE_INDIVISIBLE_P (type1) + && !TYPE_INDIVISIBLE_P (type2) + && (aarch64_sve::builtin_type_p (type1) + != aarch64_sve::builtin_type_p (type2))) + return N_("cannot combine GNU and SVE vectors in a binary operation"); + /* Operation allowed. */ return NULL; } @@ -22167,6 +22657,9 @@ aarch64_run_selftests (void) #undef TARGET_CONDITIONAL_REGISTER_USAGE #define TARGET_CONDITIONAL_REGISTER_USAGE aarch64_conditional_register_usage +#undef TARGET_MEMBER_TYPE_FORCES_BLK +#define TARGET_MEMBER_TYPE_FORCES_BLK aarch64_member_type_forces_blk + /* Only the least significant bit is used for initialization guard variables. */ #undef TARGET_CXX_GUARD_MASK_BIT diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 0bccae8..de28227 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1992,6 +1992,15 @@ AArch64 target which generates instruction sequences for big endian. @item aarch64_small_fpic Binutils installed on test system supports relocation types required by -fpic for AArch64 small memory model. +@item aarch64_sve_hw +AArch64 target that is able to generate and execute SVE code (regardless of +whether it does so by default). +@item aarch64_sve128_hw +@itemx aarch64_sve256_hw +@itemx aarch64_sve512_hw +@itemx aarch64_sve1024_hw +@itemx aarch64_sve2048_hw +Like @code{aarch64_sve_hw}, but also test for an exact hardware vector length. @end table diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d79c4db..8c44253 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,31 @@ +2020-04-09 Richard Sandiford + + * gcc.target/aarch64/sve/acle/general/attributes_1.c: New test. + * gcc.target/aarch64/sve/acle/general/attributes_2.c: Likewise. + * gcc.target/aarch64/sve/acle/general/attributes_3.c: Likewise. + * gcc.target/aarch64/sve/acle/general/attributes_4.c: Likewise. + * gcc.target/aarch64/sve/acle/general/attributes_5.c: Likewise. + * gcc.target/aarch64/sve/acle/general/attributes_6.c: Likewise. + * gcc.target/aarch64/sve/acle/general/attributes_7.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct.h: New file. + * gcc.target/aarch64/sve/pcs/struct_1_128.c: New test. + * gcc.target/aarch64/sve/pcs/struct_1_256.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_1_512.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_1_1024.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_1_2048.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_2_128.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_2_256.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_2_512.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_2_1024.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_2_2048.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_3_128.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_3_256.c: Likewise. + * gcc.target/aarch64/sve/pcs/struct_3_512.c: Likewise. + * lib/target-supports.exp (check_effective_target_aarch64_sve128_hw) + (check_effective_target_aarch64_sve512_hw) + (check_effective_target_aarch64_sve1024_hw) + (check_effective_target_aarch64_sve2048_hw): New procedures. + 2020-04-09 Matthew Malcomson * g++.target/arm/cde_mve.C: New test. diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_1.c new file mode 100644 index 0000000..6cd4f99 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_1.c @@ -0,0 +1,205 @@ +/* { dg-options "-msve-vector-bits=256" } */ + +#include + +#ifndef __ARM_FEATURE_SVE_BITS +#error "__ARM_FEATURE_SVE_BITS is not defined but should be" +#endif + +#if __ARM_FEATURE_SVE_VECTOR_OPERATIONS != 1 +#error "__ARM_FEATURE_SVE_VECTOR_OPERATIONS should be equal to 1" +#endif + +#ifndef __cplusplus +#define alignof _Alignof +#endif + +#define N __ARM_FEATURE_SVE_BITS +#define FIXED_ATTR __attribute__ ((arm_sve_vector_bits (N))) +#define GNU_ATTR __attribute__ ((vector_size (N / 8))) + +typedef svint8_t fixed_int8_t FIXED_ATTR; +typedef svint16_t fixed_int16_t FIXED_ATTR; +typedef svint32_t fixed_int32_t FIXED_ATTR; +typedef svint64_t fixed_int64_t FIXED_ATTR; + +typedef svuint8_t fixed_uint8_t FIXED_ATTR; +typedef svuint16_t fixed_uint16_t FIXED_ATTR; +typedef svuint32_t fixed_uint32_t FIXED_ATTR; +typedef svuint64_t fixed_uint64_t FIXED_ATTR; + +typedef svbfloat16_t fixed_bfloat16_t FIXED_ATTR; +typedef svfloat16_t fixed_float16_t FIXED_ATTR; +typedef svfloat32_t fixed_float32_t FIXED_ATTR; +typedef svfloat64_t fixed_float64_t FIXED_ATTR; + +typedef svbool_t fixed_bool_t FIXED_ATTR; + +typedef int8_t gnu_int8_t GNU_ATTR; +typedef int16_t gnu_int16_t GNU_ATTR; +typedef int32_t gnu_int32_t GNU_ATTR; +typedef int64_t gnu_int64_t GNU_ATTR; + +typedef uint8_t gnu_uint8_t GNU_ATTR; +typedef uint16_t gnu_uint16_t GNU_ATTR; +typedef uint32_t gnu_uint32_t GNU_ATTR; +typedef uint64_t gnu_uint64_t GNU_ATTR; + +typedef bfloat16_t gnu_bfloat16_t GNU_ATTR; +typedef float16_t gnu_float16_t GNU_ATTR; +typedef float32_t gnu_float32_t GNU_ATTR; +typedef float64_t gnu_float64_t GNU_ATTR; + +void f() { +#define TEST_VECTOR(TYPE) \ + do \ + { \ + int assert_sizeof[sizeof (TYPE) == N / 8 ? 1 : -1]; \ + int assert_alignof[alignof (TYPE) == 16 ? 1 : -1]; \ + } \ + while (0) + + TEST_VECTOR (fixed_int8_t); + TEST_VECTOR (fixed_int16_t); + TEST_VECTOR (fixed_int32_t); + TEST_VECTOR (fixed_int64_t); + + TEST_VECTOR (fixed_uint8_t); + TEST_VECTOR (fixed_uint16_t); + TEST_VECTOR (fixed_uint32_t); + TEST_VECTOR (fixed_uint64_t); + + TEST_VECTOR (fixed_bfloat16_t); + TEST_VECTOR (fixed_float16_t); + TEST_VECTOR (fixed_float32_t); + TEST_VECTOR (fixed_float64_t); + +#undef TEST_VECTOR + + { + int assert_sizeof[sizeof(fixed_bool_t) == N / 64 ? 1 : -1]; + int assert_alignof[alignof(fixed_bool_t) == 2 ? 1 : -1]; + } +} + +#define TEST_GLOBAL(TYPE) \ + extern fixed_##TYPE extern_##TYPE; \ + fixed_##TYPE global_##TYPE; + +#define TEST_STRUCT(TYPE) \ + struct struct_##TYPE \ + { \ + fixed_##TYPE a, b, c[3]; \ + }; \ + \ + union union_##TYPE \ + { \ + fixed_##TYPE a, b, c[3]; \ + }; + +#define TEST_CONVERT(TYPE, PREFIX) \ + PREFIX##TYPE \ + to_##PREFIX##TYPE (fixed_##TYPE x) \ + { \ + return x; \ + } \ + \ + fixed_##TYPE \ + from_##PREFIX##TYPE (PREFIX##TYPE x) \ + { \ + return x; \ + } + +#define TEST_UNARY(TYPE, NAME, OP) \ + fixed_##TYPE \ + NAME##_##TYPE (fixed_##TYPE x) \ + { \ + return OP x; \ + } + +#define TEST_BINARY(TYPE, NAME, OP) \ + fixed_##TYPE \ + NAME##_##TYPE (fixed_##TYPE x, fixed_##TYPE y) \ + { \ + return x OP y; \ + } \ + \ + fixed_##TYPE \ + NAME##_##TYPE##_eq (fixed_##TYPE x, fixed_##TYPE y) \ + { \ + x OP##= y; return x; \ + } + +#define TEST_COMPARISON(TYPE, NAME, OP) \ + fixed_##TYPE \ + NAME##_##TYPE (fixed_##TYPE x, fixed_##TYPE y) \ + { \ + return x OP y; \ + } + +#define TEST_CALL(TYPE) \ + fixed_##TYPE \ + call_##TYPE##_ff (svbool_t pg, fixed_##TYPE x, fixed_##TYPE y) \ + { \ + return svsel (pg, x, y); \ + } \ + \ + fixed_##TYPE \ + call_##TYPE##_sf (svbool_t pg, sv##TYPE x, fixed_##TYPE y) \ + { \ + return svsel (pg, x, y); \ + } \ + \ + fixed_##TYPE \ + call_##TYPE##_fs (svbool_t pg, fixed_##TYPE x, sv##TYPE y) \ + { \ + return svsel (pg, x, y); \ + } + +#define TEST_COMMON(TYPE) \ + TEST_GLOBAL (TYPE) \ + TEST_STRUCT (TYPE) \ + TEST_CONVERT (TYPE, sv) \ + TEST_CALL (TYPE) + +#define TEST_VECTOR(TYPE) \ + TEST_COMMON (TYPE) \ + TEST_CONVERT (TYPE, gnu_) \ + TEST_UNARY (TYPE, nop, +) \ + TEST_UNARY (TYPE, neg, -) \ + TEST_BINARY (TYPE, add, +) \ + TEST_BINARY (TYPE, sub, -) \ + TEST_BINARY (TYPE, mul, *) \ + TEST_BINARY (TYPE, div, /) \ + +#define TEST_INT_VECTOR(TYPE) \ + TEST_VECTOR (TYPE) \ + TEST_UNARY (TYPE, inv, ~) \ + TEST_BINARY (TYPE, mod, %) \ + TEST_BINARY (TYPE, shl, <<) \ + TEST_BINARY (TYPE, shr, >>) \ + TEST_BINARY (TYPE, and, &) \ + TEST_BINARY (TYPE, ior, |) \ + TEST_BINARY (TYPE, xor, ^) \ + TEST_COMPARISON (TYPE, eq, =) \ + TEST_COMPARISON (TYPE, ne, !=) \ + TEST_COMPARISON (TYPE, lt, <) \ + TEST_COMPARISON (TYPE, le, <=) \ + TEST_COMPARISON (TYPE, ge, >=) \ + TEST_COMPARISON (TYPE, gt, >) + +TEST_INT_VECTOR (int8_t); +TEST_INT_VECTOR (int16_t); +TEST_INT_VECTOR (int32_t); +TEST_INT_VECTOR (int64_t); + +TEST_INT_VECTOR (uint8_t); +TEST_INT_VECTOR (uint16_t); +TEST_INT_VECTOR (uint32_t); +TEST_INT_VECTOR (uint64_t); + +TEST_VECTOR (float16_t); +TEST_VECTOR (float32_t); +TEST_VECTOR (float64_t); + +TEST_COMMON (bool_t) diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_2.c new file mode 100644 index 0000000..798491b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_2.c @@ -0,0 +1,3 @@ +/* { dg-options "-msve-vector-bits=512" } */ + +#include "attributes_1.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_3.c new file mode 100644 index 0000000..c3ba562 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_3.c @@ -0,0 +1,3 @@ +/* { dg-options "-msve-vector-bits=1024" } */ + +#include "attributes_1.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_4.c new file mode 100644 index 0000000..487dba6 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_4.c @@ -0,0 +1,3 @@ +/* { dg-options "-msve-vector-bits=2048" } */ + +#include "attributes_1.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_5.c new file mode 100644 index 0000000..c7951c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_5.c @@ -0,0 +1,7 @@ +/* { dg-options "-msve-vector-bits=128" } */ + +#if __ARM_BIG_ENDIAN && !__ARM_FEATURE_SVE_BITS +int pass = 1; +#else +#include "attributes_1.c" +#endif diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_6.c new file mode 100644 index 0000000..907637f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_6.c @@ -0,0 +1,97 @@ +/* { dg-options "-O2 -msve-vector-bits=256" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include + +#define N __ARM_FEATURE_SVE_BITS +#define FIXED_ATTR __attribute__ ((arm_sve_vector_bits (N))) +#define GNU_ATTR __attribute__ ((vector_size (N / 8))) + +typedef svint8_t fixed_int8_t FIXED_ATTR; + +typedef svbool_t fixed_bool_t FIXED_ATTR; + +typedef int8_t gnu_int8_t GNU_ATTR; + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** test_add: +** add z0\.b, (?:z0\.b, z1\.b|z1\.b, z0\.b) +** ret +*/ +fixed_int8_t +test_add (fixed_int8_t x, fixed_int8_t y) +{ + return x + y; +} + +/* +** test_add_gnu: +** ( +** add (z[0-9]+\.b), (?:z0\.b, z1\.b|z1\.b, z0\.b) +** ptrue (p[0-7])\.b, vl32 +** st1b \1, \2, \[x8\] +** | +** ptrue (p[0-7]\.b), vl32 +** add (z[0-9]+)\.b, (?:z0\.b, z1\.b|z1\.b, z0\.b) +** st1b \4, \3, \[x8\] +** ) +** ret +*/ +gnu_int8_t +test_add_gnu (fixed_int8_t x, fixed_int8_t y) +{ + return x + y; +} + +/* +** test_load: { target lp64 } +** ld1b z0\.b, p0/z, \[x0\] +** ret +*/ +/* +** test_load: { target ilp32 } +** uxtw x0, w0 +** ld1b z0\.b, p0/z, \[x0\] +** ret +*/ +fixed_int8_t +test_load (fixed_bool_t pg, int8_t *ptr) +{ + return svld1 (pg, ptr); +} + +/* +** test_store: { target lp64 } +** st1b z0\.b, p0, \[x0\] +** ret +*/ +/* +** test_store: { target ilp32 } +** uxtw x0, w0 +** st1b z0\.b, p0, \[x0\] +** ret +*/ +void +test_store (fixed_bool_t pg, int8_t *ptr, fixed_int8_t data) +{ + svst1 (pg, ptr, data); +} + +/* +** test_and_z: +** and p0\.b, p0/z, p1\.b, p2\.b +** ret +*/ +fixed_bool_t +test_and_z (fixed_bool_t pg, svbool_t p1, fixed_bool_t p2) +{ + return svand_z (pg, p1, p2); +} + +#ifdef __cplusplus +} +#endif diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c new file mode 100644 index 0000000..55d9dea --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_7.c @@ -0,0 +1,181 @@ +/* { dg-options "-msve-vector-bits=256 -W -Wall" } */ + +#include + +#define N __ARM_FEATURE_SVE_BITS +#define FIXED_ATTR __attribute__ ((arm_sve_vector_bits (N))) +#define GNU_ATTR __attribute__ ((vector_size (N / 8))) + +typedef svint8_t fixed_int8_t FIXED_ATTR; +typedef svint16_t fixed_int16_t FIXED_ATTR; + +typedef svuint8_t fixed_uint8_t FIXED_ATTR; + +typedef svbool_t fixed_bool_t FIXED_ATTR; + +typedef int8_t gnu_int8_t GNU_ATTR; +typedef int16_t gnu_int16_t GNU_ATTR; + +typedef uint8_t gnu_uint8_t GNU_ATTR; + +typedef int bad_type_1 __attribute__ ((arm_sve_vector_bits (N))); // { dg-error {'arm_sve_vector_bits' applied to non-SVE type 'int'} } +typedef svbool_t bad_type_2 __attribute__ ((arm_sve_vector_bits)); // { dg-error {wrong number of arguments specified for 'arm_sve_vector_bits' attribute} } +typedef svbool_t bad_type_3 __attribute__ ((arm_sve_vector_bits (N, N))); // { dg-error {wrong number of arguments specified for 'arm_sve_vector_bits' attribute} } +typedef svbool_t bad_type_4 __attribute__ ((arm_sve_vector_bits ("256"))); // { dg-error {'arm_sve_vector_bits' requires an integer constant expression} } +typedef svbool_t bad_type_5 __attribute__ ((arm_sve_vector_bits (100))); // { dg-warning {unsupported SVE vector size} } + +void +f (int c) +{ + svint8_t ss8; + fixed_int8_t fs8; + gnu_int8_t gs8; + + svuint8_t su8; + fixed_uint8_t fu8; + gnu_uint8_t gu8; + + svint16_t ss16; + fixed_int16_t fs16; + gnu_int16_t gs16; + + svbool_t sb; + fixed_bool_t fb; + + ss8 = ss8 + ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + ss8 = ss8 + fs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + ss8 = ss8 + gs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + ss8 += ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + ss8 += fs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + ss8 += gs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + + fs8 = fs8 + ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + fs8 = fs8 + fs8; + fs8 = fs8 + gs8; // { dg-error {cannot combine GNU and SVE vectors in a binary operation} } + fs8 += ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + fs8 += fs8; + fs8 += gs8; // { dg-error {cannot combine GNU and SVE vectors in a binary operation} } + + gs8 = gs8 + ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + gs8 = gs8 + fs8; // { dg-error {cannot combine GNU and SVE vectors in a binary operation} } + gs8 = gs8 + gs8; + gs8 += ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\+} } + gs8 += fs8; // { dg-error {cannot combine GNU and SVE vectors in a binary operation} } + gs8 += gs8; + + fs8 = ss8; + fs8 = fs8; + fs8 = gs8; + + fs8 = su8; // { dg-error {cannot convert|incompatible types} } + fs8 = fu8; // { dg-error {cannot convert|incompatible types} } + fs8 = gu8; // { dg-error {cannot convert|incompatible types} } + + fs8 = ss16; // { dg-error {cannot convert|incompatible types} } + fs8 = fs16; // { dg-error {cannot convert|incompatible types} } + fs8 = gs16; // { dg-error {cannot convert|incompatible types} } + + (void) (c ? ss8 : ss8); + (void) (c ? ss8 : fs8); // { dg-error {type mismatch|different types} } + (void) (c ? ss8 : gs8); // { dg-error {type mismatch|different types} } + + (void) (c ? fs8 : ss8); // { dg-error {type mismatch|different types} } + (void) (c ? fs8 : fs8); + (void) (c ? fs8 : gs8); // { dg-error {type mismatch|different types} "" { xfail c++ } } + + (void) (c ? gs8 : ss8); // { dg-error {type mismatch|different types} } + (void) (c ? gs8 : fs8); // { dg-error {type mismatch|different types} "" { xfail c++ } } + (void) (c ? gs8 : gs8); + + sb = fb; + fb = sb; + + (void) (c ? sb : sb); + (void) (c ? sb : fb); // { dg-error {type mismatch|different types} "" { xfail *-*-* } } + + (void) (c ? fb : sb); // { dg-error {type mismatch|different types} "" { xfail *-*-* } } + (void) (c ? fb : fb); +} + +void +g (int c) +{ + svint8_t *ss8; + fixed_int8_t *fs8; + gnu_int8_t *gs8; + + svuint8_t *su8; + fixed_uint8_t *fu8; + gnu_uint8_t *gu8; + + svint16_t *ss16; + fixed_int16_t *fs16; + gnu_int16_t *gs16; + + svbool_t *sb; + fixed_bool_t *fb; + + __PTRDIFF_TYPE__ diff __attribute__((unused)); + void *select __attribute__((unused)); + + diff = ss8 - ss8; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } + diff = ss8 - fs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" { xfail c } } + // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} "bogus" { target c } .-1 } + diff = ss8 - gs8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" { xfail c } } + // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} "bogus" { target c } .-1 } + + diff = fs8 - ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" { xfail c } } + // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} "bogus" { target c } .-1 } + diff = fs8 - fs8; + diff = fs8 - gs8; + + diff = gs8 - ss8; // { dg-error {invalid operands [^\n]* binary[^\n]*\-} "" { xfail c } } + // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} "bogus" { target c } .-1 } + diff = gs8 - fs8; + diff = gs8 - gs8; + + fs8 = ss8; // { dg-error {invalid conversion} "" { xfail c } } + fs8 = fs8; + fs8 = gs8; + + fs8 = su8; // { dg-error {cannot convert} "c++" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + fs8 = fu8; // { dg-error {cannot convert} "c++" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + fs8 = gu8; // { dg-error {cannot convert} "c++" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + + fs8 = ss16; // { dg-error {cannot convert} "c++" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + fs8 = fs16; // { dg-error {cannot convert} "c++" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + fs8 = gs16; // { dg-error {cannot convert} "c++" { target c++ } } + // { dg-warning {incompatible pointer type} "c" { target c } .-1 } + + select = c ? ss8 : ss8; + select = c ? ss8 : fs8; // { dg-error {distinct pointer types} "" { xfail c } } + select = c ? ss8 : gs8; // { dg-error {distinct pointer types} "" { xfail c } } + + select = c ? fs8 : ss8; // { dg-error {distinct pointer types} "" { xfail c } } + select = c ? fs8 : fs8; + select = c ? fs8 : gs8; // { dg-error {distinct pointer types} "" { xfail *-*-* } } + + select = c ? gs8 : ss8; // { dg-error {distinct pointer types} "" { xfail c } } + select = c ? gs8 : fs8; // { dg-error {distinct pointer types} "" { xfail *-*-* } } + select = c ? gs8 : gs8; + + diff = sb - sb; // { dg-error {arithmetic on pointer to SVE type 'svbool_t'} } + diff = sb - fb; // { dg-error {arithmetic on pointer to SVE type 'svbool_t'} } + + diff = fb - sb; // { dg-error {arithmetic on pointer to SVE type 'svbool_t'} } + diff = fb - fb; + + sb = fb; + fb = sb; + + select = c ? sb : sb; + select = c ? sb : fb; // { dg-error {type mismatch|different types} "" { xfail *-*-* } } + + select = c ? fb : sb; // { dg-error {type mismatch|different types} "" { xfail *-*-* } } + select = c ? fb : fb; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct.h b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct.h new file mode 100644 index 0000000..45fa330 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct.h @@ -0,0 +1,77 @@ +#ifndef STRUCT_H +#define STRUCT_H 1 + +#include + +#ifndef __ARM_FEATURE_SVE_BITS +#error "__ARM_FEATURE_SVE_BITS should be defined" +#endif + +#define FIXED_ATTR \ + __attribute__ ((arm_sve_vector_bits (__ARM_FEATURE_SVE_BITS))) + +#define SVE_BYTES (__ARM_FEATURE_SVE_BITS / 8) + +typedef __SVInt8_t fixed_int8_t FIXED_ATTR; +typedef __SVInt16_t fixed_int16_t FIXED_ATTR; +typedef __SVInt32_t fixed_int32_t FIXED_ATTR; +typedef __SVInt64_t fixed_int64_t FIXED_ATTR; + +typedef __SVUint8_t fixed_uint8_t FIXED_ATTR; +typedef __SVUint16_t fixed_uint16_t FIXED_ATTR; +typedef __SVUint32_t fixed_uint32_t FIXED_ATTR; +typedef __SVUint64_t fixed_uint64_t FIXED_ATTR; + +typedef __SVBfloat16_t fixed_bfloat16_t FIXED_ATTR; +typedef __SVFloat16_t fixed_float16_t FIXED_ATTR; +typedef __SVFloat32_t fixed_float32_t FIXED_ATTR; +typedef __SVFloat64_t fixed_float64_t FIXED_ATTR; + +typedef __SVBool_t fixed_bool_t FIXED_ATTR; + +/* Define an asm function called NAME with return type RET_TYPE and + argument list ARG_TYPES. INSNS contains the body of the function, + except for the final "ret". + + Conservatively mark the function as a variant PCS function, + since many uses are. */ +#define ASM_FUNCTION(NAME, RET_TYPE, ARG_TYPES, INSNS) \ +extern RET_TYPE NAME ARG_TYPES; \ + asm( \ +" .type " #NAME ", %function\n" \ +#NAME ":\n" \ +" " INSNS "\n" \ +" ret\n" \ +" .size " #NAME ", .-" #NAME "\n" \ +" .variant_pcs " #NAME "\n" \ +) + +/* Set the argument registers to fixed values. */ +#define CLEANSE \ + asm volatile ("mov\tx0, #-1\n\t" \ + "mov\tx1, #-1\n\t" \ + "mov\tx2, #-1\n\t" \ + "mov\tx3, #-1\n\t" \ + "mov\tx4, #-1\n\t" \ + "mov\tx5, #-1\n\t" \ + "mov\tx6, #-1\n\t" \ + "mov\tx7, #-1\n\t" \ + "mov\tx8, #-1\n\t" \ + "mov\tz0.b, #0xaf\n\t" \ + "mov\tz1.b, #0xaf\n\t" \ + "mov\tz2.b, #0xaf\n\t" \ + "mov\tz3.b, #0xaf\n\t" \ + "mov\tz4.b, #0xaf\n\t" \ + "mov\tz5.b, #0xaf\n\t" \ + "mov\tz6.b, #0xaf\n\t" \ + "mov\tz7.b, #0xaf\n\t" \ + "pfalse\tp0.b\n\t" \ + "pfalse\tp1.b\n\t" \ + "pfalse\tp2.b\n\t" \ + "pfalse\tp3.b" \ + ::: \ + "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", \ + "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", \ + "p0", "p1", "p2", "p3") + +#endif diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_1024.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_1024.c new file mode 100644 index 0000000..3a4b1b2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_1024.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { aarch64_sve1024_hw } } } */ +/* { dg-options "-msve-vector-bits=1024" } */ + +#include "struct_1_128.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_128.c new file mode 100644 index 0000000..a7e4700 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_128.c @@ -0,0 +1,405 @@ +/* { dg-do run { target { aarch64_sve128_hw } } } */ +/* { dg-require-effective-target aarch64_little_endian } */ +/* { dg-options "-msve-vector-bits=128" } */ + +#include "struct.h" + +struct pst1 +{ + fixed_int8_t v[8]; + fixed_bool_t p[4]; +}; + +ASM_FUNCTION (make_pst1_asm, struct pst1, (), + "mov z0.b, #1\n\t" + "mov z1.b, #4\n\t" + "mov z2.b, #5\n\t" + "mov z3.b, #9\n\t" + "mov z4.b, #14\n\t" + "mov z5.b, #23\n\t" + "mov z6.b, #37\n\t" + "mov z7.b, #60\n\t" + "ptrue p0.b, vl1\n\t" + "ptrue p1.b, vl2\n\t" + "ptrue p2.b, vl3\n\t" + "ptrue p3.b, vl4"); + +#define LOAD_PST1(PTR) \ + "ld1b z0.b, p0/z, [" PTR ", #0, mul vl]\n\t" \ + "ld1b z1.b, p0/z, [" PTR ", #1, mul vl]\n\t" \ + "ld1b z2.b, p0/z, [" PTR ", #2, mul vl]\n\t" \ + "ld1b z3.b, p0/z, [" PTR ", #3, mul vl]\n\t" \ + "ld1b z4.b, p0/z, [" PTR ", #4, mul vl]\n\t" \ + "ld1b z5.b, p0/z, [" PTR ", #5, mul vl]\n\t" \ + "ld1b z6.b, p0/z, [" PTR ", #6, mul vl]\n\t" \ + "ld1b z7.b, p0/z, [" PTR ", #7, mul vl]\n\t" \ + "incb " PTR ", all, mul #8\n\t" \ + "ldr p0, [" PTR ", #0, mul vl]\n\t" \ + "ldr p1, [" PTR ", #1, mul vl]\n\t" \ + "ldr p2, [" PTR ", #2, mul vl]\n\t" \ + "ldr p3, [" PTR ", #3, mul vl]" + +ASM_FUNCTION (passthru_pst1_x0_a, + struct pst1, (svbool_t, struct pst1), + "incp x0, p0.b\n\t" + "sub x0, x0, #11\n\t" + "ptrue p0.b\n\t" + LOAD_PST1 ("x0")); + +ASM_FUNCTION (passthru_pst1_x0_b, + struct pst1, (svbool_t, struct pst1, uint64_t), + "incp x0, p0.b\n\t" + "add x0, x0, x1\n\t" + "sub x0, x0, #52\n\t" + "ptrue p0.b\n\t" + LOAD_PST1 ("x0")); + +ASM_FUNCTION (passthru_pst1_x0_c, + struct pst1, (svbool_t, struct pst1, svbool_t, + svbool_t, svbool_t, svbool_t), + "incp x0, p0.b\n\t" + "ldr p0, [x1]\n\t" + "incp x0, p1.b\n\t" + "incp x0, p2.b\n\t" + "incp x0, p3.b\n\t" + "incp x0, p0.b\n\t" + "sub x0, x0, #27\n\t" + "ptrue p0.b\n\t" + LOAD_PST1 ("x0")); + +ASM_FUNCTION (passthru_pst1_x0_d, + struct pst1, (svfloat32_t, struct pst1), + "ptrue p0.b\n\t" + "fmov z1.s, #1.0\n\t" + "fcmeq p0.s, p0/z, z0.s, z1.s\n\t" + "uzp1 p0.b, p0.b, p0.b\n\t" + "uzp1 p0.b, p0.b, p0.b\n\t" + LOAD_PST1 ("x0")); + +ASM_FUNCTION (passthru_pst1_x0_e, + struct pst1, (svfloat32_t, struct pst1, svint32_t, + svint32_t, svint32_t, svint32_t, + svint32_t, svint32_t, svint32_t), + "ptrue p0.b\n\t" + "fmov z24.s, #4.0\n\t" + "fcmeq p0.s, p0/z, z0.s, z24.s\n\t" + "cmpeq p0.s, p0/z, z1.s, #-4\n\t" + "cmpeq p0.s, p0/z, z2.s, #-9\n\t" + "cmpeq p0.s, p0/z, z3.s, #-14\n\t" + "cmpeq p0.s, p0/z, z4.s, #11\n\t" + "cmpeq p0.s, p0/z, z5.s, #10\n\t" + "cmpeq p0.s, p0/z, z6.s, #8\n\t" + "cmpeq p0.s, p0/z, z7.s, #-1\n\t" + "uzp1 p0.b, p0.b, p0.b\n\t" + "uzp1 p0.b, p0.b, p0.b\n\t" + LOAD_PST1 ("x0")); + +ASM_FUNCTION (passthru_pst1_x7_a, + struct pst1, (svbool_t, + uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, struct pst1), + "add x0, x0, x1\n\t" + "add x2, x2, x3\n\t" + "add x4, x4, x5\n\t" + "add x0, x0, x2\n\t" + "add x4, x4, x6\n\t" + "add x0, x0, x4\n\t" + "add x7, x7, x0\n\t" + "sub x7, x7, #127\n\t" + "ptrue p0.b\n\t" + LOAD_PST1 ("x7")); + +ASM_FUNCTION (passthru_pst1_x7_b, + struct pst1, (svbool_t, svbool_t, svbool_t, svbool_t, + svbool_t, svbool_t, svbool_t, svbool_t, + svbool_t, svbool_t, svbool_t, + struct pst1), + "and p0.b, p1/z, p0.b, p2.b\n\t" + "ldr p2, [x0]\n\t" + "and p0.b, p2/z, p0.b, p3.b\n\t" + "ldr p2, [x1]\n\t" + "ldr p3, [x2]\n\t" + "and p0.b, p2/z, p0.b, p3.b\n\t" + "ldr p2, [x3]\n\t" + "ldr p3, [x4]\n\t" + "and p0.b, p2/z, p0.b, p3.b\n\t" + "ldr p2, [x5]\n\t" + "ldr p3, [x6]\n\t" + "and p0.b, p2/z, p0.b, p3.b\n\t" + LOAD_PST1 ("x7")); + +ASM_FUNCTION (passthru_pst1_sp_a, + struct pst1, (svbool_t, svbool_t, svbool_t, svbool_t, + svbool_t, svbool_t, svbool_t, svbool_t, + svbool_t, svbool_t, svbool_t, svbool_t, + struct pst1), + "and p0.b, p1/z, p0.b, p2.b\n\t" + "ldr p2, [x0]\n\t" + "and p0.b, p2/z, p0.b, p3.b\n\t" + "ldr p2, [x1]\n\t" + "ldr p3, [x2]\n\t" + "and p0.b, p2/z, p0.b, p3.b\n\t" + "ldr p2, [x3]\n\t" + "ldr p3, [x4]\n\t" + "and p0.b, p2/z, p0.b, p3.b\n\t" + "ldr p2, [x5]\n\t" + "ldr p3, [x6]\n\t" + "and p0.b, p2/z, p0.b, p3.b\n\t" + "ldr p2, [x7]\n\t" + "and p0.b, p2/z, p0.b, p0.b\n\t" + "ldr x5, [sp]\n\t" +#if __ILP32__ + "uxtw x5, w5\n\t" +#endif + LOAD_PST1 ("x5")); + +void +test_vl (svbool_t p0, unsigned int vl) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, sveor_z (pg, p0, svwhilelt_b8 (0U, vl)))) + __builtin_abort (); +} + +void +test_pst1 (struct pst1 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, svcmpne (pg, x->v[0], 1)) + || svptest_any (pg, svcmpne (pg, x->v[1], 4)) + || svptest_any (pg, svcmpne (pg, x->v[2], 5)) + || svptest_any (pg, svcmpne (pg, x->v[3], 9)) + || svptest_any (pg, svcmpne (pg, x->v[4], 14)) + || svptest_any (pg, svcmpne (pg, x->v[5], 23)) + || svptest_any (pg, svcmpne (pg, x->v[6], 37)) + || svptest_any (pg, svcmpne (pg, x->v[7], 60)) + || svptest_any (pg, sveor_z (pg, x->p[0], svptrue_pat_b8 (SV_VL1))) + || svptest_any (pg, sveor_z (pg, x->p[1], svptrue_pat_b8 (SV_VL2))) + || svptest_any (pg, sveor_z (pg, x->p[2], svptrue_pat_b8 (SV_VL3))) + || svptest_any (pg, sveor_z (pg, x->p[3], svptrue_pat_b8 (SV_VL4)))) + __builtin_abort (); +} + +struct pst1 +make_pst1 (void) +{ + struct pst1 res; + res.v[0] = svdup_s8 (1); + res.v[1] = svdup_s8 (4); + res.v[2] = svdup_s8 (5); + res.v[3] = svdup_s8 (9); + res.v[4] = svdup_s8 (14); + res.v[5] = svdup_s8 (23); + res.v[6] = svdup_s8 (37); + res.v[7] = svdup_s8 (60); + res.p[0] = svptrue_pat_b8 (SV_VL1); + res.p[1] = svptrue_pat_b8 (SV_VL2); + res.p[2] = svptrue_pat_b8 (SV_VL3); + res.p[3] = svptrue_pat_b8 (SV_VL4); + return res; +} + +struct pst1 +deref_pst1 (struct pst1 *ptr) +{ + return *ptr; +} + +void +consume_pst1 (struct pst1 x) +{ + test_pst1 (&x); +} + +void +consume_pst1_x0_a (svbool_t p0, struct pst1 x0) +{ + test_vl (p0, 11); + test_pst1 (&x0); +} + +void +consume_pst1_x0_b (svbool_t p0, struct pst1 x0, uint64_t x1) +{ + test_vl (p0, 10); + test_pst1 (&x0); + if (x1 != 42) + __builtin_abort (); +} + +void +consume_pst1_x0_c (svbool_t p0, struct pst1 x0, svbool_t p1, + svbool_t p2, svbool_t p3, svbool_t x1) +{ + test_vl (p0, 9); + test_pst1 (&x0); + test_vl (p1, 7); + test_vl (p2, 6); + test_vl (p3, 3); + test_vl (x1, 2); +} + +void +consume_pst1_x0_d (svfloat32_t z0, struct pst1 x0) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, svcmpne (pg, z0, 1.0))) + __builtin_abort (); + test_pst1 (&x0); +} + +void +consume_pst1_x0_e (svfloat32_t z0, struct pst1 x0, + svint32_t z1, svint32_t z2, svint32_t z3, svint32_t z4, + svint32_t z5, svint32_t z6, svint32_t z7) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, svcmpne (pg, z0, 4.0)) + || svptest_any (pg, svcmpne (pg, z1, -4)) + || svptest_any (pg, svcmpne (pg, z2, -9)) + || svptest_any (pg, svcmpne (pg, z3, -14)) + || svptest_any (pg, svcmpne (pg, z4, 11)) + || svptest_any (pg, svcmpne (pg, z5, 10)) + || svptest_any (pg, svcmpne (pg, z6, 8)) + || svptest_any (pg, svcmpne (pg, z7, -1))) + __builtin_abort (); + test_pst1 (&x0); +} + +void +consume_pst1_x7_a (svbool_t p0, uint64_t x0, uint64_t x1, uint64_t x2, + uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6, + struct pst1 x7) +{ + test_vl (p0, __ARM_FEATURE_SVE_BITS); + if (x0 != 1 + || x1 != 2 + || x2 != 4 + || x3 != 8 + || x4 != 16 + || x5 != 32 + || x6 != 64) + __builtin_abort (); + test_pst1 (&x7); +} + +void +consume_pst1_x7_b (svbool_t p0, svbool_t p1, svbool_t p2, svbool_t p3, + svbool_t x0, svbool_t x1, svbool_t x2, svbool_t x3, + svbool_t x4, svbool_t x5, svbool_t x6, struct pst1 x7) +{ + test_vl (p0, __ARM_FEATURE_SVE_BITS); + test_vl (p1, __ARM_FEATURE_SVE_BITS); + test_vl (p2, __ARM_FEATURE_SVE_BITS); + test_vl (p3, __ARM_FEATURE_SVE_BITS); + test_vl (x0, __ARM_FEATURE_SVE_BITS); + test_vl (x1, __ARM_FEATURE_SVE_BITS); + test_vl (x2, __ARM_FEATURE_SVE_BITS); + test_vl (x3, __ARM_FEATURE_SVE_BITS); + test_vl (x4, __ARM_FEATURE_SVE_BITS); + test_vl (x5, __ARM_FEATURE_SVE_BITS); + test_vl (x6, __ARM_FEATURE_SVE_BITS); + test_pst1 (&x7); +} + +void +consume_pst1_sp_a (svbool_t p0, svbool_t p1, svbool_t p2, svbool_t p3, + svbool_t x0, svbool_t x1, svbool_t x2, svbool_t x3, + svbool_t x4, svbool_t x5, svbool_t x6, svbool_t x7, + struct pst1 sp) +{ + test_vl (p0, __ARM_FEATURE_SVE_BITS); + test_vl (p1, __ARM_FEATURE_SVE_BITS); + test_vl (p2, __ARM_FEATURE_SVE_BITS); + test_vl (p3, __ARM_FEATURE_SVE_BITS); + test_vl (x0, __ARM_FEATURE_SVE_BITS); + test_vl (x1, __ARM_FEATURE_SVE_BITS); + test_vl (x2, __ARM_FEATURE_SVE_BITS); + test_vl (x3, __ARM_FEATURE_SVE_BITS); + test_vl (x4, __ARM_FEATURE_SVE_BITS); + test_vl (x5, __ARM_FEATURE_SVE_BITS); + test_vl (x6, __ARM_FEATURE_SVE_BITS); + test_vl (x7, __ARM_FEATURE_SVE_BITS); + test_pst1 (&sp); +} + +int +main (void) +{ + svbool_t pg = svptrue_b8 (); + svbool_t vl2 = svptrue_pat_b8 (SV_VL2); + svbool_t vl3 = svptrue_pat_b8 (SV_VL3); + svbool_t vl6 = svptrue_pat_b8 (SV_VL6); + svbool_t vl7 = svptrue_pat_b8 (SV_VL7); + svbool_t vl9 = svwhilelt_b8 (0, 9); + svbool_t vl10 = svwhilelt_b8 (0, 10); + svbool_t vl11 = svwhilelt_b8 (0, 11); + + CLEANSE; struct pst1 res1 = make_pst1_asm (); + CLEANSE; test_pst1 (&res1); + CLEANSE; consume_pst1 (make_pst1 ()); + + CLEANSE; struct pst1 res2 = deref_pst1 (&res1); + CLEANSE; test_pst1 (&res2); + CLEANSE; consume_pst1 (res2); + + CLEANSE; struct pst1 res3 = passthru_pst1_x0_a (vl11, res1); + CLEANSE; test_pst1 (&res3); + CLEANSE; consume_pst1_x0_a (vl11, res3); + + CLEANSE; struct pst1 res4 = passthru_pst1_x0_b (vl10, res1, 42); + CLEANSE; test_pst1 (&res4); + CLEANSE; consume_pst1_x0_b (vl10, res4, 42); + + CLEANSE; struct pst1 res5 = passthru_pst1_x0_c (vl9, res1, vl7, + vl6, vl3, vl2); + CLEANSE; test_pst1 (&res5); + CLEANSE; consume_pst1_x0_c (vl9, res5, vl7, + vl6, vl3, vl2); + + CLEANSE; struct pst1 res6 = passthru_pst1_x0_d (svdup_f32 (1.0), res1); + CLEANSE; test_pst1 (&res6); + CLEANSE; consume_pst1_x0_d (svdup_f32 (1.0), res6); + + CLEANSE; struct pst1 res7 = passthru_pst1_x0_e (svdup_f32 (4.0), res1, + svdup_s32 (-4), + svdup_s32 (-9), + svdup_s32 (-14), + svdup_s32 (11), + svdup_s32 (10), + svdup_s32 (8), + svdup_s32 (-1)); + CLEANSE; test_pst1 (&res7); + CLEANSE; consume_pst1_x0_e (svdup_f32 (4.0), res1, + svdup_s32 (-4), + svdup_s32 (-9), + svdup_s32 (-14), + svdup_s32 (11), + svdup_s32 (10), + svdup_s32 (8), + svdup_s32 (-1)); + + CLEANSE; struct pst1 res8 = passthru_pst1_x7_a (pg, 1, 2, 4, 8, + 16, 32, 64, res1); + CLEANSE; test_pst1 (&res8); + CLEANSE; consume_pst1_x7_a (pg, 1, 2, 4, 8, + 16, 32, 64, res8); + + CLEANSE; struct pst1 res9 = passthru_pst1_x7_b (pg, pg, pg, pg, + pg, pg, pg, pg, + pg, pg, pg, res1); + CLEANSE; test_pst1 (&res9); + CLEANSE; consume_pst1_x7_b (pg, pg, pg, pg, + pg, pg, pg, pg, + pg, pg, pg, res9); + + CLEANSE; struct pst1 res10 = passthru_pst1_sp_a (pg, pg, pg, pg, + pg, pg, pg, pg, + pg, pg, pg, pg, res1); + CLEANSE; test_pst1 (&res10); + CLEANSE; consume_pst1_sp_a (pg, pg, pg, pg, + pg, pg, pg, pg, + pg, pg, pg, pg, res10); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_2048.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_2048.c new file mode 100644 index 0000000..b7721db --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_2048.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { aarch64_sve2048_hw } } } */ +/* { dg-options "-msve-vector-bits=2048" } */ + +#include "struct_1_128.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_256.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_256.c new file mode 100644 index 0000000..4cdc628 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_256.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { aarch64_sve256_hw } } } */ +/* { dg-options "-msve-vector-bits=256" } */ + +#include "struct_1_128.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_512.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_512.c new file mode 100644 index 0000000..07be8c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_1_512.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { aarch64_sve512_hw } } } */ +/* { dg-options "-msve-vector-bits=512" } */ + +#include "struct_1_128.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_1024.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_1024.c new file mode 100644 index 0000000..9899c4e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_1024.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { aarch64_sve1024_hw } } } */ +/* { dg-options "-msve-vector-bits=1024" } */ + +#include "struct_2_128.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_128.c new file mode 100644 index 0000000..4a608b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_128.c @@ -0,0 +1,701 @@ +/* { dg-do run { target { aarch64_sve128_hw } } } */ +/* { dg-require-effective-target aarch64_little_endian } */ +/* { dg-options "-msve-vector-bits=128" } */ + +#include "struct.h" + +struct pst1 +{ + fixed_uint32_t u32; + fixed_uint64_t u64; +}; + +ASM_FUNCTION (make_pst1_asm, struct pst1, (), + "mov z0.s, #0x1ffffe00\n\t" + "mov z1.d, #0x7f80"); + +ASM_FUNCTION (passthru_pst1_asm, struct pst1, (struct pst1), ""); + +ASM_FUNCTION (passthru_pst1_z6_asm, + struct pst1, (svint32_t, svint32_t, svint32_t, svint32_t, + svint32_t, svint32_t, struct pst1), + "mov z0.d, z6.d\n\t" + "mov z1.d, z7.d"); + +ASM_FUNCTION (passthru_pst1_x0_asm, + struct pst1, (svint32_t, svint32_t, svint32_t, svint32_t, + svint32_t, svint32_t, svint32_t, struct pst1), + "ptrue p0.b\n\t" + "ld1w z0.s, p0/z, [x0]\n\t" + "ld1d z1.d, p0/z, [x0, #1, mul vl]"); + +void +test_pst1 (struct pst1 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, svcmpne (pg, x->u32, 0x1ffffe00)) + || svptest_any (pg, svcmpne (pg, x->u64, 0x7f80))) + __builtin_abort (); +} + +struct pst1 deref_pst1 (struct pst1 *ptr) { return *ptr; } +struct pst1 passthru_pst1 (struct pst1 x) { return x; } + +struct pst1 +passthru_pst1_z6 (svint32_t z0, svint32_t z1, svint32_t z2, svint32_t z3, + svint32_t z4, svint32_t z5, struct pst1 z6) +{ + return z6; +} + +struct pst1 +passthru_pst1_x0 (svint32_t z0, svint32_t z1, svint32_t z2, svint32_t z3, + svint32_t z4, svint32_t z5, svint32_t z6, struct pst1 x0) +{ + return x0; +} + +void consume_pst1 (struct pst1 x) { test_pst1 (&x); } + +static void +run_pst1_tests (void) +{ + svint32_t s32 = svdup_s32 (0); + svbool_t pg = svptrue_b8 (); + + CLEANSE; struct pst1 res = make_pst1_asm (); + CLEANSE; test_pst1 (&res); + CLEANSE; consume_pst1 (deref_pst1 (&res)); + CLEANSE; consume_pst1 (passthru_pst1_asm (res)); + CLEANSE; consume_pst1 (passthru_pst1 (res)); + CLEANSE; consume_pst1 (passthru_pst1_z6_asm (s32, s32, s32, s32, + s32, s32, res)); + CLEANSE; consume_pst1 (passthru_pst1_z6 (s32, s32, s32, s32, + s32, s32, res)); + CLEANSE; consume_pst1 (passthru_pst1_x0_asm (s32, s32, s32, s32, + s32, s32, s32, res)); + CLEANSE; consume_pst1 (passthru_pst1_x0 (s32, s32, s32, s32, + s32, s32, s32, res)); +} + +//-------------------------------------------------------------------------- + +struct pst2 +{ + fixed_uint8_t u8; + fixed_uint16_t u16; + struct { + fixed_float64_t f64; + fixed_bool_t pg; + } a[4]; + struct pst1 sub; +}; + +ASM_FUNCTION (make_pst2_asm, struct pst2, (), + "mov z0.b, #100\n\t" + "mov z1.h, #99\n\t" + "fmov z2.d, #1.0\n\t" + "fmov z3.d, #2.0\n\t" + "fmov z4.d, #3.0\n\t" + "fmov z5.d, #4.0\n\t" + "mov z6.s, #98\n\t" + "mov z7.d, #97\n\t" + "ptrue p0.b, vl5\n\t" + "ptrue p1.b, vl6\n\t" + "ptrue p2.b, vl7\n\t" + "ptrue p3.b, vl8"); + +ASM_FUNCTION (passthru_pst2_asm, struct pst2, (struct pst2), ""); + +ASM_FUNCTION (passthru_pst2_x0_asm, struct pst2, (svbool_t, struct pst2), + "cntd x2, all, mul #9\n\t" + "add x2, x2, #15\n\t" + "and x2, x2, #-16\n\t" + "ptrue p0.b\n\t" + "ld1b z0.b, p0/z, [x0, #0, mul vl]\n\t" + "ld1h z1.h, p0/z, [x0, #1, mul vl]\n\t" + "ld1d z2.d, p0/z, [x0, #2, mul vl]\n\t" + "add x1, x0, x2\n\t" + "ld1d z3.d, p0/z, [x1, #2, mul vl]\n\t" + "ldr p1, [x1, #24, mul vl]\n\t" + "add x1, x1, x2\n\t" + "ld1d z4.d, p0/z, [x1, #2, mul vl]\n\t" + "ldr p2, [x1, #24, mul vl]\n\t" + "add x1, x1, x2\n\t" + "ld1d z5.d, p0/z, [x1, #2, mul vl]\n\t" + "ldr p3, [x1, #24, mul vl]\n\t" + "add x1, x1, x2\n\t" + "ld1w z6.s, p0/z, [x1, #2, mul vl]\n\t" + "ld1d z7.d, p0/z, [x1, #3, mul vl]\n\t" + "ldr p0, [x0, #24, mul vl]"); + +void +test_pst2 (struct pst2 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, svcmpne (pg, x->u8, 100)) + || svptest_any (pg, svcmpne (pg, x->u16, 99)) + || svptest_any (pg, svcmpne (pg, x->a[0].f64, 1.0)) + || svptest_any (pg, sveor_z (pg, x->a[0].pg, svptrue_pat_b8 (SV_VL5))) + || svptest_any (pg, svcmpne (pg, x->a[1].f64, 2.0)) + || svptest_any (pg, sveor_z (pg, x->a[1].pg, svptrue_pat_b8 (SV_VL6))) + || svptest_any (pg, svcmpne (pg, x->a[2].f64, 3.0)) + || svptest_any (pg, sveor_z (pg, x->a[2].pg, svptrue_pat_b8 (SV_VL7))) + || svptest_any (pg, svcmpne (pg, x->a[3].f64, 4.0)) + || svptest_any (pg, sveor_z (pg, x->a[3].pg, svptrue_pat_b8 (SV_VL8))) + || svptest_any (pg, svcmpne (pg, x->sub.u32, 98)) + || svptest_any (pg, svcmpne (pg, x->sub.u64, 97))) + __builtin_abort (); +} + +struct pst2 deref_pst2 (struct pst2 *ptr) { return *ptr; } +struct pst2 passthru_pst2 (struct pst2 x) { return x; } + +struct pst2 +passthru_pst2_x0 (svbool_t pg, struct pst2 x0) +{ + return x0; +} + +void +consume_pst2 (struct pst2 x) +{ + test_pst2 (&x); +} + +static void +run_pst2_tests (void) +{ + CLEANSE; struct pst2 res = make_pst2_asm (); + CLEANSE; test_pst2 (&res); + CLEANSE; consume_pst2 (deref_pst2 (&res)); + CLEANSE; consume_pst2 (passthru_pst2_asm (res)); + CLEANSE; consume_pst2 (passthru_pst2 (res)); + CLEANSE; consume_pst2 (passthru_pst2_x0_asm (svptrue_b8 (), res)); + CLEANSE; consume_pst2 (passthru_pst2_x0 (svptrue_b8 (), res)); +} + +//-------------------------------------------------------------------------- + +struct __attribute__((packed, aligned (2))) pst3 +{ + fixed_bool_t p; + fixed_float16_t v; +}; + +ASM_FUNCTION (make_pst3_asm, struct pst3, (), + "ptrue p0.h, vl3\n\t" + "fmov z0.h, #5.0"); + +ASM_FUNCTION (passthru_pst3_asm, struct pst3, (struct pst3), ""); + +ASM_FUNCTION (passthru_pst3_p3_z7_asm, + struct pst3, (svbool_t, svbool_t, svbool_t, + svint32_t, svint32_t, svint32_t, svint32_t, + svint32_t, svint32_t, svint32_t, struct pst3), + "mov z0.d, z7.d\n\t" + "mov p0.b, p3.b"); + +ASM_FUNCTION (passthru_pst3_x0_asm, + struct pst3, (svbool_t, svbool_t, svbool_t, svbool_t, + struct pst3), + "addpl x1, x0, #1\n\t" + "ld1h z0.h, p1/z, [x1]\n\t" + "ldr p0, [x0]"); + +void +test_pst3 (struct pst3 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, sveor_z (pg, x->p, svptrue_pat_b16 (SV_VL3))) + || svptest_any (pg, svcmpne (pg, x->v, 5.0))) + __builtin_abort (); +} + +struct pst3 deref_pst3 (struct pst3 *ptr) { return *ptr; } +struct pst3 passthru_pst3 (struct pst3 x) { return x; } + +struct pst3 +passthru_pst3_p3_z7 (svbool_t p0, svbool_t p1, svbool_t p2, + svint32_t z0, svint32_t z1, svint32_t z2, svint32_t z3, + svint32_t z4, svint32_t z5, svint32_t z6, + struct pst3 p3_z7) +{ + return p3_z7; +} + +struct pst3 +passthru_pst3_x0 (svbool_t p0, svbool_t p1, svbool_t p2, svbool_t p3, + struct pst3 x0) +{ + return x0; +} + +void consume_pst3 (struct pst3 x) { test_pst3 (&x); } + +static void +run_pst3_tests (void) +{ + svint32_t s32 = svdup_s32 (0); + svbool_t pg = svptrue_b8 (); + + CLEANSE; struct pst3 res = make_pst3_asm (); + CLEANSE; test_pst3 (&res); + CLEANSE; consume_pst3 (deref_pst3 (&res)); + CLEANSE; consume_pst3 (passthru_pst3_asm (res)); + CLEANSE; consume_pst3 (passthru_pst3 (res)); + CLEANSE; consume_pst3 (passthru_pst3_p3_z7_asm (pg, pg, pg, + s32, s32, s32, s32, + s32, s32, s32, res)); + CLEANSE; consume_pst3 (passthru_pst3_p3_z7 (pg, pg, pg, + s32, s32, s32, s32, + s32, s32, s32, res)); + CLEANSE; consume_pst3 (passthru_pst3_x0_asm (pg, pg, pg, pg, res)); + CLEANSE; consume_pst3 (passthru_pst3_x0 (pg, pg, pg, pg, res)); +} + +//-------------------------------------------------------------------------- + +struct pst4 +{ + fixed_bool_t p1; + fixed_bool_t p2 __attribute__((aligned (256))); + fixed_bool_t p3 __attribute__((aligned (2048))); +}; + +ASM_FUNCTION (make_pst4_asm, struct pst4, (), + "ptrue p0.h, vl7\n\t" + "ptrue p1.h, mul3\n\t" + "ptrue p2.h, vl5"); + +ASM_FUNCTION (passthru_pst4_asm, struct pst4, (struct pst4), ""); + +ASM_FUNCTION (passthru_pst4_p1_asm, + struct pst4, (svbool_t, struct pst4), + "mov p0.b, p1.b\n\t" + "mov p1.b, p2.b\n\t" + "mov p2.b, p3.b"); + +ASM_FUNCTION (passthru_pst4_x0_asm, + struct pst4, (svbool_t, svbool_t, struct pst4), + "ldr p0, [x0]\n\t" + "add x0, x0, #256\n\t" + "ldr p1, [x0]\n\t" + "add x0, x0, #2048 - 256\n\t" + "ldr p2, [x0]"); + +void +test_pst4 (struct pst4 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, sveor_z (pg, x->p1, svptrue_pat_b16 (SV_VL7))) + || svptest_any (pg, sveor_z (pg, x->p2, svptrue_pat_b16 (SV_MUL3))) + || svptest_any (pg, sveor_z (pg, x->p3, svptrue_pat_b16 (SV_VL5)))) + __builtin_abort (); +} + +struct pst4 deref_pst4 (struct pst4 *ptr) { return *ptr; } +struct pst4 passthru_pst4 (struct pst4 x) { return x; } + +struct pst4 +passthru_pst4_p1 (svbool_t p0, struct pst4 p1) +{ + return p1; +} + +struct pst4 +passthru_pst4_x0 (svbool_t p0, svbool_t p1, struct pst4 x0) +{ + return x0; +} + +void consume_pst4 (struct pst4 x) { test_pst4 (&x); } + +static void +run_pst4_tests (void) +{ + svbool_t pg = svptrue_b8 (); + + CLEANSE; struct pst4 res = make_pst4_asm (); + CLEANSE; test_pst4 (&res); + CLEANSE; consume_pst4 (deref_pst4 (&res)); + CLEANSE; consume_pst4 (passthru_pst4_asm (res)); + CLEANSE; consume_pst4 (passthru_pst4 (res)); + CLEANSE; consume_pst4 (passthru_pst4_p1_asm (pg, res)); + CLEANSE; consume_pst4 (passthru_pst4_p1 (pg, res)); + CLEANSE; consume_pst4 (passthru_pst4_x0_asm (pg, pg, res)); + CLEANSE; consume_pst4 (passthru_pst4_x0 (pg, pg, res)); +} + +//-------------------------------------------------------------------------- + +struct pst5 +{ + fixed_uint16_t v[8]; +}; + +ASM_FUNCTION (make_pst5_asm, struct pst5, (), + "index z0.h, #0, #-1\n\t" + "index z1.h, #0, #-2\n\t" + "index z2.h, #0, #-3\n\t" + "index z3.h, #0, #-4\n\t" + "index z4.h, #0, #-5\n\t" + "index z5.h, #0, #-6\n\t" + "index z6.h, #0, #-7\n\t" + "index z7.h, #0, #-8"); + +ASM_FUNCTION (passthru_pst5_asm, struct pst5, (struct pst5), ""); + +void +test_pst5 (struct pst5 *x) +{ + svbool_t pg = svptrue_b8 (); + for (int i = 0; i < 8; ++i) + if (svptest_any (pg, svcmpne (pg, x->v[i], svindex_u16 (0, -1 - i)))) + __builtin_abort (); +} + +struct pst5 deref_pst5 (struct pst5 *ptr) { return *ptr; } +struct pst5 passthru_pst5 (struct pst5 x) { return x; } + +void consume_pst5 (struct pst5 x) { test_pst5 (&x); } + +static void +run_pst5_tests (void) +{ + CLEANSE; struct pst5 res = make_pst5_asm (); + CLEANSE; test_pst5 (&res); + CLEANSE; consume_pst5 (deref_pst5 (&res)); + CLEANSE; consume_pst5 (passthru_pst5_asm (res)); + CLEANSE; consume_pst5 (passthru_pst5 (res)); +} + +//-------------------------------------------------------------------------- + +struct pst6 +{ + fixed_uint16_t v[9]; +}; + +ASM_FUNCTION (make_pst6_asm, struct pst6, (), + "mov x0, #10\n\t" + "ptrue p0.b\n" + "1:\n\t" + "index z0.h, #0, w0\n\t" + "st1h z0.h, p0, [x8]\n\t" + "add x0, x0, #1\n\t" + "incb x8\n\t" + "cmp x0, #19\n\t" + "bne 1b"); + +ASM_FUNCTION (passthru_pst6_asm, struct pst6, (struct pst6), + "mov x1, x0\n\t" + "mov x0, x8\n\t" + "cntb x2, all, mul #9\n\t" + "b memcpy"); + +void +test_pst6 (struct pst6 *x) +{ + svbool_t pg = svptrue_b8 (); + for (int i = 0; i < 9; ++i) + if (svptest_any (pg, svcmpne (pg, x->v[i], svindex_u16 (0, i + 10)))) + __builtin_abort (); +} + +struct pst6 deref_pst6 (struct pst6 *ptr) { return *ptr; } +struct pst6 passthru_pst6 (struct pst6 x) { return x; } + +void consume_pst6 (struct pst6 x) { test_pst6 (&x); } + +static void +run_pst6_tests (void) +{ + CLEANSE; struct pst6 res = make_pst6_asm (); + CLEANSE; test_pst6 (&res); + CLEANSE; consume_pst6 (deref_pst6 (&res)); + CLEANSE; consume_pst6 (passthru_pst6_asm (res)); + CLEANSE; consume_pst6 (passthru_pst6 (res)); +} + +//-------------------------------------------------------------------------- + +struct pst7 +{ + fixed_bool_t p[2][2]; +}; + +ASM_FUNCTION (make_pst7_asm, struct pst7, (), + "ptrue p0.b, vl6\n\t" + "ptrue p1.b, vl7\n\t" + "ptrue p2.h, vl3\n\t" + "ptrue p3.h, vl2"); + +ASM_FUNCTION (passthru_pst7_asm, struct pst7, (struct pst7), ""); + +void +test_pst7 (struct pst7 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, sveor_z (pg, x->p[0][0], svptrue_pat_b8 (SV_VL6))) + || svptest_any (pg, sveor_z (pg, x->p[0][1], svptrue_pat_b8 (SV_VL7))) + || svptest_any (pg, sveor_z (pg, x->p[1][0], svptrue_pat_b16 (SV_VL3))) + || svptest_any (pg, sveor_z (pg, x->p[1][1], svptrue_pat_b16 (SV_VL2)))) + __builtin_abort (); +} + +struct pst7 deref_pst7 (struct pst7 *ptr) { return *ptr; } +struct pst7 passthru_pst7 (struct pst7 x) { return x; } + +void consume_pst7 (struct pst7 x) { test_pst7 (&x); } + +static void +run_pst7_tests (void) +{ + CLEANSE; struct pst7 res = make_pst7_asm (); + CLEANSE; test_pst7 (&res); + CLEANSE; consume_pst7 (deref_pst7 (&res)); + CLEANSE; consume_pst7 (passthru_pst7_asm (res)); + CLEANSE; consume_pst7 (passthru_pst7 (res)); +} + +//-------------------------------------------------------------------------- + +struct pst8 +{ + fixed_bool_t p[2][3]; +}; + +ASM_FUNCTION (make_pst8_asm, struct pst8, (), + "ptrue p3.h, vl2\n\t" + "str p3, [x8]\n\t" + "ptrue p3.h, vl3\n\t" + "str p3, [x8, #1, mul vl]\n\t" + "ptrue p3.h, vl4\n\t" + "str p3, [x8, #2, mul vl]\n\t" + "ptrue p3.s, vl2\n\t" + "str p3, [x8, #3, mul vl]\n\t" + "ptrue p3.s, vl3\n\t" + "str p3, [x8, #4, mul vl]\n\t" + "ptrue p3.s, vl4\n\t" + "str p3, [x8, #5, mul vl]"); + +ASM_FUNCTION (passthru_pst8_asm, struct pst8, (struct pst8), + "cntw x1, all, mul #3\n\t" + "whilelo p0.b, xzr, x1\n\t" + "ld1b z0.b, p0/z, [x0]\n\t" + "st1b z0.b, p0, [x8]"); + +void +test_pst8 (struct pst8 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, sveor_z (pg, x->p[0][0], svptrue_pat_b16 (SV_VL2))) + || svptest_any (pg, sveor_z (pg, x->p[0][1], svptrue_pat_b16 (SV_VL3))) + || svptest_any (pg, sveor_z (pg, x->p[0][2], svptrue_pat_b16 (SV_VL4))) + || svptest_any (pg, sveor_z (pg, x->p[1][0], svptrue_pat_b32 (SV_VL2))) + || svptest_any (pg, sveor_z (pg, x->p[1][1], svptrue_pat_b32 (SV_VL3))) + || svptest_any (pg, sveor_z (pg, x->p[1][2], svptrue_pat_b32 (SV_VL4)))) + __builtin_abort (); +} + +struct pst8 deref_pst8 (struct pst8 *ptr) { return *ptr; } +struct pst8 passthru_pst8 (struct pst8 x) { return x; } + +void consume_pst8 (struct pst8 x) { test_pst8 (&x); } + +static void +run_pst8_tests (void) +{ + CLEANSE; struct pst8 res = make_pst8_asm (); + CLEANSE; test_pst8 (&res); + CLEANSE; consume_pst8 (deref_pst8 (&res)); + CLEANSE; consume_pst8 (passthru_pst8_asm (res)); + CLEANSE; consume_pst8 (passthru_pst8 (res)); +} + +//-------------------------------------------------------------------------- + +struct nonpst1 +{ + int x; + fixed_uint8_t v; + fixed_bool_t p; +}; + +ASM_FUNCTION (make_nonpst1_asm, struct nonpst1, (), + "mov w0, #42\n\t" + "str w0, [x8]\n\t" + "add x0, x8, #16\n\t" + "ptrue p0.b\n\t" + "index z0.b, #0, #3\n\t" + "st1b z0.b, p0, [x0]\n\t" + "ptrue p3.b, vl5\n\t" + "str p3, [x0, #8, mul vl]"); + +ASM_FUNCTION (passthru_nonpst1_asm, struct nonpst1, (struct nonpst1), + "mov x1, x0\n\t" + "mov x0, x8\n\t" + "cntd x2, all, mul #9\n\t" + "add x2, x2, #16\n\t" + "b memcpy"); + +void +test_nonpst1 (struct nonpst1 *x) +{ + svbool_t pg = svptrue_b8 (); + if (x->x != 42 + || svptest_any (pg, svcmpne (pg, x->v, svindex_u8 (0, 3))) + || svptest_any (pg, sveor_z (pg, x->p, svptrue_pat_b8 (SV_VL5)))) + __builtin_abort (); +} + +struct nonpst1 deref_nonpst1 (struct nonpst1 *ptr) { return *ptr; } +struct nonpst1 passthru_nonpst1 (struct nonpst1 x) { return x; } + +void consume_nonpst1 (struct nonpst1 x) { test_nonpst1 (&x); } + +static void +run_nonpst1_tests (void) +{ + CLEANSE; struct nonpst1 res = make_nonpst1_asm (); + CLEANSE; test_nonpst1 (&res); + CLEANSE; consume_nonpst1 (deref_nonpst1 (&res)); + CLEANSE; consume_nonpst1 (passthru_nonpst1_asm (res)); + CLEANSE; consume_nonpst1 (passthru_nonpst1 (res)); +} + +//-------------------------------------------------------------------------- + +struct nonpst2 +{ + union { struct { fixed_bool_t p; }; }; +}; + +ASM_FUNCTION (make_nonpst2_asm, struct nonpst2, (), + "ptrue p3.h, mul3\n\t" + "cntd x2\n\t" + "cmp x2, #16\n\t" + "b.ls 1f\n\t" + "str p3, [x8]\n\t" + "ret\n" + "1:\n\t" + "addvl sp, sp, #-1\n\t" + "str p3, [sp]\n\t" + "ldp x0, x1, [sp]\n\t" + "addvl sp, sp, #1"); + +ASM_FUNCTION (passthru_nonpst2_asm, struct nonpst2, (struct nonpst2), + "cntb x2\n\t" + "cmp x2, #128\n\t" + "b.eq 1f\n\t" + "b.lo 2f\n\t" + "ldr p3, [x0]\n\t" + "str p3, [x8]\n" + "1:\n\t" + "ret\n" + "2:\n\t" + "mov x3, #-1\n\t" +#if __ARM_BIG_ENDIAN + "lsr x3, x3, x2\n\t" +#else + "lsl x3, x3, x2\n\t" +#endif + "bic x1, x0, x3\n\t" + "cmp x2, #64\n\t" + "csel x0, x0, x1, eq"); + +void +test_nonpst2 (struct nonpst2 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, sveor_z (pg, x->p, svptrue_pat_b16 (SV_MUL3)))) + __builtin_abort (); +} + +struct nonpst2 deref_nonpst2 (struct nonpst2 *ptr) { return *ptr; } +struct nonpst2 passthru_nonpst2 (struct nonpst2 x) { return x; } + +void consume_nonpst2 (struct nonpst2 x) { test_nonpst2 (&x); } + +static void +run_nonpst2_tests (void) +{ + CLEANSE; struct nonpst2 res = make_nonpst2_asm (); + CLEANSE; test_nonpst2 (&res); + CLEANSE; consume_nonpst2 (deref_nonpst2 (&res)); + CLEANSE; consume_nonpst2 (passthru_nonpst2_asm (res)); + CLEANSE; consume_nonpst2 (passthru_nonpst2 (res)); +} + +//-------------------------------------------------------------------------- + +struct nonpst3 +{ + union { struct { fixed_int32_t v; }; }; +}; + +ASM_FUNCTION (make_nonpst3_asm, struct nonpst3, (), + "ptrue p0.b\n\t" + "index z1.s, #15, #-9\n\t" + "cntb x2\n\t" + "cmp x2, #16\n\t" + "b.ls 1f\n\t" + "st1w z1.s, p0, [x8]\n\t" + "ret\n" + "1:\n\t" + "addvl sp, sp, #-1\n\t" + "st1w z1.s, p0, [sp]\n\t" + "ldp x0, x1, [sp]\n\t" + "addvl sp, sp, #1"); + +ASM_FUNCTION (passthru_nonpst3_asm, struct nonpst3, (struct nonpst3), + "cntb x2\n\t" + "cmp x2, #16\n\t" + "b.ls 1f\n\t" + "ptrue p0.b\n\t" + "ld1w z1.s, p0/z, [x0]\n\t" + "st1w z1.s, p0, [x8]\n" + "1:"); + +void +test_nonpst3 (struct nonpst3 *x) +{ + svbool_t pg = svptrue_b8 (); + if (svptest_any (pg, svcmpne (pg, x->v, svindex_s32 (15, -9)))) + __builtin_abort (); +} + +struct nonpst3 deref_nonpst3 (struct nonpst3 *ptr) { return *ptr; } +struct nonpst3 passthru_nonpst3 (struct nonpst3 x) { return x; } + +void consume_nonpst3 (struct nonpst3 x) { test_nonpst3 (&x); } + +static void +run_nonpst3_tests (void) +{ + CLEANSE; struct nonpst3 res = make_nonpst3_asm (); + CLEANSE; test_nonpst3 (&res); + CLEANSE; consume_nonpst3 (deref_nonpst3 (&res)); + CLEANSE; consume_nonpst3 (passthru_nonpst3_asm (res)); + CLEANSE; consume_nonpst3 (passthru_nonpst3 (res)); +} + +//-------------------------------------------------------------------------- + +int +main (void) +{ + run_pst1_tests (); + run_pst2_tests (); + run_pst3_tests (); + run_pst4_tests (); + run_pst5_tests (); + run_pst6_tests (); + run_pst7_tests (); + run_pst8_tests (); + run_nonpst1_tests (); + run_nonpst2_tests (); + run_nonpst3_tests (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_2048.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_2048.c new file mode 100644 index 0000000..6df410d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_2048.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { aarch64_sve2048_hw } } } */ +/* { dg-options "-msve-vector-bits=2048" } */ + +#include "struct_2_128.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_256.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_256.c new file mode 100644 index 0000000..230fa8c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_256.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { aarch64_sve256_hw } } } */ +/* { dg-options "-msve-vector-bits=256" } */ + +#include "struct_2_128.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_512.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_512.c new file mode 100644 index 0000000..e6d0512 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_2_512.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { aarch64_sve512_hw } } } */ +/* { dg-options "-msve-vector-bits=512" } */ + +#include "struct_2_128.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_128.c new file mode 100644 index 0000000..443ce4c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_128.c @@ -0,0 +1,1092 @@ +/* { dg-options "-O -msve-vector-bits=128" } */ +/* { dg-require-effective-target aarch64_little_endian } +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "struct.h" + +#define CONSUME(VAR) \ + { \ + register void *ptr_ asm ("x7") = &(VAR); \ + asm volatile ("" :: "r" (ptr_) : "memory"); \ + } + +#define SEL2(TAG, TYPE) \ + TAG TYPE \ + sel2_##TYPE (TAG TYPE x, TAG TYPE y) \ + { \ + return y; \ + } + +#define WRAP(TYPE) \ + struct wrap_##TYPE \ + { \ + TYPE data; \ + }; \ + SEL2 (struct, wrap_##TYPE) + +/* +** sel2_wrap_fixed_int8_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int8_t\n} } } */ +WRAP (fixed_int8_t); + +/* +** sel2_wrap_fixed_int16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int16_t\n} } } */ +WRAP (fixed_int16_t); + +/* +** sel2_wrap_fixed_int32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int32_t\n} } } */ +WRAP (fixed_int32_t); + +/* +** sel2_wrap_fixed_int64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int64_t\n} } } */ +WRAP (fixed_int64_t); + +/* +** sel2_wrap_fixed_uint8_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint8_t\n} } } */ +WRAP (fixed_uint8_t); + +/* +** sel2_wrap_fixed_uint16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint16_t\n} } } */ +WRAP (fixed_uint16_t); + +/* +** sel2_wrap_fixed_uint32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint32_t\n} } } */ +WRAP (fixed_uint32_t); + +/* +** sel2_wrap_fixed_uint64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint64_t\n} } } */ +WRAP (fixed_uint64_t); + +/* +** sel2_wrap_fixed_bfloat16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_bfloat16_t\n} } } */ +WRAP (fixed_bfloat16_t); + +/* +** sel2_wrap_fixed_float16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float16_t\n} } } */ +WRAP (fixed_float16_t); + +/* +** sel2_wrap_fixed_float32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float32_t\n} } } */ +WRAP (fixed_float32_t); + +/* +** sel2_wrap_fixed_float64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float64_t\n} } } */ +WRAP (fixed_float64_t); + +/* +** sel2_wrap_fixed_bool_t: +** mov p0\.b, p1\.b +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_bool_t\n} } } */ +WRAP (fixed_bool_t); + +struct pst_arr1 +{ + fixed_uint8_t u8[1]; +}; + +/* +** sel2_pst_arr1: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr1\n} } } */ +SEL2 (struct, pst_arr1) + +/* +** test_pst_arr1: +** eor z0\.b, z0\.b, #(?:0x)?1 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr1\n} } } */ +svuint8_t +test_pst_arr1 (struct pst_arr1 x) +{ + return sveor_x (svptrue_b8 (), x.u8[0], 1); +} + +struct pst_arr2 +{ + fixed_uint8_t u8[2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr2\n} } } */ +SEL2 (struct, pst_arr2) + +/* +** test_pst_arr2: +** sub z0\.b, z0\.b, z1\.b +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr2\n} } } */ +svuint8_t +test_pst_arr2 (struct pst_arr2 x) +{ + return svsub_x (svptrue_b8 (), x.u8[0], x.u8[1]); +} + +struct pst_arr3 +{ + fixed_uint16_t u16[3]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr3\n} } } */ +SEL2 (struct, pst_arr3) + +/* +** test_pst_arr3: +** sub z0\.h, z0\.h, z2\.h +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr3\n} } } */ +svuint16_t +test_pst_arr3 (struct pst_arr3 x) +{ + return svsub_x (svptrue_b8 (), x.u16[0], x.u16[2]); +} + +struct pst_arr4 +{ + fixed_uint32_t u32[4]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr4\n} } } */ +SEL2 (struct, pst_arr4) + +/* +** test_pst_arr4: +** sub z0\.s, z0\.s, z3\.s +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr4\n} } } */ +svuint32_t +test_pst_arr4 (struct pst_arr4 x) +{ + return svsub_x (svptrue_b8 (), x.u32[0], x.u32[3]); +} + +struct pst_arr5 +{ + fixed_uint64_t u64[2][2][2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr5\n} } } */ +SEL2 (struct, pst_arr5) + +/* +** test_pst_arr5: +** sub sp, sp, #128 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** str z3, \[sp, #3, mul vl\] +** str z4, \[sp, #4, mul vl\] +** str z5, \[sp, #5, mul vl\] +** str z6, \[sp, #6, mul vl\] +** str z7, \[sp, #7, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?128 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5\n} } } */ +void +test_pst_arr5 (struct pst_arr5 x) +{ + CONSUME (x); +} + +/* +** test_pst_arr5_x0: +** ( +** mov z0\.d, z7\.d +** mov (x7, x0|w7, w0) +** | +** mov (x7, x0|w7, w0) +** mov z0\.d, z7\.d +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_x0\n} } } */ +svint32_t +test_pst_arr5_x0 (svint32_t z0, struct pst_arr5 x, + svint32_t z1, svint32_t z2, svint32_t z3, svint32_t z4, + svint32_t z5, svint32_t z6, svint32_t z7) +{ + CONSUME (x); + return z7; +} + +/* +** test_pst_arr5_x7: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_x7\n} } } */ +svint32_t +test_pst_arr5_x7 (svint32_t z0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, struct pst_arr5 x) +{ + CONSUME (x); + return z0; +} + +/* +** test_pst_arr5_sp: { target lp64 } +** ldr x7, \[sp\] +** ret +*/ +/* +** test_pst_arr5_sp: { target ilp32 } +** ldr w7, \[sp\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_sp\n} } } */ +svint32_t +test_pst_arr5_sp (svint32_t z0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, struct pst_arr5 x) +{ + CONSUME (x); + return z0; +} + +struct pst_arr6 +{ + fixed_bool_t b[2][2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr6\n} } } */ +SEL2 (struct, pst_arr6) + +/* +** test_pst_arr6: +** ... +** brkpa p0\.b, p0/z, p2\.b, p3\.b +** ... +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6\n} } } */ +fixed_bool_t +test_pst_arr6 (struct pst_arr6 x) +{ + return svbrkpa_z (x.b[0][0], x.b[1][0], x.b[1][1]); +} + +/* +** test_pst_arr6_x0: +** ( +** mov p0\.b, p3\.b +** mov (x7, x0|w7, w0) +** | +** mov (x7, x0|w7, w0) +** mov p0\.b, p3\.b +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_x0\n} } } */ +fixed_bool_t +test_pst_arr6_x0 (svbool_t p0, struct pst_arr6 x, svbool_t p1, svbool_t p2, + svbool_t p3) +{ + CONSUME (x); + return p3; +} + +/* +** test_pst_arr6_x7: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_x7\n} } } */ +fixed_bool_t +test_pst_arr6_x7 (svbool_t p0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, struct pst_arr6 x) +{ + CONSUME (x); + return p0; +} + +/* +** test_pst_arr6_sp: { target lp64 } +** ldr x7, \[sp\] +** ret +*/ +/* +** test_pst_arr6_sp: { target ilp32 } +** ldr w7, \[sp\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_sp\n} } } */ +fixed_bool_t +test_pst_arr6_sp (svbool_t p0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, struct pst_arr6 x) +{ + CONSUME (x); + return p0; +} + +struct pst_uniform1 +{ + fixed_int8_t a, b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform1\n} } } */ +SEL2 (struct, pst_uniform1) + +/* +** test_pst_uniform1: +** sub sp, sp, #32 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?32 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform1\n} } } */ +void +test_pst_uniform1 (struct pst_uniform1 x) +{ + CONSUME (x); +} + +struct pst_uniform2 +{ + fixed_int16_t a; + fixed_int16_t b[2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform2\n} } } */ +SEL2 (struct, pst_uniform2) + +/* +** test_pst_uniform2: +** sub sp, sp, #48 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?48 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform2\n} } } */ +void +test_pst_uniform2 (struct pst_uniform2 x) +{ + CONSUME (x); +} + +struct pst_uniform3 +{ + fixed_int32_t a; + fixed_int32_t b[2]; + fixed_int32_t c; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform3\n} } } */ +SEL2 (struct, pst_uniform3) + +/* +** test_pst_uniform3: +** sub sp, sp, #64 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** str z3, \[sp, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?64 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform3\n} } } */ +void +test_pst_uniform3 (struct pst_uniform3 x) +{ + CONSUME (x); +} + +struct pst_uniform4 +{ + fixed_int32_t a __attribute__((aligned(SVE_BYTES * 2))); + fixed_int32_t b[3] __attribute__((aligned(SVE_BYTES * 2))); + fixed_int32_t c __attribute__((aligned(SVE_BYTES * 2))); +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform4\n} } } */ +SEL2 (struct, pst_uniform4) + +/* +** test_pst_uniform4: +** sub sp, sp, #144 +** add (x[0-9]+), sp, #?31 +** and x7, \1, #?(?:-32|4294967264) +** ptrue (p[0-7])\.b, vl16 +** st1w z0\.s, \2, \[x7\] +** add (x[0-9]+), x7, #?32 +** str z1, \[\3\] +** str z2, \[\3, #1, mul vl\] +** str z3, \[\3, #2, mul vl\] +** st1w z4\.s, \2, \[x7, #6, mul vl\] +** add sp, sp, #?144 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform4\n} } } */ +void +test_pst_uniform4 (struct pst_uniform4 x) +{ + CONSUME (x); +} + +struct pst_mixed1 +{ + fixed_bool_t p0; + fixed_bfloat16_t z0; + fixed_float16_t z1; + fixed_float32_t z2; + fixed_float64_t z3; + fixed_bool_t p1; + fixed_bool_t p2; + fixed_int8_t z4; + fixed_int16_t z5; + fixed_int32_t z6; + fixed_int64_t z7; + fixed_bool_t p3; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_mixed1\n} } } */ +SEL2 (struct, pst_mixed1) + +/* +** test_pst_mixed1: +** sub sp, sp, #176 +** str p0, \[sp\] +** ptrue p0\.b, vl16 +** st1h z0\.h, p0, \[sp, #1, mul vl\] +** st1h z1\.h, p0, \[sp, #2, mul vl\] +** st1w z2\.s, p0, \[sp, #3, mul vl\] +** st1d z3\.d, p0, \[sp, #4, mul vl\] +** str p1, \[sp, #40, mul vl\] +** str p2, \[sp, #41, mul vl\] +** st1b z4\.b, p0, \[sp, #6, mul vl\] +** st1h z5\.h, p0, \[sp, #7, mul vl\] +** ... +** st1w z6\.s, p0, [^\n]* +** ... +** st1d z7\.d, p0, [^\n]* +** ... +** str p3, \[sp, #80, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?176 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_mixed1\n} } } */ +void +test_pst_mixed1 (struct pst_mixed1 x) +{ + CONSUME (x); +} + +struct pst_mixed2 +{ + struct __attribute__ ((packed)) { + fixed_bool_t p; + fixed_int8_t z; + } a[3]; + fixed_int16_t b[1][1][1][4]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_mixed2\n} } } */ +SEL2 (struct, pst_mixed2) + +/* +** test_pst_mixed2: +** sub sp, sp, #128 +** str p0, \[sp\] +** ptrue (p[03])\.b, vl16 +** add (x[0-9]+), sp, #?2 +** st1b z0\.b, \1, \[\2\] +** str p1, \[sp, #9, mul vl\] +** add (x[0-9]+), sp, #?20 +** st1b z1\.b, \1, \[\3\] +** str p2, \[sp, #18, mul vl\] +** add (x[0-9]+), sp, #?38 +** st1b z2\.b, \1, \[\4\] +** str z3, \[sp, #4, mul vl\] +** str z4, \[sp, #5, mul vl\] +** str z5, \[sp, #6, mul vl\] +** str z6, \[sp, #7, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?128 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_mixed2\n} } } */ +void +test_pst_mixed2 (struct pst_mixed2 x) +{ + CONSUME (x); +} + +struct pst_big1 +{ + fixed_int8_t a[9]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big1\n} } } */ +SEL2 (struct, pst_big1) + +/* +** test_pst_big1_a: { target lp64 } +** ptrue (p[0-7])\.b, vl16 +** ld1b z0\.b, \1/z, \[x0\] +** ret +*/ +/* +** test_pst_big1_a: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl16 +** ld1b z0\.b, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big1_a\n} } } */ +svint8_t +test_pst_big1_a (struct pst_big1 x) +{ + return x.a[0]; +} + +/* +** test_pst_big1_b: { target lp64 } +** add x7, x0, #?128 +** ret +*/ +/* +** test_pst_big1_b: { target ilp32 } +** add w7, w0, #?128 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big1_b\n} } } */ +svint8_t +test_pst_big1_b (struct pst_big1 x) +{ + CONSUME (x.a[8]); +} + +struct pst_big2 +{ + fixed_bool_t a[5]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big2\n} } } */ +SEL2 (struct, pst_big2) + +/* +** test_pst_big2_a: { target lp64 } +** ldr p0, \[x0\] +** ret +*/ +/* +** test_pst_big2_a: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big2_a\n} } } */ +svbool_t +test_pst_big2_a (struct pst_big2 x) +{ + return x.a[0]; +} + +/* +** test_pst_big2_b: { target lp64 } +** ldr p0, \[x0, #4, mul vl\] +** ret +*/ +/* +** test_pst_big2_b: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #4, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big2_b\n} } } */ +svbool_t +test_pst_big2_b (struct pst_big2 x) +{ + return x.a[4]; +} + +struct pst_big3 +{ + fixed_bool_t p0; + fixed_int8_t a[2]; + fixed_bool_t p1; + fixed_bool_t p2; + fixed_bool_t p3; + fixed_int8_t b[6]; + fixed_bool_t p4; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big3\n} } } */ +SEL2 (struct, pst_big3) + +/* +** test_pst_big3_a: { target lp64 } +** ldr p0, \[x0\] +** ret +*/ +/* +** test_pst_big3_a: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_a\n} } } */ +svbool_t +test_pst_big3_a (struct pst_big3 x) +{ + return x.p0; +} + +/* +** test_pst_big3_b: { target lp64 } +** ldr p0, \[x0, #24, mul vl\] +** ret +*/ +/* +** test_pst_big3_b: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #24, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_b\n} } } */ +svbool_t +test_pst_big3_b (struct pst_big3 x) +{ + return x.p1; +} + +/* +** test_pst_big3_c: { target lp64 } +** ldr p0, \[x0, #25, mul vl\] +** ret +*/ +/* +** test_pst_big3_c: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #25, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_c\n} } } */ +svbool_t +test_pst_big3_c (struct pst_big3 x) +{ + return x.p2; +} + +/* +** test_pst_big3_d: { target lp64 } +** ldr p0, \[x0, #80, mul vl\] +** ret +*/ +/* +** test_pst_big3_d: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #80, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_d\n} } } */ +svbool_t +test_pst_big3_d (struct pst_big3 x) +{ + return x.p4; +} + +/* +** test_pst_big3_e: { target lp64 } +** ptrue (p[0-7])\.b, vl16 +** ld1b z0\.b, \1/z, \[x0, #1, mul vl\] +** ret +*/ +/* +** test_pst_big3_e: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl16 +** ld1b z0\.b, \1/z, \[x0, #1, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_e\n} } } */ +svint8_t +test_pst_big3_e (struct pst_big3 x) +{ + return x.a[0]; +} + +/* +** test_pst_big3_f: { target lp64 } +** ptrue (p[0-7])\.b, vl16 +** ld1b z0\.b, \1/z, \[x0, #5, mul vl\] +** ret +*/ +/* +** test_pst_big3_f: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl16 +** ld1b z0\.b, \1/z, \[x0, #5, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_f\n} } } */ +svint8_t +test_pst_big3_f (struct pst_big3 x) +{ + return x.b[1]; +} + +struct pst_zero1 +{ + fixed_bool_t a[0]; + fixed_int32_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero1\n} } } */ +SEL2 (struct, pst_zero1) + +/* +** test_pst_zero1: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero1\n} } } */ +svint32_t +test_pst_zero1 (struct pst_zero1 x) +{ + return x.b; +} + +struct pst_zero2 +{ + unsigned int : 0; + fixed_bool_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero2\n} } } */ +SEL2 (struct, pst_zero2) + +/* +** test_pst_zero2: +** ( +** sub sp, sp, #16 +** add sp, sp, #?16 +** | +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero2\n} } } */ +svbool_t +test_pst_zero2 (struct pst_zero2 x) +{ + return x.b; +} + +struct pst_zero3 +{ + struct {} empty; + fixed_uint64_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero3\n} } } */ +SEL2 (struct, pst_zero3) + +/* +** test_pst_zero3: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero3\n} } } */ +svuint64_t +test_pst_zero3 (struct pst_zero3 x) +{ + return x.b; +} + +typedef unsigned char small_vec __attribute__((vector_size(SVE_BYTES / 4))); + +struct nonpst1 +{ + small_vec a[4]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst1\n} } } */ +SEL2 (struct, nonpst1) + +/* +** test_nonpst1: +** ... +** lsr x0, x1, #?32 +** ... +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\ttest_nonpst1\n} } } */ +small_vec +test_nonpst1 (struct nonpst1 x) +{ + return x.a[3]; +} + +union nonpst2 +{ + struct { + fixed_bool_t a[0]; + fixed_int32_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst2\n} } } */ +SEL2 (union, nonpst2) + +/* +** test_nonpst2: +** sub sp, sp, #16 +** stp x0, x1, \[sp\] +** ... +** ldr z0, \[sp\] +** add sp, sp, #?16 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst2\n} } } */ +svint32_t +test_nonpst2 (union nonpst2 x) +{ + return x.b; +} + +/* +** ret_nonpst2: +** mov x0, #?1 +** movk x0, #?0x3, lsl #?32 +** mov x1, #?5 +** movk x1, #?0x7, lsl #?32 +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst2\n} } } */ +union nonpst2 +ret_nonpst2 (void) +{ + return (union nonpst2) { { {}, 1, 3, 5, 7 } }; +} + +union nonpst3 +{ + struct { + unsigned int : 0; + fixed_bool_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst3\n} } } */ +SEL2 (union, nonpst3) + +/* +** test_nonpst3: +** sub sp, sp, #16 +** strh w0, \[sp, #?6\] +** ldr p0, \[sp, #3, mul vl\] +** add sp, sp, #?16 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst3\n} } } */ +svbool_t +test_nonpst3 (union nonpst3 x) +{ + return x.b; +} + +/* +** ret_nonpst3: { xfail *-*-* } +** mov w0, #?(?:0xffff|65535) +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst3\n} } } */ +union nonpst3 +ret_nonpst3 (void) +{ + return (union nonpst3) { { svptrue_b8 () } }; +} + +union nonpst4 +{ + struct { + struct {} empty; + fixed_uint64_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst4\n} } } */ +SEL2 (union, nonpst4) + +/* +** test_nonpst4: +** sub sp, sp, #16 +** stp x0, x1, \[sp\] +** ... +** ldr z0, \[sp\] +** add sp, sp, #?16 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst4\n} } } */ +svuint64_t +test_nonpst4 (union nonpst4 x) +{ + return x.b; +} + +/* +** ret_nonpst4: +** mov x0, 1 +** mov x1, 2 +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst4\n} } } */ +union nonpst4 +ret_nonpst4 (void) +{ + return (union nonpst4) { { {}, 1, 2 } }; +} + +struct nonpst5 +{ + union { + fixed_uint16_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst5\n} } } */ +SEL2 (struct, nonpst5) + +/* +** test_nonpst5: +** sub sp, sp, #16 +** stp x0, x1, \[sp\] +** ... +** ldr z0, \[sp\] +** add sp, sp, #?16 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst5\n} } } */ +svuint16_t +test_nonpst5 (struct nonpst5 x) +{ + return x.b; +} + +struct nonpst6 +{ + fixed_uint64_t b; + fixed_uint64_t *ptr; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst6\n} } } */ +SEL2 (struct, nonpst6) + +/* +** test_nonpst6: { target lp64 } +** ptrue (p[0-3])\.b, vl16 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst6: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-3])\.b, vl16 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst6\n} } } */ +svuint64_t +test_nonpst6 (struct nonpst6 x) +{ + return x.b; +} + +struct nonpst7 +{ + fixed_uint64_t b; + uint32_t foo __attribute__((vector_size(SVE_BYTES))); +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst7\n} } } */ +SEL2 (struct, nonpst7) + +/* +** test_nonpst7: { target lp64 } +** ptrue (p[0-3])\.b, vl16 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst7: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-3])\.b, vl16 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst7\n} } } */ +svuint64_t +test_nonpst7 (struct nonpst7 x) +{ + return x.b; +} + +typedef unsigned char tiny_vec __attribute__((vector_size(SVE_BYTES / 8))); + +struct nonpst8 +{ + tiny_vec a; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst8\n} } } */ +SEL2 (struct, nonpst8) + +/* +** test_nonpst8: +** ubfx x0, x0, 8, 8 +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\ttest_nonpst8\n} } } */ +unsigned int +test_nonpst8 (struct nonpst8 x) +{ + return x.a[1]; +} + +/* +** ret_nonpst8: +** ( +** sub sp, sp, #16 +** mov w0, #?513 +** add sp, sp, #?16 +** | +** mov w0, #?513 +** ) +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst8\n} } } */ +struct nonpst8 +ret_nonpst8 (void) +{ + return (struct nonpst8) { { 1, 2 } }; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_256.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_256.c new file mode 100644 index 0000000..fdfbec5 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_256.c @@ -0,0 +1,1231 @@ +/* { dg-options "-O -msve-vector-bits=256" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "struct.h" + +#define CONSUME(VAR) \ + { \ + register void *ptr_ asm ("x7") = &(VAR); \ + asm volatile ("" :: "r" (ptr_) : "memory"); \ + } + +#define SEL2(TAG, TYPE) \ + TAG TYPE \ + sel2_##TYPE (TAG TYPE x, TAG TYPE y) \ + { \ + return y; \ + } + +#define WRAP(TYPE) \ + struct wrap_##TYPE \ + { \ + TYPE data; \ + }; \ + SEL2 (struct, wrap_##TYPE) + +/* +** sel2_wrap_fixed_int8_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int8_t\n} } } */ +WRAP (fixed_int8_t); + +/* +** sel2_wrap_fixed_int16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int16_t\n} } } */ +WRAP (fixed_int16_t); + +/* +** sel2_wrap_fixed_int32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int32_t\n} } } */ +WRAP (fixed_int32_t); + +/* +** sel2_wrap_fixed_int64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int64_t\n} } } */ +WRAP (fixed_int64_t); + +/* +** sel2_wrap_fixed_uint8_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint8_t\n} } } */ +WRAP (fixed_uint8_t); + +/* +** sel2_wrap_fixed_uint16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint16_t\n} } } */ +WRAP (fixed_uint16_t); + +/* +** sel2_wrap_fixed_uint32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint32_t\n} } } */ +WRAP (fixed_uint32_t); + +/* +** sel2_wrap_fixed_uint64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint64_t\n} } } */ +WRAP (fixed_uint64_t); + +/* +** sel2_wrap_fixed_bfloat16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_bfloat16_t\n} } } */ +WRAP (fixed_bfloat16_t); + +/* +** sel2_wrap_fixed_float16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float16_t\n} } } */ +WRAP (fixed_float16_t); + +/* +** sel2_wrap_fixed_float32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float32_t\n} } } */ +WRAP (fixed_float32_t); + +/* +** sel2_wrap_fixed_float64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float64_t\n} } } */ +WRAP (fixed_float64_t); + +/* +** sel2_wrap_fixed_bool_t: +** mov p0\.b, p1\.b +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_bool_t\n} } } */ +WRAP (fixed_bool_t); + +struct pst_arr1 +{ + fixed_uint8_t u8[1]; +}; + +/* +** sel2_pst_arr1: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr1\n} } } */ +SEL2 (struct, pst_arr1) + +/* +** test_pst_arr1: +** eor z0\.b, z0\.b, #(?:0x)?1 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr1\n} } } */ +svuint8_t +test_pst_arr1 (struct pst_arr1 x) +{ + return sveor_x (svptrue_b8 (), x.u8[0], 1); +} + +struct pst_arr2 +{ + fixed_uint8_t u8[2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr2\n} } } */ +SEL2 (struct, pst_arr2) + +/* +** test_pst_arr2: +** sub z0\.b, z0\.b, z1\.b +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr2\n} } } */ +svuint8_t +test_pst_arr2 (struct pst_arr2 x) +{ + return svsub_x (svptrue_b8 (), x.u8[0], x.u8[1]); +} + +struct pst_arr3 +{ + fixed_uint16_t u16[3]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr3\n} } } */ +SEL2 (struct, pst_arr3) + +/* +** test_pst_arr3: +** sub z0\.h, z0\.h, z2\.h +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr3\n} } } */ +svuint16_t +test_pst_arr3 (struct pst_arr3 x) +{ + return svsub_x (svptrue_b8 (), x.u16[0], x.u16[2]); +} + +struct pst_arr4 +{ + fixed_uint32_t u32[4]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr4\n} } } */ +SEL2 (struct, pst_arr4) + +/* +** test_pst_arr4: +** sub z0\.s, z0\.s, z3\.s +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr4\n} } } */ +svuint32_t +test_pst_arr4 (struct pst_arr4 x) +{ + return svsub_x (svptrue_b8 (), x.u32[0], x.u32[3]); +} + +struct pst_arr5 +{ + fixed_uint64_t u64[2][2][2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr5\n} } } */ +SEL2 (struct, pst_arr5) + +/* +** test_pst_arr5: { target aarch64_little_endian } +** sub sp, sp, #256 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** str z3, \[sp, #3, mul vl\] +** str z4, \[sp, #4, mul vl\] +** str z5, \[sp, #5, mul vl\] +** str z6, \[sp, #6, mul vl\] +** str z7, \[sp, #7, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?256 +** ret +*/ +/* +** test_pst_arr5: { target aarch64_big_endian } +** sub sp, sp, #256 +** ptrue (p[0-3])\.b, vl32 +** st1d z0\.d, \1, \[sp\] +** st1d z1\.d, \1, \[sp, #1, mul vl\] +** st1d z2\.d, \1, \[sp, #2, mul vl\] +** st1d z3\.d, \1, \[sp, #3, mul vl\] +** st1d z4\.d, \1, \[sp, #4, mul vl\] +** st1d z5\.d, \1, \[sp, #5, mul vl\] +** st1d z6\.d, \1, \[sp, #6, mul vl\] +** st1d z7\.d, \1, \[sp, #7, mul vl\] +** mov ((x7, sp|w7, wsp)|w7, wsp) +** add sp, sp, #?256 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5\n} } } */ +void +test_pst_arr5 (struct pst_arr5 x) +{ + CONSUME (x); +} + +/* +** test_pst_arr5_x0: +** ( +** mov z0\.d, z7\.d +** mov (x7, x0|w7, w0) +** | +** mov (x7, x0|w7, w0) +** mov z0\.d, z7\.d +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_x0\n} } } */ +svint32_t +test_pst_arr5_x0 (svint32_t z0, struct pst_arr5 x, + svint32_t z1, svint32_t z2, svint32_t z3, svint32_t z4, + svint32_t z5, svint32_t z6, svint32_t z7) +{ + CONSUME (x); + return z7; +} + +/* +** test_pst_arr5_x7: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_x7\n} } } */ +svint32_t +test_pst_arr5_x7 (svint32_t z0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, struct pst_arr5 x) +{ + CONSUME (x); + return z0; +} + +/* +** test_pst_arr5_sp: { target lp64 } +** ldr x7, \[sp\] +** ret +*/ +/* +** test_pst_arr5_sp: { target ilp32 } +** ldr w7, \[sp(, 4)?\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_sp\n} } } */ +svint32_t +test_pst_arr5_sp (svint32_t z0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, struct pst_arr5 x) +{ + CONSUME (x); + return z0; +} + +struct pst_arr6 +{ + fixed_bool_t b[2][2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr6\n} } } */ +SEL2 (struct, pst_arr6) + +/* +** test_pst_arr6: +** ... +** brkpa p0\.b, p0/z, p2\.b, p3\.b +** ... +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6\n} } } */ +fixed_bool_t +test_pst_arr6 (struct pst_arr6 x) +{ + return svbrkpa_z (x.b[0][0], x.b[1][0], x.b[1][1]); +} + +/* +** test_pst_arr6_x0: +** ( +** mov p0\.b, p3\.b +** mov (x7, x0|w7, w0) +** | +** mov (x7, x0|w7, w0) +** mov p0\.b, p3\.b +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_x0\n} } } */ +fixed_bool_t +test_pst_arr6_x0 (svbool_t p0, struct pst_arr6 x, svbool_t p1, svbool_t p2, + svbool_t p3) +{ + CONSUME (x); + return p3; +} + +/* +** test_pst_arr6_x7: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_x7\n} } } */ +fixed_bool_t +test_pst_arr6_x7 (svbool_t p0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, struct pst_arr6 x) +{ + CONSUME (x); + return p0; +} + +/* +** test_pst_arr6_sp: { target lp64 } +** ldr x7, \[sp\] +** ret +*/ +/* +** test_pst_arr6_sp: { target ilp32 } +** ldr w7, \[sp(, 4)?\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_sp\n} } } */ +fixed_bool_t +test_pst_arr6_sp (svbool_t p0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, struct pst_arr6 x) +{ + CONSUME (x); + return p0; +} + +struct pst_uniform1 +{ + fixed_int8_t a, b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform1\n} } } */ +SEL2 (struct, pst_uniform1) + +/* +** test_pst_uniform1: { target aarch64_little_endian } +** sub sp, sp, #64 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?64 +** ret +*/ +/* +** test_pst_uniform1: { target aarch64_big_endian } +** sub sp, sp, #64 +** ptrue (p[0-3])\.b, vl32 +** st1b z0\.b, \1, \[sp\] +** st1b z1\.b, \1, \[sp, #1, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?64 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform1\n} } } */ +void +test_pst_uniform1 (struct pst_uniform1 x) +{ + CONSUME (x); +} + +struct pst_uniform2 +{ + fixed_int16_t a; + fixed_int16_t b[2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform2\n} } } */ +SEL2 (struct, pst_uniform2) + +/* +** test_pst_uniform2: { target aarch64_little_endian } +** sub sp, sp, #96 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?96 +** ret +*/ +/* +** test_pst_uniform2: { target aarch64_big_endian } +** sub sp, sp, #96 +** ptrue (p[0-3])\.b, vl32 +** st1h z0\.h, \1, \[sp\] +** st1h z1\.h, \1, \[sp, #1, mul vl\] +** st1h z2\.h, \1, \[sp, #2, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?96 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform2\n} } } */ +void +test_pst_uniform2 (struct pst_uniform2 x) +{ + CONSUME (x); +} + +struct pst_uniform3 +{ + fixed_int32_t a; + fixed_int32_t b[2]; + fixed_int32_t c; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform3\n} } } */ +SEL2 (struct, pst_uniform3) + +/* +** test_pst_uniform3: { target aarch64_little_endian } +** sub sp, sp, #128 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** str z3, \[sp, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?128 +** ret +*/ +/* +** test_pst_uniform3: { target aarch64_big_endian } +** sub sp, sp, #128 +** ptrue (p[0-3])\.b, vl32 +** st1w z0\.s, \1, \[sp\] +** st1w z1\.s, \1, \[sp, #1, mul vl\] +** st1w z2\.s, \1, \[sp, #2, mul vl\] +** st1w z3\.s, \1, \[sp, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?128 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform3\n} } } */ +void +test_pst_uniform3 (struct pst_uniform3 x) +{ + CONSUME (x); +} + +struct pst_uniform4 +{ + fixed_int32_t a __attribute__((aligned(SVE_BYTES * 2))); + fixed_int32_t b[3] __attribute__((aligned(SVE_BYTES * 2))); + fixed_int32_t c __attribute__((aligned(SVE_BYTES * 2))); +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform4\n} } } */ +SEL2 (struct, pst_uniform4) + +/* +** test_pst_uniform4: { target aarch64_little_endian } +** sub sp, sp, #304 +** add (x[0-9]+), sp, #?63 +** and x7, \1, #?(?:-64|4294967232) +** ptrue (p[0-7])\.b, vl32 +** st1w z0\.s, \2, \[x7\] +** add (x[0-9]+), x7, #?64 +** str z1, \[\3\] +** str z2, \[\3, #1, mul vl\] +** str z3, \[\3, #2, mul vl\] +** st1w z4\.s, \2, \[x7, #6, mul vl\] +** add sp, sp, #?304 +** ret +*/ +/* +** test_pst_uniform4: { target aarch64_big_endian } +** sub sp, sp, #304 +** add (x[0-9]+), sp, #?63 +** and x7, \1, #?(?:-64|4294967232) +** ptrue (p[0-7])\.b, vl32 +** st1w z0\.s, \2, \[x7\] +** add (x[0-9]+), x7, #?64 +** st1w z1\.s, \2, \[\3\] +** st1w z2\.s, \2, \[\3, #1, mul vl\] +** st1w z3\.s, \2, \[\3, #2, mul vl\] +** st1w z4\.s, \2, \[x7, #6, mul vl\] +** add sp, sp, #?304 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform4\n} } } */ +void +test_pst_uniform4 (struct pst_uniform4 x) +{ + CONSUME (x); +} + +struct pst_mixed1 +{ + fixed_bool_t p0; + fixed_bfloat16_t z0; + fixed_float16_t z1; + fixed_float32_t z2; + fixed_float64_t z3; + fixed_bool_t p1; + fixed_bool_t p2; + fixed_int8_t z4; + fixed_int16_t z5; + fixed_int32_t z6; + fixed_int64_t z7; + fixed_bool_t p3; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_mixed1\n} } } */ +SEL2 (struct, pst_mixed1) + +/* +** test_pst_mixed1: +** sub sp, sp, #304 +** str p0, \[sp\] +** ptrue p0\.b, vl32 +** add (x[0-9+]), sp, #?16 +** st1h z0\.h, p0, \[\1\] +** add (x[0-9+]), sp, #?48 +** st1h z1\.h, p0, \[\2\] +** add (x[0-9+]), sp, #?80 +** st1w z2\.s, p0, \[\3\] +** add (x[0-9+]), sp, #?112 +** st1d z3\.d, p0, \[\4\] +** str p1, \[sp, #36, mul vl\] +** str p2, \[sp, #37, mul vl\] +** st1b z4\.b, p0, \[sp, #5, mul vl\] +** st1h z5\.h, p0, \[sp, #6, mul vl\] +** st1w z6\.s, p0, \[sp, #7, mul vl\] +** ... +** st1d z7\.d, p0, [^\n]* +** ... +** str p3, \[sp, #72, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?304 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_mixed1\n} } } */ +void +test_pst_mixed1 (struct pst_mixed1 x) +{ + CONSUME (x); +} + +struct pst_mixed2 +{ + struct __attribute__ ((packed)) { + fixed_bool_t p; + fixed_int8_t z; + } a[3]; + fixed_int16_t b[1][1][1][4]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_mixed2\n} } } */ +SEL2 (struct, pst_mixed2) + +/* +** test_pst_mixed2: { target aarch64_little_endian } +** sub sp, sp, #240 +** str p0, \[sp\] +** ptrue (p[03])\.b, vl32 +** add (x[0-9]+), sp, #?4 +** st1b z0\.b, \1, \[\2\] +** str p1, \[sp, #9, mul vl\] +** add (x[0-9]+), sp, #?40 +** st1b z1\.b, \1, \[\3\] +** str p2, \[sp, #18, mul vl\] +** add (x[0-9]+), sp, #?76 +** st1b z2\.b, \1, \[\4\] +** add (x[0-9]+), sp, #?112 +** str z3, \[\5\] +** str z4, \[\5, #1, mul vl\] +** str z5, \[\5, #2, mul vl\] +** str z6, \[\5, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?240 +** ret +*/ +/* +** test_pst_mixed2: { target aarch64_big_endian } +** sub sp, sp, #240 +** str p0, \[sp\] +** ptrue (p[03])\.b, vl32 +** add (x[0-9]+), sp, #?4 +** st1b z0\.b, \1, \[\2\] +** str p1, \[sp, #9, mul vl\] +** add (x[0-9]+), sp, #?40 +** st1b z1\.b, \1, \[\3\] +** str p2, \[sp, #18, mul vl\] +** add (x[0-9]+), sp, #?76 +** st1b z2\.b, \1, \[\4\] +** add (x[0-9]+), sp, #?112 +** st1h z3\.h, \1, \[\5\] +** st1h z4\.h, \1, \[\5, #1, mul vl\] +** st1h z5\.h, \1, \[\5, #2, mul vl\] +** st1h z6\.h, \1, \[\5, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?240 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_mixed2\n} } } */ +void +test_pst_mixed2 (struct pst_mixed2 x) +{ + CONSUME (x); +} + +struct pst_big1 +{ + fixed_int8_t a[9]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big1\n} } } */ +SEL2 (struct, pst_big1) + +/* +** test_pst_big1_a: { target lp64 } +** ptrue (p[0-7])\.b, vl32 +** ld1b z0\.b, \1/z, \[x0\] +** ret +*/ +/* +** test_pst_big1_a: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl32 +** ld1b z0\.b, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big1_a\n} } } */ +svint8_t +test_pst_big1_a (struct pst_big1 x) +{ + return x.a[0]; +} + +/* +** test_pst_big1_b: { target lp64 } +** add x7, x0, #?256 +** ret +*/ +/* +** test_pst_big1_b: { target ilp32 } +** add w7, w0, #?256 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big1_b\n} } } */ +svint8_t +test_pst_big1_b (struct pst_big1 x) +{ + CONSUME (x.a[8]); +} + +struct pst_big2 +{ + fixed_bool_t a[5]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big2\n} } } */ +SEL2 (struct, pst_big2) + +/* +** test_pst_big2_a: { target lp64 } +** ldr p0, \[x0\] +** ret +*/ +/* +** test_pst_big2_a: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big2_a\n} } } */ +svbool_t +test_pst_big2_a (struct pst_big2 x) +{ + return x.a[0]; +} + +/* +** test_pst_big2_b: { target lp64 } +** ldr p0, \[x0, #4, mul vl\] +** ret +*/ +/* +** test_pst_big2_b: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #4, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big2_b\n} } } */ +svbool_t +test_pst_big2_b (struct pst_big2 x) +{ + return x.a[4]; +} + +struct pst_big3 +{ + fixed_bool_t p0; + fixed_int8_t a[2]; + fixed_bool_t p1; + fixed_bool_t p2; + fixed_bool_t p3; + fixed_int8_t b[6]; + fixed_bool_t p4; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big3\n} } } */ +SEL2 (struct, pst_big3) + +/* +** test_pst_big3_a: { target lp64 } +** ldr p0, \[x0\] +** ret +*/ +/* +** test_pst_big3_a: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_a\n} } } */ +svbool_t +test_pst_big3_a (struct pst_big3 x) +{ + return x.p0; +} + +/* +** test_pst_big3_b: { target lp64 } +** ldr p0, \[x0, #20, mul vl\] +** ret +*/ +/* +** test_pst_big3_b: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #20, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_b\n} } } */ +svbool_t +test_pst_big3_b (struct pst_big3 x) +{ + return x.p1; +} + +/* +** test_pst_big3_c: { target lp64 } +** ldr p0, \[x0, #21, mul vl\] +** ret +*/ +/* +** test_pst_big3_c: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #21, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_c\n} } } */ +svbool_t +test_pst_big3_c (struct pst_big3 x) +{ + return x.p2; +} + +/* +** test_pst_big3_d: { target lp64 } +** ldr p0, \[x0, #72, mul vl\] +** ret +*/ +/* +** test_pst_big3_d: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #72, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_d\n} } } */ +svbool_t +test_pst_big3_d (struct pst_big3 x) +{ + return x.p4; +} + +/* +** test_pst_big3_e: { target lp64 } +** add (x[0-9]+), x0, #?16 +** ptrue (p[0-7])\.b, vl32 +** ld1b z0\.b, \2/z, \[\1\] +** ret +*/ +/* +** test_pst_big3_e: { target ilp32 } +** uxtw x0, w0 +** add (x[0-9]+), x0, #?16 +** ptrue (p[0-7])\.b, vl32 +** ld1b z0\.b, \2/z, \[\1\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_e\n} } } */ +svint8_t +test_pst_big3_e (struct pst_big3 x) +{ + return x.a[0]; +} + +/* +** test_pst_big3_f: { target lp64 } +** ptrue (p[0-7])\.b, vl32 +** ld1b z0\.b, \1/z, \[x0, #4, mul vl\] +** ret +*/ +/* +** test_pst_big3_f: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl32 +** ld1b z0\.b, \1/z, \[x0, #4, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_f\n} } } */ +svint8_t +test_pst_big3_f (struct pst_big3 x) +{ + return x.b[1]; +} + +struct pst_zero1 +{ + fixed_bool_t a[0]; + fixed_int32_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero1\n} } } */ +SEL2 (struct, pst_zero1) + +/* +** test_pst_zero1: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero1\n} } } */ +svint32_t +test_pst_zero1 (struct pst_zero1 x) +{ + return x.b; +} + +struct pst_zero2 +{ + unsigned int : 0; + fixed_bool_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero2\n} } } */ +SEL2 (struct, pst_zero2) + +/* +** test_pst_zero2: +** ( +** sub sp, sp, #16 +** add sp, sp, #?16 +** | +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero2\n} } } */ +svbool_t +test_pst_zero2 (struct pst_zero2 x) +{ + return x.b; +} + +struct pst_zero3 +{ + struct {} empty; + fixed_uint64_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero3\n} } } */ +SEL2 (struct, pst_zero3) + +/* +** test_pst_zero3: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero3\n} } } */ +svuint64_t +test_pst_zero3 (struct pst_zero3 x) +{ + return x.b; +} + +typedef unsigned char small_vec __attribute__((vector_size(SVE_BYTES / 4))); + +struct nonpst1 +{ + small_vec a[4]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst1\n} } } */ +SEL2 (struct, nonpst1) + +/* +** test_nonpst1: +** mov v0\.8b, v3\.8b +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\ttest_nonpst1\n} } } */ +small_vec +test_nonpst1 (struct nonpst1 x) +{ + return x.a[3]; +} + +union nonpst2 +{ + struct { + fixed_bool_t a[0]; + fixed_int32_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst2\n} } } */ +SEL2 (union, nonpst2) + +/* +** test_nonpst2: { target lp64 } +** ptrue (p[0-7])\.b, vl32 +** ld1w z0\.s, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst2: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl32 +** ld1w z0\.s, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst2\n} } } */ +svint32_t +test_nonpst2 (union nonpst2 x) +{ + return x.b; +} + +/* +** ret_nonpst2: +** ptrue (p[0-7])\.b, vl32 +** index (z[0-9]+\.s), #1, #2 +** st1w \2, \1, \[x8\] +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst2\n} } } */ +union nonpst2 +ret_nonpst2 (void) +{ + return (union nonpst2) { { {}, 1, 3, 5, 7, 9, 11, 13, 15 } }; +} + +union nonpst3 +{ + struct { + unsigned int : 0; + fixed_bool_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst3\n} } } */ +SEL2 (union, nonpst3) + +/* +** test_nonpst3: { target aarch64_little_endian } +** sub sp, sp, #16 +** str w0, \[sp, #?12\] +** ldr p0, \[sp, #3, mul vl\] +** add sp, sp, #?16 +** ret +*/ +/* +** test_nonpst3: { target aarch64_big_endian } +** sub sp, sp, #16 +** ( +** lsr (x[0-9]+), x0, #?32 +** str \1, \[sp\] +** ldr p0, \[sp, #1, mul vl\] +** | +** str x0, \[sp\] +** ldr p0, \[sp\] +** ) +** add sp, sp, #?16 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst3\n} } } */ +svbool_t +test_nonpst3 (union nonpst3 x) +{ + return x.b; +} + +/* +** ret_nonpst3: { target aarch64_little_endian } +** mov w0, -1 +** ret +*/ +/* +** ret_nonpst3: { target aarch64_big_endian } +** mov x0, -4294967296 +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst3\n} } } */ +union nonpst3 +ret_nonpst3 (void) +{ + return (union nonpst3) { { svptrue_b8 () } }; +} + +union nonpst4 +{ + struct { + struct {} empty; + fixed_uint64_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst4\n} } } */ +SEL2 (union, nonpst4) + +/* +** test_nonpst4: { target lp64 } +** ptrue (p[0-7])\.b, vl32 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst4: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl32 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst4\n} } } */ +svuint64_t +test_nonpst4 (union nonpst4 x) +{ + return x.b; +} + +/* +** ret_nonpst4: +** ptrue (p[0-7])\.b, vl32 +** index (z[0-9]+\.d), #1, #1 +** st1d \2, \1, \[x8\] +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst4\n} } } */ +union nonpst4 +ret_nonpst4 (void) +{ + return (union nonpst4) { { {}, 1, 2, 3, 4 } }; +} + +struct nonpst5 +{ + union { + fixed_uint16_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst5\n} } } */ +SEL2 (struct, nonpst5) + +/* +** test_nonpst5: { target lp64 } +** ptrue (p[0-7])\.b, vl32 +** ld1h z0\.h, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst5: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl32 +** ld1h z0\.h, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst5\n} } } */ +svuint16_t +test_nonpst5 (struct nonpst5 x) +{ + return x.b; +} + +struct nonpst6 +{ + fixed_uint64_t b; + fixed_uint64_t *ptr; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst6\n} } } */ +SEL2 (struct, nonpst6) + +/* +** test_nonpst6: { target lp64 } +** ptrue (p[0-3])\.b, vl32 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst6: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-3])\.b, vl32 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst6\n} } } */ +svuint64_t +test_nonpst6 (struct nonpst6 x) +{ + return x.b; +} + +struct nonpst7 +{ + fixed_uint64_t b; + uint32_t foo __attribute__((vector_size(SVE_BYTES))); +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst7\n} } } */ +SEL2 (struct, nonpst7) + +/* +** test_nonpst7: { target lp64 } +** ptrue (p[0-3])\.b, vl32 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst7: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-3])\.b, vl32 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst7\n} } } */ +svuint64_t +test_nonpst7 (struct nonpst7 x) +{ + return x.b; +} + +typedef unsigned char tiny_vec __attribute__((vector_size(SVE_BYTES / 8))); + +struct nonpst8 +{ + tiny_vec a; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst8\n} } } */ +SEL2 (struct, nonpst8) + +/* +** test_nonpst8: { target aarch64_little_endian } +** ubfx x0, x0, 8, 8 +** ret +*/ +/* +** test_nonpst8: { target aarch64_big_endian } +** ( +** sub sp, sp, #16 +** ubfx x0, x0, 48, 8 +** add sp, sp, #?16 +** | +** ubfx x0, x0, 48, 8 +** ) +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\ttest_nonpst8\n} } } */ +unsigned int +test_nonpst8 (struct nonpst8 x) +{ + return x.a[1]; +} + +/* +** ret_nonpst8: { target aarch64_little_endian } +** ( +** sub sp, sp, #16 +** mov w0, #?513 +** movk w0, #?0x403, lsl #?16 +** add sp, sp, #?16 +** | +** mov w0, #?513 +** movk w0, #?0x403, lsl #?16 +** ) +** ret +*/ +/* +** ret_nonpst8: { target aarch64_big_endian } +** mov x0, #?3315714752512 +** movk x0, #?0x102, lsl #?48 +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst8\n} } } */ +struct nonpst8 +ret_nonpst8 (void) +{ + return (struct nonpst8) { { 1, 2, 3, 4 } }; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_512.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_512.c new file mode 100644 index 0000000..e03fd73 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/struct_3_512.c @@ -0,0 +1,1197 @@ +/* { dg-options "-O -msve-vector-bits=512" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "struct.h" + +#define CONSUME(VAR) \ + { \ + register void *ptr_ asm ("x7") = &(VAR); \ + asm volatile ("" :: "r" (ptr_) : "memory"); \ + } + +#define SEL2(TAG, TYPE) \ + TAG TYPE \ + sel2_##TYPE (TAG TYPE x, TAG TYPE y) \ + { \ + return y; \ + } + +#define WRAP(TYPE) \ + struct wrap_##TYPE \ + { \ + TYPE data; \ + }; \ + SEL2 (struct, wrap_##TYPE) + +/* +** sel2_wrap_fixed_int8_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int8_t\n} } } */ +WRAP (fixed_int8_t); + +/* +** sel2_wrap_fixed_int16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int16_t\n} } } */ +WRAP (fixed_int16_t); + +/* +** sel2_wrap_fixed_int32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int32_t\n} } } */ +WRAP (fixed_int32_t); + +/* +** sel2_wrap_fixed_int64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_int64_t\n} } } */ +WRAP (fixed_int64_t); + +/* +** sel2_wrap_fixed_uint8_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint8_t\n} } } */ +WRAP (fixed_uint8_t); + +/* +** sel2_wrap_fixed_uint16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint16_t\n} } } */ +WRAP (fixed_uint16_t); + +/* +** sel2_wrap_fixed_uint32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint32_t\n} } } */ +WRAP (fixed_uint32_t); + +/* +** sel2_wrap_fixed_uint64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_uint64_t\n} } } */ +WRAP (fixed_uint64_t); + +/* +** sel2_wrap_fixed_bfloat16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_bfloat16_t\n} } } */ +WRAP (fixed_bfloat16_t); + +/* +** sel2_wrap_fixed_float16_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float16_t\n} } } */ +WRAP (fixed_float16_t); + +/* +** sel2_wrap_fixed_float32_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float32_t\n} } } */ +WRAP (fixed_float32_t); + +/* +** sel2_wrap_fixed_float64_t: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_float64_t\n} } } */ +WRAP (fixed_float64_t); + +/* +** sel2_wrap_fixed_bool_t: +** mov p0\.b, p1\.b +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_wrap_fixed_bool_t\n} } } */ +WRAP (fixed_bool_t); + +struct pst_arr1 +{ + fixed_uint8_t u8[1]; +}; + +/* +** sel2_pst_arr1: +** mov z0\.d, z1\.d +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr1\n} } } */ +SEL2 (struct, pst_arr1) + +/* +** test_pst_arr1: +** eor z0\.b, z0\.b, #(?:0x)?1 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr1\n} } } */ +svuint8_t +test_pst_arr1 (struct pst_arr1 x) +{ + return sveor_x (svptrue_b8 (), x.u8[0], 1); +} + +struct pst_arr2 +{ + fixed_uint8_t u8[2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr2\n} } } */ +SEL2 (struct, pst_arr2) + +/* +** test_pst_arr2: +** sub z0\.b, z0\.b, z1\.b +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr2\n} } } */ +svuint8_t +test_pst_arr2 (struct pst_arr2 x) +{ + return svsub_x (svptrue_b8 (), x.u8[0], x.u8[1]); +} + +struct pst_arr3 +{ + fixed_uint16_t u16[3]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr3\n} } } */ +SEL2 (struct, pst_arr3) + +/* +** test_pst_arr3: +** sub z0\.h, z0\.h, z2\.h +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr3\n} } } */ +svuint16_t +test_pst_arr3 (struct pst_arr3 x) +{ + return svsub_x (svptrue_b8 (), x.u16[0], x.u16[2]); +} + +struct pst_arr4 +{ + fixed_uint32_t u32[4]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr4\n} } } */ +SEL2 (struct, pst_arr4) + +/* +** test_pst_arr4: +** sub z0\.s, z0\.s, z3\.s +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr4\n} } } */ +svuint32_t +test_pst_arr4 (struct pst_arr4 x) +{ + return svsub_x (svptrue_b8 (), x.u32[0], x.u32[3]); +} + +struct pst_arr5 +{ + fixed_uint64_t u64[2][2][2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr5\n} } } */ +SEL2 (struct, pst_arr5) + +/* +** test_pst_arr5: { target aarch64_little_endian } +** sub sp, sp, #512 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** str z3, \[sp, #3, mul vl\] +** str z4, \[sp, #4, mul vl\] +** str z5, \[sp, #5, mul vl\] +** str z6, \[sp, #6, mul vl\] +** str z7, \[sp, #7, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?512 +** ret +*/ +/* +** test_pst_arr5: { target aarch64_big_endian } +** sub sp, sp, #512 +** ptrue (p[0-3])\.b, vl64 +** st1d z0\.d, \1, \[sp\] +** st1d z1\.d, \1, \[sp, #1, mul vl\] +** st1d z2\.d, \1, \[sp, #2, mul vl\] +** st1d z3\.d, \1, \[sp, #3, mul vl\] +** st1d z4\.d, \1, \[sp, #4, mul vl\] +** st1d z5\.d, \1, \[sp, #5, mul vl\] +** st1d z6\.d, \1, \[sp, #6, mul vl\] +** st1d z7\.d, \1, \[sp, #7, mul vl\] +** mov ((x7, sp|w7, wsp)|w7, wsp) +** add sp, sp, #?512 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5\n} } } */ +void +test_pst_arr5 (struct pst_arr5 x) +{ + CONSUME (x); +} + +/* +** test_pst_arr5_x0: +** ( +** mov z0\.d, z7\.d +** mov (x7, x0|w7, w0) +** | +** mov (x7, x0|w7, w0) +** mov z0\.d, z7\.d +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_x0\n} } } */ +svint32_t +test_pst_arr5_x0 (svint32_t z0, struct pst_arr5 x, + svint32_t z1, svint32_t z2, svint32_t z3, svint32_t z4, + svint32_t z5, svint32_t z6, svint32_t z7) +{ + CONSUME (x); + return z7; +} + +/* +** test_pst_arr5_x7: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_x7\n} } } */ +svint32_t +test_pst_arr5_x7 (svint32_t z0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, struct pst_arr5 x) +{ + CONSUME (x); + return z0; +} + +/* +** test_pst_arr5_sp: { target lp64 } +** ldr x7, \[sp\] +** ret +*/ +/* +** test_pst_arr5_sp: { target ilp32 } +** ldr w7, \[sp(, 4)?\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr5_sp\n} } } */ +svint32_t +test_pst_arr5_sp (svint32_t z0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, struct pst_arr5 x) +{ + CONSUME (x); + return z0; +} + +struct pst_arr6 +{ + fixed_bool_t b[2][2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_arr6\n} } } */ +SEL2 (struct, pst_arr6) + +/* +** test_pst_arr6: +** ... +** brkpa p0\.b, p0/z, p2\.b, p3\.b +** ... +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6\n} } } */ +fixed_bool_t +test_pst_arr6 (struct pst_arr6 x) +{ + return svbrkpa_z (x.b[0][0], x.b[1][0], x.b[1][1]); +} + +/* +** test_pst_arr6_x0: +** ( +** mov p0\.b, p3\.b +** mov (x7, x0|w7, w0) +** | +** mov (x7, x0|w7, w0) +** mov p0\.b, p3\.b +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_x0\n} } } */ +fixed_bool_t +test_pst_arr6_x0 (svbool_t p0, struct pst_arr6 x, svbool_t p1, svbool_t p2, + svbool_t p3) +{ + CONSUME (x); + return p3; +} + +/* +** test_pst_arr6_x7: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_x7\n} } } */ +fixed_bool_t +test_pst_arr6_x7 (svbool_t p0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, struct pst_arr6 x) +{ + CONSUME (x); + return p0; +} + +/* +** test_pst_arr6_sp: { target lp64 } +** ldr x7, \[sp\] +** ret +*/ +/* +** test_pst_arr6_sp: { target ilp32 } +** ldr w7, \[sp(, 4)?\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_arr6_sp\n} } } */ +fixed_bool_t +test_pst_arr6_sp (svbool_t p0, int x0, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, struct pst_arr6 x) +{ + CONSUME (x); + return p0; +} + +struct pst_uniform1 +{ + fixed_int8_t a, b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform1\n} } } */ +SEL2 (struct, pst_uniform1) + +/* +** test_pst_uniform1: { target aarch64_little_endian } +** sub sp, sp, #128 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?128 +** ret +*/ +/* +** test_pst_uniform1: { target aarch64_big_endian } +** sub sp, sp, #128 +** ptrue (p[0-3])\.b, vl64 +** st1b z0\.b, \1, \[sp\] +** st1b z1\.b, \1, \[sp, #1, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?128 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform1\n} } } */ +void +test_pst_uniform1 (struct pst_uniform1 x) +{ + CONSUME (x); +} + +struct pst_uniform2 +{ + fixed_int16_t a; + fixed_int16_t b[2]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform2\n} } } */ +SEL2 (struct, pst_uniform2) + +/* +** test_pst_uniform2: { target aarch64_little_endian } +** sub sp, sp, #192 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?192 +** ret +*/ +/* +** test_pst_uniform2: { target aarch64_big_endian } +** sub sp, sp, #192 +** ptrue (p[0-3])\.b, vl64 +** st1h z0\.h, \1, \[sp\] +** st1h z1\.h, \1, \[sp, #1, mul vl\] +** st1h z2\.h, \1, \[sp, #2, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?192 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform2\n} } } */ +void +test_pst_uniform2 (struct pst_uniform2 x) +{ + CONSUME (x); +} + +struct pst_uniform3 +{ + fixed_int32_t a; + fixed_int32_t b[2]; + fixed_int32_t c; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform3\n} } } */ +SEL2 (struct, pst_uniform3) + +/* +** test_pst_uniform3: { target aarch64_little_endian } +** sub sp, sp, #256 +** str z0, \[sp\] +** str z1, \[sp, #1, mul vl\] +** str z2, \[sp, #2, mul vl\] +** str z3, \[sp, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?256 +** ret +*/ +/* +** test_pst_uniform3: { target aarch64_big_endian } +** sub sp, sp, #256 +** ptrue (p[0-3])\.b, vl64 +** st1w z0\.s, \1, \[sp\] +** st1w z1\.s, \1, \[sp, #1, mul vl\] +** st1w z2\.s, \1, \[sp, #2, mul vl\] +** st1w z3\.s, \1, \[sp, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?256 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform3\n} } } */ +void +test_pst_uniform3 (struct pst_uniform3 x) +{ + CONSUME (x); +} + +struct pst_uniform4 +{ + fixed_int32_t a __attribute__((aligned(SVE_BYTES * 2))); + fixed_int32_t b[3] __attribute__((aligned(SVE_BYTES * 2))); + fixed_int32_t c __attribute__((aligned(SVE_BYTES * 2))); +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_uniform4\n} } } */ +SEL2 (struct, pst_uniform4) + +/* +** test_pst_uniform4: { target aarch64_little_endian } +** sub sp, sp, #624 +** add (x[0-9]+), sp, #?127 +** and x7, \1, #?(?:-128|4294967168) +** ptrue (p[0-7])\.b, vl64 +** st1w z0\.s, \2, \[x7\] +** add (x[0-9]+), x7, #?128 +** str z1, \[\3\] +** str z2, \[\3, #1, mul vl\] +** str z3, \[\3, #2, mul vl\] +** st1w z4\.s, \2, \[x7, #6, mul vl\] +** add sp, sp, #?624 +** ret +*/ +/* +** test_pst_uniform4: { target aarch64_big_endian } +** sub sp, sp, #624 +** add (x[0-9]+), sp, #?127 +** and x7, \1, #?(?:-128|4294967168) +** ptrue (p[0-7])\.b, vl64 +** st1w z0\.s, \2, \[x7\] +** add (x[0-9]+), x7, #?128 +** st1w z1\.s, \2, \[\3\] +** st1w z2\.s, \2, \[\3, #1, mul vl\] +** st1w z3\.s, \2, \[\3, #2, mul vl\] +** st1w z4\.s, \2, \[x7, #6, mul vl\] +** add sp, sp, #?624 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_uniform4\n} } } */ +void +test_pst_uniform4 (struct pst_uniform4 x) +{ + CONSUME (x); +} + +struct pst_mixed1 +{ + fixed_bool_t p0; + fixed_bfloat16_t z0; + fixed_float16_t z1; + fixed_float32_t z2; + fixed_float64_t z3; + fixed_bool_t p1; + fixed_bool_t p2; + fixed_int8_t z4; + fixed_int16_t z5; + fixed_int32_t z6; + fixed_int64_t z7; + fixed_bool_t p3; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_mixed1\n} } } */ +SEL2 (struct, pst_mixed1) + +/* +** test_pst_mixed1: +** sub sp, sp, #560 +** str p0, \[sp\] +** ptrue p0\.b, vl64 +** add (x[0-9+]), sp, #?16 +** st1h z0\.h, p0, \[\1\] +** add (x[0-9+]), sp, #?80 +** st1h z1\.h, p0, \[\2\] +** add (x[0-9+]), sp, #?144 +** st1w z2\.s, p0, \[\3\] +** add (x[0-9+]), sp, #?208 +** st1d z3\.d, p0, \[\4\] +** str p1, \[sp, #34, mul vl\] +** str p2, \[sp, #35, mul vl\] +** add (x[0-9+]), sp, #?288 +** st1b z4\.b, p0, \[\5\] +** add (x[0-9+]), sp, #?352 +** st1h z5\.h, p0, \[\6\] +** add (x[0-9+]), sp, #?416 +** st1w z6\.s, p0, \[\7\] +** add (x[0-9+]), sp, #?480 +** st1d z7\.d, p0, \[\8\] +** str p3, \[sp, #68, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?560 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_mixed1\n} } } */ +void +test_pst_mixed1 (struct pst_mixed1 x) +{ + CONSUME (x); +} + +struct pst_mixed2 +{ + struct __attribute__ ((packed)) { + fixed_bool_t p; + fixed_int8_t z; + } a[3]; + fixed_int16_t b[1][1][1][4]; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_mixed2\n} } } */ +SEL2 (struct, pst_mixed2) + +/* +** test_pst_mixed2: { target aarch64_little_endian } +** sub sp, sp, #480 +** str p0, \[sp\] +** ptrue (p[03])\.b, vl64 +** add (x[0-9]+), sp, #?8 +** st1b z0\.b, \1, \[\2\] +** str p1, \[sp, #9, mul vl\] +** add (x[0-9]+), sp, #?80 +** st1b z1\.b, \1, \[\3\] +** str p2, \[sp, #18, mul vl\] +** add (x[0-9]+), sp, #?152 +** st1b z2\.b, \1, \[\4\] +** add (x[0-9]+), sp, #?224 +** str z3, \[\5\] +** str z4, \[\5, #1, mul vl\] +** str z5, \[\5, #2, mul vl\] +** str z6, \[\5, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?480 +** ret +*/ +/* +** test_pst_mixed2: { target aarch64_big_endian } +** sub sp, sp, #480 +** str p0, \[sp\] +** ptrue (p[03])\.b, vl64 +** add (x[0-9]+), sp, #?8 +** st1b z0\.b, \1, \[\2\] +** str p1, \[sp, #9, mul vl\] +** add (x[0-9]+), sp, #?80 +** st1b z1\.b, \1, \[\3\] +** str p2, \[sp, #18, mul vl\] +** add (x[0-9]+), sp, #?152 +** st1b z2\.b, \1, \[\4\] +** add (x[0-9]+), sp, #?224 +** st1h z3\.h, \1, \[\5\] +** st1h z4\.h, \1, \[\5, #1, mul vl\] +** st1h z5\.h, \1, \[\5, #2, mul vl\] +** st1h z6\.h, \1, \[\5, #3, mul vl\] +** mov (x7, sp|w7, wsp) +** add sp, sp, #?480 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_mixed2\n} } } */ +void +test_pst_mixed2 (struct pst_mixed2 x) +{ + CONSUME (x); +} + +struct pst_big1 +{ + fixed_int8_t a[9]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big1\n} } } */ +SEL2 (struct, pst_big1) + +/* +** test_pst_big1_a: { target lp64 } +** ptrue (p[0-7])\.b, vl64 +** ld1b z0\.b, \1/z, \[x0\] +** ret +*/ +/* +** test_pst_big1_a: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl64 +** ld1b z0\.b, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big1_a\n} } } */ +svint8_t +test_pst_big1_a (struct pst_big1 x) +{ + return x.a[0]; +} + +/* +** test_pst_big1_b: { target lp64 } +** add x7, x0, #?512 +** ret +*/ +/* +** test_pst_big1_b: { target ilp32 } +** add w7, w0, #?512 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big1_b\n} } } */ +svint8_t +test_pst_big1_b (struct pst_big1 x) +{ + CONSUME (x.a[8]); +} + +struct pst_big2 +{ + fixed_bool_t a[5]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big2\n} } } */ +SEL2 (struct, pst_big2) + +/* +** test_pst_big2_a: { target lp64 } +** ldr p0, \[x0\] +** ret +*/ +/* +** test_pst_big2_a: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big2_a\n} } } */ +svbool_t +test_pst_big2_a (struct pst_big2 x) +{ + return x.a[0]; +} + +/* +** test_pst_big2_b: { target lp64 } +** ldr p0, \[x0, #4, mul vl\] +** ret +*/ +/* +** test_pst_big2_b: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #4, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big2_b\n} } } */ +svbool_t +test_pst_big2_b (struct pst_big2 x) +{ + return x.a[4]; +} + +struct pst_big3 +{ + fixed_bool_t p0; + fixed_int8_t a[2]; + fixed_bool_t p1; + fixed_bool_t p2; + fixed_bool_t p3; + fixed_int8_t b[6]; + fixed_bool_t p4; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_big3\n} } } */ +SEL2 (struct, pst_big3) + +/* +** test_pst_big3_a: { target lp64 } +** ldr p0, \[x0\] +** ret +*/ +/* +** test_pst_big3_a: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_a\n} } } */ +svbool_t +test_pst_big3_a (struct pst_big3 x) +{ + return x.p0; +} + +/* +** test_pst_big3_b: { target lp64 } +** ldr p0, \[x0, #18, mul vl\] +** ret +*/ +/* +** test_pst_big3_b: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #18, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_b\n} } } */ +svbool_t +test_pst_big3_b (struct pst_big3 x) +{ + return x.p1; +} + +/* +** test_pst_big3_c: { target lp64 } +** ldr p0, \[x0, #19, mul vl\] +** ret +*/ +/* +** test_pst_big3_c: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #19, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_c\n} } } */ +svbool_t +test_pst_big3_c (struct pst_big3 x) +{ + return x.p2; +} + +/* +** test_pst_big3_d: { target lp64 } +** ldr p0, \[x0, #70, mul vl\] +** ret +*/ +/* +** test_pst_big3_d: { target ilp32 } +** uxtw x0, w0 +** ldr p0, \[x0, #70, mul vl\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_d\n} } } */ +svbool_t +test_pst_big3_d (struct pst_big3 x) +{ + return x.p4; +} + +/* +** test_pst_big3_e: { target lp64 } +** add (x[0-9]+), x0, #?16 +** ptrue (p[0-7])\.b, vl64 +** ld1b z0\.b, \2/z, \[\1\] +** ret +*/ +/* +** test_pst_big3_e: { target ilp32 } +** uxtw x0, w0 +** add (x[0-9]+), x0, #?16 +** ptrue (p[0-7])\.b, vl64 +** ld1b z0\.b, \2/z, \[\1\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_e\n} } } */ +svint8_t +test_pst_big3_e (struct pst_big3 x) +{ + return x.a[0]; +} + +/* +** test_pst_big3_f: { target lp64 } +** add (x[0-9]+), x0, #?240 +** ptrue (p[0-7])\.b, vl64 +** ld1b z0\.b, \2/z, \[\1\] +** ret +*/ +/* +** test_pst_big3_f: { target ilp32 } +** uxtw x0, w0 +** add (x[0-9]+), x0, #?240 +** ptrue (p[0-7])\.b, vl64 +** ld1b z0\.b, \2/z, \[\1\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_big3_f\n} } } */ +svint8_t +test_pst_big3_f (struct pst_big3 x) +{ + return x.b[1]; +} + +struct pst_zero1 +{ + fixed_bool_t a[0]; + fixed_int32_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero1\n} } } */ +SEL2 (struct, pst_zero1) + +/* +** test_pst_zero1: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero1\n} } } */ +svint32_t +test_pst_zero1 (struct pst_zero1 x) +{ + return x.b; +} + +struct pst_zero2 +{ + unsigned int : 0; + fixed_bool_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero2\n} } } */ +SEL2 (struct, pst_zero2) + +/* +** test_pst_zero2: +** ( +** sub sp, sp, #16 +** add sp, sp, #?16 +** | +** ) +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero2\n} } } */ +svbool_t +test_pst_zero2 (struct pst_zero2 x) +{ + return x.b; +} + +struct pst_zero3 +{ + struct {} empty; + fixed_uint64_t b; +}; +/* { dg-final { scan-assembler {\t\.variant_pcs\tsel2_pst_zero3\n} } } */ +SEL2 (struct, pst_zero3) + +/* +** test_pst_zero3: +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_pst_zero3\n} } } */ +svuint64_t +test_pst_zero3 (struct pst_zero3 x) +{ + return x.b; +} + +typedef unsigned char small_vec __attribute__((vector_size(SVE_BYTES / 4))); + +struct nonpst1 +{ + small_vec a[4]; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst1\n} } } */ +SEL2 (struct, nonpst1) + +/* +** test_nonpst1: +** mov v0\.16b, v3\.16b +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\ttest_nonpst1\n} } } */ +small_vec +test_nonpst1 (struct nonpst1 x) +{ + return x.a[3]; +} + +union nonpst2 +{ + struct { + fixed_bool_t a[0]; + fixed_int32_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst2\n} } } */ +SEL2 (union, nonpst2) + +/* +** test_nonpst2: { target lp64 } +** ptrue (p[0-7])\.b, vl64 +** ld1w z0\.s, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst2: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl64 +** ld1w z0\.s, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst2\n} } } */ +svint32_t +test_nonpst2 (union nonpst2 x) +{ + return x.b; +} + +/* +** ret_nonpst2: +** ptrue (p[0-7])\.b, vl64 +** index (z[0-9]+\.s), #1, #2 +** st1w \2, \1, \[x8\] +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst2\n} } } */ +union nonpst2 +ret_nonpst2 (void) +{ + return (union nonpst2) { { {}, 1, 3, 5, 7, 9, 11, 13, 15, + 17, 19, 21, 23, 25, 27, 29, 31 } }; +} + +union nonpst3 +{ + struct { + unsigned int : 0; + fixed_bool_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst3\n} } } */ +SEL2 (union, nonpst3) + +/* +** test_nonpst3: +** sub sp, sp, #16 +** str x0, \[sp, #?8\] +** ldr p0, \[sp, #1, mul vl\] +** add sp, sp, #?16 +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst3\n} } } */ +svbool_t +test_nonpst3 (union nonpst3 x) +{ + return x.b; +} + +/* +** ret_nonpst3: +** mov x0, -1 +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst3\n} } } */ +union nonpst3 +ret_nonpst3 (void) +{ + return (union nonpst3) { { svptrue_b8 () } }; +} + +union nonpst4 +{ + struct { + struct {} empty; + fixed_uint64_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst4\n} } } */ +SEL2 (union, nonpst4) + +/* +** test_nonpst4: { target lp64 } +** ptrue (p[0-7])\.b, vl64 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst4: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl64 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst4\n} } } */ +svuint64_t +test_nonpst4 (union nonpst4 x) +{ + return x.b; +} + +/* +** ret_nonpst4: +** ptrue (p[0-7])\.b, vl64 +** index (z[0-9]+\.d), #1, #1 +** st1d \2, \1, \[x8\] +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst4\n} } } */ +union nonpst4 +ret_nonpst4 (void) +{ + return (union nonpst4) { { {}, 1, 2, 3, 4, 5, 6, 7, 8 } }; +} + +struct nonpst5 +{ + union { + fixed_uint16_t b; + }; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst5\n} } } */ +SEL2 (struct, nonpst5) + +/* +** test_nonpst5: { target lp64 } +** ptrue (p[0-7])\.b, vl64 +** ld1h z0\.h, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst5: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-7])\.b, vl64 +** ld1h z0\.h, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst5\n} } } */ +svuint16_t +test_nonpst5 (struct nonpst5 x) +{ + return x.b; +} + +struct nonpst6 +{ + fixed_uint64_t b; + fixed_uint64_t *ptr; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst6\n} } } */ +SEL2 (struct, nonpst6) + +/* +** test_nonpst6: { target lp64 } +** ptrue (p[0-3])\.b, vl64 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst6: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-3])\.b, vl64 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst6\n} } } */ +svuint64_t +test_nonpst6 (struct nonpst6 x) +{ + return x.b; +} + +struct nonpst7 +{ + fixed_uint64_t b; + uint32_t foo __attribute__((vector_size(SVE_BYTES))); +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst7\n} } } */ +SEL2 (struct, nonpst7) + +/* +** test_nonpst7: { target lp64 } +** ptrue (p[0-3])\.b, vl64 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* +** test_nonpst7: { target ilp32 } +** uxtw x0, w0 +** ptrue (p[0-3])\.b, vl64 +** ld1d z0\.d, \1/z, \[x0\] +** ret +*/ +/* { dg-final { scan-assembler {\t\.variant_pcs\ttest_nonpst7\n} } } */ +svuint64_t +test_nonpst7 (struct nonpst7 x) +{ + return x.b; +} + +typedef unsigned char tiny_vec __attribute__((vector_size(SVE_BYTES / 8))); + +struct nonpst8 +{ + tiny_vec a; +}; +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tsel2_pst_nonpst8\n} } } */ +SEL2 (struct, nonpst8) + +/* +** test_nonpst8: { target aarch64_little_endian } +** umov w0, v0\.b\[1\] +** ret +*/ +/* +** test_nonpst8: { target aarch64_big_endian } +** umov w0, v0\.b\[6\] +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\ttest_nonpst8\n} } } */ +unsigned int +test_nonpst8 (struct nonpst8 x) +{ + return x.a[1]; +} + +/* +** ret_nonpst8: +** movi v0\.8b, 0x1 +** ret +*/ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tret_nonpst8\n} } } */ +struct nonpst8 +ret_nonpst8 (void) +{ + return (struct nonpst8) { { 1, 1, 1, 1, 1, 1, 1, 1 } }; +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index e42d0ea..3758bb3 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -4695,8 +4695,12 @@ proc aarch64_sve_hw_bits { bits } { # Return true if this is an AArch64 target that can run SVE code and # if its SVE vectors have exactly 256 bits. -proc check_effective_target_aarch64_sve256_hw { } { - return [aarch64_sve_hw_bits 256] +foreach N { 128 256 512 1024 2048 } { + eval [string map [list N $N] { + proc check_effective_target_aarch64_sveN_hw { } { + return [aarch64_sve_hw_bits N] + } + }] } proc check_effective_target_arm_neonv2_hw { } { -- cgit v1.1 From 33c45e51b4914008064d9b77f2c1fc0eea1ad060 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 9 Apr 2020 21:21:24 +0200 Subject: cselib, var-tracking: Improve debug info after the cselib sp tracking changes [PR94495] On the https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94495#c5 testcase GCC emits worse debug info after the PR92264 cselib.c changes. The difference at -O2 -g -dA in the assembly is (when ignoring debug info): # DEBUG g => [argp] # DEBUG k => [argp+0x20] # DEBUG j => [argp+0x18] # DEBUG a => di # DEBUG b => si # DEBUG c => dx # DEBUG d => cx # DEBUG h => [argp+0x8] # DEBUG e => r8 # DEBUG i => [argp+0x10] # DEBUG f => r9 ... .LVL4: + # DEBUG h => [sp+0x10] + # DEBUG i => [sp+0x18] + # DEBUG j => [sp+0x20] + # DEBUG k => [sp+0x28] # DEBUG c => entry_value # SUCC: EXIT [always] count:1073741824 (estimated locally) ret .LVL5: + # DEBUG k => [argp+0x20] # DEBUG a => bx # DEBUG b => si # DEBUG c => dx # DEBUG d => cx # DEBUG e => r8 # DEBUG f => r9 + # DEBUG h => [argp+0x8] + # DEBUG i => [argp+0x10] + # DEBUG j => [argp+0x18] This means that before the changes, h, i, j, k could be all expressed in DW_AT_location directly with DW_OP_fbreg , but now we need to use a location list, where in the first part of the function and last part of the function (everything except the ret instruction) we use that DW_OP_fbreg , but for the single ret instruction we instead say those values live in something pointed by stack pointer + offset. It is true, but only because stack pointer + offset is equal to DW_OP_fbreg at that point. The var-tracking pass has for !frame_pointer_needed functions code to canonicalize stack pointer uses in the insns before it hands it over to cselib to cfa_base_rtx + offset depending on the stack depth at each point. The problem is that on the last epilogue pop insn (the one right before ret) the canonicalization is sp = argp - 8 and add_stores records a MO_VAL_SET operation for that argp - 8 value (which is the SP_DERIVED_VALUE_P VALUE the cselib changes canonicalize sp based accesses on) and thus var-tracking from that point onwards tracks that that VALUE (2:2) now lives in sp. At the end of function it of course needs to forget it again (or it would need on any changes to sp). But when processing that uop, we note that the VALUE has changed and anything based on it changed too, so emit changes for everything. Before that var-tracking itself doesn't track it in any register, so uses cselib and cselib knows through the permanent equivs how to compute it using argp (i.e. what will be DW_OP_fbreg). The following fix has two parts. One is it detects if cselib can compute a certain VALUE using the cfa_base_rtx and for such VALUEs doesn't add the MO_VAL_SET operation, as it is better to express them using cfa_base_rtx rather than temporarily through something else. And the other is make sure we reuse in !frame_pointer_needed the single SP_DERIVED_VALUE_P VALUE in other extended basic blocks too (and other VALUEs) too. This can be done because we have computed the stack depths at the start of each basic block in vt_stack_adjustments and while cselib_reset_table is called at the end of each extended bb, which throws away all hard registers (but the magic cfa_base_rtx) and so can hint cselib.c at the start of the ebb what VALUE the sp hard reg has. That means fewer VALUEs during var-tracking and more importantly that they will all have the cfa_base_rtx + offset equivalency. I have performed 4 bootstraps+regtests (x86_64-linux and i686-linux, each with this patch (that is the new cselib + var-tracking variant) and once with that patch reverted as well as all other cselib.c changes from this month; once that bootstrapped, I've reapplied the cselib.c changes and this patch and rebuilt cc1plus, so that the content is comparable, but built with the pre-Apr 2 cselib.c+var-tracking.c (that is the old cselib one)). Below are readelf -WS cc1plus | grep debug_ filtered to only have debug sections whose size actually changed, followed by dwlocstat results on cc1plus. This shows that there was about 3% shrink in those .debug* sections for 32-bit and 1% shrink for 64-bit, with minor variable coverage changes one or the other way that are IMHO insignificant. 32-bit old cselib [33] .debug_info PROGBITS 00000000 29139c0 710e5fa 00 0 0 1 [34] .debug_abbrev PROGBITS 00000000 9a21fba 21ad6d 00 0 0 1 [35] .debug_line PROGBITS 00000000 9c3cd27 1a05e56 00 0 0 1 [36] .debug_str PROGBITS 00000000 b642b7d 7cad09 01 MS 0 0 1 [37] .debug_loc PROGBITS 00000000 be0d886 5792627 00 0 0 1 [38] .debug_ranges PROGBITS 00000000 1159fead e57218 00 0 0 1 sum 263075589B 32-bit new cselib + var-tracking [33] .debug_info PROGBITS 00000000 29129c0 71065d1 00 0 0 1 [34] .debug_abbrev PROGBITS 00000000 9a18f91 21af28 00 0 0 1 [35] .debug_line PROGBITS 00000000 9c33eb9 195dffc 00 0 0 1 [36] .debug_str PROGBITS 00000000 b591eb5 7cace0 01 MS 0 0 1 [37] .debug_loc PROGBITS 00000000 bd5cb95 50185bf 00 0 0 1 [38] .debug_ranges PROGBITS 00000000 10d75154 e57068 00 0 0 1 sum 254515196B (8560393B smaller) 64-bit old cselib [33] .debug_info PROGBITS 0000000000000000 25e64b0 84d7cc9 00 0 0 1 [34] .debug_abbrev PROGBITS 0000000000000000 aabe179 225e2d 00 0 0 1 [35] .debug_line PROGBITS 0000000000000000 ace3fa6 19a3505 00 0 0 1 [37] .debug_loc PROGBITS 0000000000000000 ce6e960 89707bc 00 0 0 1 [38] .debug_ranges PROGBITS 0000000000000000 157df11c 1c59a70 00 0 0 1 sum 342274599B 64-bit new cselib + var-tracking [33] .debug_info PROGBITS 0000000000000000 25e64b0 84d8e86 00 0 0 1 [34] .debug_abbrev PROGBITS 0000000000000000 aabf336 225e8d 00 0 0 1 [35] .debug_line PROGBITS 0000000000000000 ace51c3 199ded5 00 0 0 1 [37] .debug_loc PROGBITS 0000000000000000 ce6a54d 85f62da 00 0 0 1 [38] .debug_ranges PROGBITS 0000000000000000 15460827 1c59a20 00 0 0 1 sum 338610402B (3664197B smaller) 32-bit old cselib cov% samples cumul 0..10 1231599/48% 1231599/48% 11..20 31017/1% 1262616/49% 21..30 36495/1% 1299111/51% 31..40 35846/1% 1334957/52% 41..50 47179/1% 1382136/54% 51..60 41203/1% 1423339/56% 61..70 65504/2% 1488843/58% 71..80 59656/2% 1548499/61% 81..90 104399/4% 1652898/65% 91..100 882231/34% 2535129/100% 32-bit new cselib + var-tracking cov% samples cumul 0..10 1230542/48% 1230542/48% 11..20 30385/1% 1260927/49% 21..30 36393/1% 1297320/51% 31..40 36053/1% 1333373/52% 41..50 47670/1% 1381043/54% 51..60 41599/1% 1422642/56% 61..70 65902/2% 1488544/58% 71..80 59911/2% 1548455/61% 81..90 104607/4% 1653062/65% 91..100 882067/34% 2535129/100% 64-bit old cselib cov% samples cumul 0..10 1233211/48% 1233211/48% 11..20 31120/1% 1264331/49% 21..30 39230/1% 1303561/51% 31..40 38887/1% 1342448/52% 41..50 47519/1% 1389967/54% 51..60 45264/1% 1435231/56% 61..70 69431/2% 1504662/59% 71..80 62114/2% 1566776/61% 81..90 104587/4% 1671363/65% 91..100 876085/34% 2547448/100% 64-bit new cselib + var-tracking cov% samples cumul 0..10 1233471/48% 1233471/48% 11..20 31093/1% 1264564/49% 21..30 39217/1% 1303781/51% 31..40 38851/1% 1342632/52% 41..50 47488/1% 1390120/54% 51..60 45224/1% 1435344/56% 61..70 69409/2% 1504753/59% 71..80 62140/2% 1566893/61% 81..90 104616/4% 1671509/65% 91..100 875939/34% 2547448/100% 2020-04-09 Jakub Jelinek PR debug/94495 * cselib.h (cselib_record_sp_cfa_base_equiv, cselib_sp_derived_value_p): Declare. * cselib.c (cselib_record_sp_cfa_base_equiv, cselib_sp_derived_value_p): New functions. * var-tracking.c (add_stores): Don't record MO_VAL_SET for cselib_sp_derived_value_p values. (vt_initialize): Call cselib_record_sp_cfa_base_equiv at the start of extended basic blocks other than the first one for !frame_pointer_needed functions. --- gcc/ChangeLog | 13 ++++++++++++ gcc/cselib.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/cselib.h | 2 ++ gcc/var-tracking.c | 23 ++++++++++++++++++++++ 4 files changed, 96 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1066146..e5e2290 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2020-04-09 Jakub Jelinek + + PR debug/94495 + * cselib.h (cselib_record_sp_cfa_base_equiv, + cselib_sp_derived_value_p): Declare. + * cselib.c (cselib_record_sp_cfa_base_equiv, + cselib_sp_derived_value_p): New functions. + * var-tracking.c (add_stores): Don't record MO_VAL_SET for + cselib_sp_derived_value_p values. + (vt_initialize): Call cselib_record_sp_cfa_base_equiv at the + start of extended basic blocks other than the first one + for !frame_pointer_needed functions. + 2020-04-09 Richard Sandiford * doc/sourcebuild.texi (aarch64_sve_hw, aarch64_sve128_hw) diff --git a/gcc/cselib.c b/gcc/cselib.c index 0de6836..3692feb 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -2665,6 +2665,64 @@ cselib_have_permanent_equivalences (void) return cselib_any_perm_equivs; } +/* Record stack_pointer_rtx to be equal to + (plus:P cfa_base_preserved_val offset). Used by var-tracking + at the start of basic blocks for !frame_pointer_needed functions. */ + +void +cselib_record_sp_cfa_base_equiv (HOST_WIDE_INT offset, rtx_insn *insn) +{ + rtx sp_derived_value = NULL_RTX; + for (struct elt_loc_list *l = cfa_base_preserved_val->locs; l; l = l->next) + if (GET_CODE (l->loc) == VALUE + && SP_DERIVED_VALUE_P (l->loc)) + { + sp_derived_value = l->loc; + break; + } + else if (GET_CODE (l->loc) == PLUS + && GET_CODE (XEXP (l->loc, 0)) == VALUE + && SP_DERIVED_VALUE_P (XEXP (l->loc, 0)) + && CONST_INT_P (XEXP (l->loc, 1))) + { + sp_derived_value = XEXP (l->loc, 0); + offset = offset + UINTVAL (XEXP (l->loc, 1)); + break; + } + if (sp_derived_value == NULL_RTX) + return; + cselib_val *val + = cselib_lookup_from_insn (plus_constant (Pmode, sp_derived_value, offset), + Pmode, 1, VOIDmode, insn); + if (val != NULL) + cselib_record_set (stack_pointer_rtx, val, NULL); +} + +/* Return true if V is SP_DERIVED_VALUE_P (or SP_DERIVED_VALUE_P + CONST_INT) + that can be expressed using cfa_base_preserved_val + CONST_INT. */ + +bool +cselib_sp_derived_value_p (cselib_val *v) +{ + if (!SP_DERIVED_VALUE_P (v->val_rtx)) + for (struct elt_loc_list *l = v->locs; l; l = l->next) + if (GET_CODE (l->loc) == PLUS + && GET_CODE (XEXP (l->loc, 0)) == VALUE + && SP_DERIVED_VALUE_P (XEXP (l->loc, 0)) + && CONST_INT_P (XEXP (l->loc, 1))) + v = CSELIB_VAL_PTR (XEXP (l->loc, 0)); + if (!SP_DERIVED_VALUE_P (v->val_rtx)) + return false; + for (struct elt_loc_list *l = v->locs; l; l = l->next) + if (l->loc == cfa_base_preserved_val->val_rtx) + return true; + else if (GET_CODE (l->loc) == PLUS + && XEXP (l->loc, 0) == cfa_base_preserved_val->val_rtx + && CONST_INT_P (XEXP (l->loc, 1))) + return true; + return false; +} + /* There is no good way to determine how many elements there can be in a PARALLEL. Since it's fairly cheap, use a really large number. */ #define MAX_SETS (FIRST_PSEUDO_REGISTER * 2) diff --git a/gcc/cselib.h b/gcc/cselib.h index 1628e13..adc6cc0 100644 --- a/gcc/cselib.h +++ b/gcc/cselib.h @@ -104,6 +104,8 @@ extern void cselib_add_permanent_equiv (cselib_val *, rtx, rtx_insn *); extern bool cselib_have_permanent_equivalences (void); extern void cselib_set_value_sp_based (cselib_val *); extern bool cselib_sp_based_value_p (cselib_val *); +extern void cselib_record_sp_cfa_base_equiv (HOST_WIDE_INT, rtx_insn *); +extern bool cselib_sp_derived_value_p (cselib_val *); extern void dump_cselib_table (FILE *); diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 8274df9..0d39326 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -6117,6 +6117,19 @@ add_stores (rtx loc, const_rtx expr, void *cuip) && preserve) cselib_set_value_sp_based (v); + /* Don't record MO_VAL_SET for VALUEs that can be described using + cfa_base_rtx or cfa_base_rtx + CONST_INT, cselib already knows + all the needed equivalences and they shouldn't change depending + on which register holds that VALUE in some instruction. */ + if (!frame_pointer_needed + && cfa_base_rtx + && cselib_sp_derived_value_p (v)) + { + if (preserve) + preserve_value (v); + return; + } + nloc = replace_expr_with_values (oloc); if (nloc) oloc = nloc; @@ -10154,6 +10167,7 @@ vt_initialize (void) vt_add_function_parameters (); + bool record_sp_value = false; FOR_EACH_BB_FN (bb, cfun) { rtx_insn *insn; @@ -10168,6 +10182,15 @@ vt_initialize (void) cselib_get_next_uid ()); } + if (MAY_HAVE_DEBUG_BIND_INSNS + && cfa_base_rtx + && !frame_pointer_needed + && record_sp_value) + cselib_record_sp_cfa_base_equiv (-cfa_base_offset + - VTI (bb)->in.stack_adjust, + BB_HEAD (bb)); + record_sp_value = true; + first_bb = bb; for (;;) { -- cgit v1.1 From 07432a807ede1c629f0f52aa5f8bf00012929e88 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Thu, 9 Apr 2020 20:52:20 +0100 Subject: MSP430: Indiciate that the epilogue_helper insn does not fallthru This fixes an ICE in rtl_verify_fallthru, at cfgrtl.c:2970 gcc.c-torture/execute/20071210-1.c for -mcpu=msp430 at -O2 and above. The epilogue_helper insn was treated as a regular insn which will fallthru, so when a barrier is emitted after it, RTL verification failed as rtl_verify_fallthru. gcc/ChangeLog: 2020-04-09 Jozef Lawrynowicz * config/msp430/msp430.c (msp430_expand_epilogue): Use emit_jump_insn when to emit the epilogue_helper insn. * config/msp430/msp430.md (epilogue_helper): Add a return insn to the RTL pattern. --- gcc/ChangeLog | 7 +++++++ gcc/config/msp430/msp430.c | 2 +- gcc/config/msp430/msp430.md | 4 +++- 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e5e2290..bce700e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2020-04-09 Jozef Lawrynowicz + + * config/msp430/msp430.c (msp430_expand_epilogue): Use emit_jump_insn + when to emit the epilogue_helper insn. + * config/msp430/msp430.md (epilogue_helper): Add a return insn to the + RTL pattern. + 2020-04-09 Jakub Jelinek PR debug/94495 diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index cde14c8..e0d2d73 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -2587,7 +2587,7 @@ msp430_expand_epilogue (int is_eh) && helper_n > 1 && !is_eh) { - emit_insn (gen_epilogue_helper (GEN_INT (helper_n))); + emit_jump_insn (gen_epilogue_helper (GEN_INT (helper_n))); return; } else diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md index 815d122..b6602fb 100644 --- a/gcc/config/msp430/msp430.md +++ b/gcc/config/msp430/msp430.md @@ -1130,7 +1130,9 @@ ) (define_insn "epilogue_helper" - [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)] + [(set (pc) + (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)) + (return)] "" "BR%Q0\t#__mspabi_func_epilog_%J0" ) -- cgit v1.1 From ef529765234bea7893bd56f3ab3a2da7695f6b21 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 8 Apr 2020 23:59:30 -0400 Subject: c++: constexpr static data member instantiation [PR94523] Here due to my recent change to store_init_value we were expanding the initializer of aw knowing that we were initializing aw. When cxx_eval_call_expression finished the constructor, it wanted to look up the value of aw to set TREE_READONLY on it, but we haven't set DECL_INITIAL yet, so decl_constant_value tried to instantiate the initializer again. And infinite recursion. Stopped by optimizing the case of asking for the value of ctx->object, which is ctx->value. It also would have worked to look in the values hash table, so let's move that up before decl_constant_value as well. gcc/cp/ChangeLog 2020-04-09 Jason Merrill PR c++/94523 * constexpr.c (cxx_eval_constant_expression) [VAR_DECL]: Look at ctx->object and ctx->global->values first. --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/constexpr.c | 13 +++++++++---- gcc/testsuite/g++.dg/cpp1y/constexpr-static1.C | 10 ++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-static1.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cdd9b52..49246e8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-04-09 Jason Merrill + + PR c++/94523 + * constexpr.c (cxx_eval_constant_expression) [VAR_DECL]: Look at + ctx->object and ctx->global->values first. + 2020-04-09 Marek Polacek PR c++/93790 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 96497ab..5793430 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5485,6 +5485,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, CONST_DECL for aggregate constants. */ if (lval) return t; + else if (t == ctx->object) + return ctx->ctor; + if (VAR_P (t)) + if (tree *p = ctx->global->values.get (t)) + if (*p != NULL_TREE) + { + r = *p; + break; + } if (COMPLETE_TYPE_P (TREE_TYPE (t)) && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false)) { @@ -5499,10 +5508,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (TREE_CODE (r) == TARGET_EXPR && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR) r = TARGET_EXPR_INITIAL (r); - if (VAR_P (r)) - if (tree *p = ctx->global->values.get (r)) - if (*p != NULL_TREE) - r = *p; if (DECL_P (r)) { if (!ctx->quiet) diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-static1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-static1.C new file mode 100644 index 0000000..f39ed21 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-static1.C @@ -0,0 +1,10 @@ +// PR c++/94523 +// { dg-do compile { target c++14 } } + +template using b = a; +struct d { + char ao; + template constexpr d(ap) : ao{} {} +}; +template struct e { static constexpr auto aw = d(au...); }; +template b ax(e<1>::aw); -- cgit v1.1 From 44facdb79f2d96ea8f5f93cfd440b3d0351d9bdb Mon Sep 17 00:00:00 2001 From: Fritz Reese Date: Thu, 9 Apr 2020 16:55:44 -0400 Subject: PR fortran/87923 -- fix ICE when resolving I/O tags and simplify io.c 2020-04-06 Fritz Reese This patch reorganizes I/O checking code. Checks which were done in the matching phase which do not affect the match result are moved to the resolution phase. Checks which were duplicated in both the matching phase and resolution phase have been reduced to one check in the resolution phase. Another section of code which used a global async_io_dt flag to check for and assign the asynchronous attribute to variables used in asynchronous I/O has been simplified. Furthermore, this patch improves error reporting and expands test coverage of I/O tags: - "TAG must be an initialization expression" reported by io.c (check_io_constraints) is replaced with an error from expr.c (gfc_reduce_init_expr) indicating _why_ the expression is not a valid initialization expression. - Several distinct error messages regarding the check for scalar + character + default kind have been unified to one message reported by resolve_tag or check_*_constraints. gcc/fortran/ChangeLog: 2020-04-09 Fritz Reese PR fortran/87923 * gfortran.h (gfc_resolve_open, gfc_resolve_close): Add locus parameter. (gfc_resolve_dt): Add code parameter. * io.c (async_io_dt, check_char_variable, is_char_type): Removed. (resolve_tag_format): Add locus to error message regarding zero-sized array in FORMAT tag. (check_open_constraints, check_close_constraints): New functions called at resolution time. (gfc_match_open, gfc_match_close, match_io): Move checks which don't affect the match result to new functions check_open_constraints, check_close_constraints, check_io_constraints. (gfc_resolve_open, gfc_resolve_close): Call new functions check_open_constraints, check_close_constraints after all tags have been independently resolved. Remove duplicate constraints which are already verified by resolve_tag. Explicitly pass locus to all error reports. (compare_to_allowed_values): Add locus parameter and provide explicit locus all error reports. (match_open_element, match_close_element, match_file_element, match_dt_element, match_inquire_element): Remove redundant special cases for ASYNCHRONOUS and IOMSG tags. (gfc_resolve_dt): Remove redundant special case for format expression. Call check_io_constraints, forwarding an I/O list as the io_code parameter if present. (check_io_constraints): Change return type to bool. Pass explicit locus to error reports. Move generic checks after tag-specific checks, since errors are no longer buffered. Move simplification of format string to match_io. Remove redundant checks which are verified by resolve_tag. Remove usage of async_io_dt flag and explicitly mark symbols used in asynchronous I/O with the asynchronous attribute. * resolve.c (resolve_transfer, resolve_fl_namelist): Remove checks for async_io_dt flag. This is now done in io.c (check_io_constraints). (gfc_resolve_code): Pass code locus to gfc_resolve_open, gfc_resolve_close, gfc_resolve_dt. gcc/testsuite/ChangeLog: 2020-04-09 Fritz Reese PR fortran/87923 * gfortran.dg/f2003_io_8.f03: Fix expected error messages. * gfortran.dg/io_constraints_8.f90: Likewise. * gfortran.dg/iomsg_2.f90: Likewise. * gfortran.dg/pr66725.f90: Likewise. * gfortran.dg/pr88205.f90: Likewise. * gfortran.dg/write_check4.f90: Likewise. * gfortran.dg/asynchronous_5.f03: New test. * gfortran.dg/io_constraints_15.f90: Likewise. * gfortran.dg/io_constraints_16.f90: Likewise. * gfortran.dg/io_constraints_17.f90: Likewise. * gfortran.dg/io_constraints_18.f90: Likewise. * gfortran.dg/io_tags_1.f90: Likewise. * gfortran.dg/io_tags_10.f90: Likewise. * gfortran.dg/io_tags_2.f90: Likewise. * gfortran.dg/io_tags_3.f90: Likewise. * gfortran.dg/io_tags_4.f90: Likewise. * gfortran.dg/io_tags_5.f90: Likewise. * gfortran.dg/io_tags_6.f90: Likewise. * gfortran.dg/io_tags_7.f90: Likewise. * gfortran.dg/io_tags_8.f90: Likewise. * gfortran.dg/io_tags_9.f90: Likewise. * gfortran.dg/write_check5.f90: Likewise. --- gcc/fortran/ChangeLog | 40 ++ gcc/fortran/gfortran.h | 7 +- gcc/fortran/io.c | 858 +++++++++++------------- gcc/fortran/resolve.c | 14 +- gcc/testsuite/ChangeLog | 26 + gcc/testsuite/gfortran.dg/asynchronous_5.f03 | 43 ++ gcc/testsuite/gfortran.dg/f2003_io_8.f03 | 2 +- gcc/testsuite/gfortran.dg/io_constraints_15.f90 | 11 + gcc/testsuite/gfortran.dg/io_constraints_16.f90 | 11 + gcc/testsuite/gfortran.dg/io_constraints_17.f90 | 11 + gcc/testsuite/gfortran.dg/io_constraints_18.f90 | 9 + gcc/testsuite/gfortran.dg/io_constraints_8.f90 | 2 +- gcc/testsuite/gfortran.dg/io_tags_1.f90 | 19 + gcc/testsuite/gfortran.dg/io_tags_10.f90 | 103 +++ gcc/testsuite/gfortran.dg/io_tags_2.f90 | 30 + gcc/testsuite/gfortran.dg/io_tags_3.f90 | 17 + gcc/testsuite/gfortran.dg/io_tags_4.f90 | 17 + gcc/testsuite/gfortran.dg/io_tags_5.f90 | 17 + gcc/testsuite/gfortran.dg/io_tags_6.f90 | 175 +++++ gcc/testsuite/gfortran.dg/io_tags_7.f90 | 103 +++ gcc/testsuite/gfortran.dg/io_tags_8.f90 | 18 + gcc/testsuite/gfortran.dg/io_tags_9.f90 | 18 + gcc/testsuite/gfortran.dg/iomsg_2.f90 | 36 +- gcc/testsuite/gfortran.dg/pr66725.f90 | 42 +- gcc/testsuite/gfortran.dg/pr88205.f90 | 6 +- gcc/testsuite/gfortran.dg/write_check4.f90 | 4 +- gcc/testsuite/gfortran.dg/write_check5.f90 | 24 + 27 files changed, 1124 insertions(+), 539 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/asynchronous_5.f03 create mode 100644 gcc/testsuite/gfortran.dg/io_constraints_15.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_constraints_16.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_constraints_17.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_constraints_18.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_1.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_10.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_2.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_3.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_4.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_5.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_6.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_7.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_8.f90 create mode 100644 gcc/testsuite/gfortran.dg/io_tags_9.f90 create mode 100644 gcc/testsuite/gfortran.dg/write_check5.f90 (limited to 'gcc') diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index fdbb8da..e2ebb96 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,43 @@ +2020-04-09 Fritz Reese + + PR fortran/87923 + * gfortran.h (gfc_resolve_open, gfc_resolve_close): Add + locus parameter. + (gfc_resolve_dt): Add code parameter. + * io.c (async_io_dt, check_char_variable, is_char_type): Removed. + (resolve_tag_format): Add locus to error message regarding + zero-sized array in FORMAT tag. + (check_open_constraints, check_close_constraints): New functions + called at resolution time. + (gfc_match_open, gfc_match_close, match_io): Move checks which don't + affect the match result to new functions check_open_constraints, + check_close_constraints, check_io_constraints. + (gfc_resolve_open, gfc_resolve_close): Call new functions + check_open_constraints, check_close_constraints after all tags have + been independently resolved. Remove duplicate constraints which are + already verified by resolve_tag. Explicitly pass locus to all error + reports. + (compare_to_allowed_values): Add locus parameter and provide + explicit locus all error reports. + (match_open_element, match_close_element, match_file_element, + match_dt_element, match_inquire_element): Remove redundant special + cases for ASYNCHRONOUS and IOMSG tags. + (gfc_resolve_dt): Remove redundant special case for format + expression. Call check_io_constraints, forwarding an I/O list as + the io_code parameter if present. + (check_io_constraints): Change return type to bool. Pass explicit + locus to error reports. Move generic checks after tag-specific + checks, since errors are no longer buffered. Move simplification of + format string to match_io. Remove redundant checks which are + verified by resolve_tag. Remove usage of async_io_dt flag and + explicitly mark symbols used in asynchronous I/O with the + asynchronous attribute. + * resolve.c (resolve_transfer, resolve_fl_namelist): Remove checks + for async_io_dt flag. This is now done in io.c. + (check_io_constraints). + (gfc_resolve_code): Pass code locus to gfc_resolve_open, + gfc_resolve_close, gfc_resolve_dt. + 2020-04-07 Fritz Reese Steven G. Kargl diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 70a6405..0d77386 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -3476,18 +3476,17 @@ bool gfc_compare_actual_formal (gfc_actual_arglist **, gfc_formal_arglist *, extern gfc_st_label format_asterisk; void gfc_free_open (gfc_open *); -bool gfc_resolve_open (gfc_open *); +bool gfc_resolve_open (gfc_open *, locus *); void gfc_free_close (gfc_close *); -bool gfc_resolve_close (gfc_close *); +bool gfc_resolve_close (gfc_close *, locus *); void gfc_free_filepos (gfc_filepos *); bool gfc_resolve_filepos (gfc_filepos *, locus *); void gfc_free_inquire (gfc_inquire *); bool gfc_resolve_inquire (gfc_inquire *); void gfc_free_dt (gfc_dt *); -bool gfc_resolve_dt (gfc_dt *, locus *); +bool gfc_resolve_dt (gfc_code *, gfc_dt *, locus *); void gfc_free_wait (gfc_wait *); bool gfc_resolve_wait (gfc_wait *); -extern bool async_io_dt; /* module.c */ void gfc_module_init_2 (void); diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c index 59cd9ce..e066666 100644 --- a/gcc/fortran/io.c +++ b/gcc/fortran/io.c @@ -112,10 +112,6 @@ static gfc_dt *current_dt; #define RESOLVE_TAG(x, y) if (!resolve_tag (x, y)) return false; -/* Are we currently processing an asynchronous I/O statement? */ - -bool async_io_dt; - /**************** Fortran 95 FORMAT parser *****************/ /* FORMAT tokens returned by format_lex(). */ @@ -1427,36 +1423,6 @@ gfc_match_format (void) } -/* Check for a CHARACTER variable. The check for scalar is done in - resolve_tag. */ - -static bool -check_char_variable (gfc_expr *e) -{ - if (e->expr_type != EXPR_VARIABLE || e->ts.type != BT_CHARACTER) - { - gfc_error("IOMSG must be a scalar-default-char-variable at %L", &e->where); - return false; - } - return true; -} - - -static bool -is_char_type (const char *name, gfc_expr *e) -{ - gfc_resolve_expr (e); - - if (e->ts.type != BT_CHARACTER) - { - gfc_error ("%s requires a scalar-default-char-expr at %L", - name, &e->where); - return false; - } - return true; -} - - /* Match an expression I/O tag of some sort. */ static match @@ -1725,7 +1691,8 @@ resolve_tag_format (gfc_expr *e) if (e->value.constructor == NULL) { - gfc_error ("FORMAT tag at %C cannot be a zero-sized array"); + gfc_error ("FORMAT tag at %L cannot be a zero-sized array", + &e->where); return false; } @@ -1919,16 +1886,12 @@ match_open_element (gfc_open *open) match m; m = match_etag (&tag_e_async, &open->asynchronous); - if (m == MATCH_YES && !is_char_type ("ASYNCHRONOUS", open->asynchronous)) - return MATCH_ERROR; if (m != MATCH_NO) return m; m = match_etag (&tag_unit, &open->unit); if (m != MATCH_NO) return m; m = match_etag (&tag_iomsg, &open->iomsg); - if (m == MATCH_YES && !check_char_variable (open->iomsg)) - return MATCH_ERROR; if (m != MATCH_NO) return m; m = match_out_tag (&tag_iostat, &open->iostat); @@ -2041,12 +2004,22 @@ gfc_free_open (gfc_open *open) } +static int +compare_to_allowed_values (const char *specifier, const char *allowed[], + const char *allowed_f2003[], + const char *allowed_gnu[], gfc_char_t *value, + const char *statement, bool warn, locus *where, + int *num = NULL); + + +static bool +check_open_constraints (gfc_open *open, locus *where); + /* Resolve everything in a gfc_open structure. */ bool -gfc_resolve_open (gfc_open *open) +gfc_resolve_open (gfc_open *open, locus *where) { - RESOLVE_TAG (&tag_unit, open->unit); RESOLVE_TAG (&tag_iomsg, open->iomsg); RESOLVE_TAG (&tag_iostat, open->iostat); @@ -2073,7 +2046,7 @@ gfc_resolve_open (gfc_open *open) if (!gfc_reference_st_label (open->err, ST_LABEL_TARGET)) return false; - return true; + return check_open_constraints (open, where); } @@ -2081,19 +2054,13 @@ gfc_resolve_open (gfc_open *open) allowed in F95 or F2003, issuing an error message and returning a zero value if it is not allowed. */ -static int -compare_to_allowed_values (const char *specifier, const char *allowed[], - const char *allowed_f2003[], - const char *allowed_gnu[], gfc_char_t *value, - const char *statement, bool warn, - int *num = NULL); - static int compare_to_allowed_values (const char *specifier, const char *allowed[], - const char *allowed_f2003[], + const char *allowed_f2003[], const char *allowed_gnu[], gfc_char_t *value, - const char *statement, bool warn, int *num) + const char *statement, bool warn, locus *where, + int *num) { int i; unsigned int len; @@ -2116,6 +2083,9 @@ compare_to_allowed_values (const char *specifier, const char *allowed[], return 1; } + if (!where) + where = &gfc_current_locus; + for (i = 0; allowed_f2003 && allowed_f2003[i]; i++) if (len == strlen (allowed_f2003[i]) && gfc_wide_strncasecmp (value, allowed_f2003[i], @@ -2125,8 +2095,8 @@ compare_to_allowed_values (const char *specifier, const char *allowed[], if (n == WARNING || (warn && n == ERROR)) { - gfc_warning (0, "Fortran 2003: %s specifier in %s statement at %C " - "has value %qs", specifier, statement, + gfc_warning (0, "Fortran 2003: %s specifier in %s statement at %L " + "has value %qs", specifier, statement, where, allowed_f2003[i]); return 1; } @@ -2134,8 +2104,8 @@ compare_to_allowed_values (const char *specifier, const char *allowed[], if (n == ERROR) { gfc_notify_std (GFC_STD_F2003, "%s specifier in " - "%s statement at %C has value %qs", specifier, - statement, allowed_f2003[i]); + "%s statement at %L has value %qs", specifier, + statement, where, allowed_f2003[i]); return 0; } @@ -2152,8 +2122,8 @@ compare_to_allowed_values (const char *specifier, const char *allowed[], if (n == WARNING || (warn && n == ERROR)) { - gfc_warning (0, "Extension: %s specifier in %s statement at %C " - "has value %qs", specifier, statement, + gfc_warning (0, "Extension: %s specifier in %s statement at %L " + "has value %qs", specifier, statement, where, allowed_gnu[i]); return 1; } @@ -2161,8 +2131,8 @@ compare_to_allowed_values (const char *specifier, const char *allowed[], if (n == ERROR) { gfc_notify_std (GFC_STD_GNU, "%s specifier in " - "%s statement at %C has value %qs", specifier, - statement, allowed_gnu[i]); + "%s statement at %L has value %qs", specifier, + statement, where, allowed_gnu[i]); return 0; } @@ -2174,74 +2144,42 @@ compare_to_allowed_values (const char *specifier, const char *allowed[], { char *s = gfc_widechar_to_char (value, -1); gfc_warning (0, - "%s specifier in %s statement at %C has invalid value %qs", - specifier, statement, s); + "%s specifier in %s statement at %L has invalid value %qs", + specifier, statement, where, s); free (s); return 1; } else { char *s = gfc_widechar_to_char (value, -1); - gfc_error ("%s specifier in %s statement at %C has invalid value %qs", - specifier, statement, s); + gfc_error ("%s specifier in %s statement at %L has invalid value %qs", + specifier, statement, where, s); free (s); return 0; } } -/* Match an OPEN statement. */ +/* Check constraints on the OPEN statement. + Similar to check_io_constraints for data transfer statements. + At this point all tags have already been resolved via resolve_tag, which, + among other things, verifies that BT_CHARACTER tags are of default kind. */ -match -gfc_match_open (void) +static bool +check_open_constraints (gfc_open *open, locus *where) { - gfc_open *open; - match m; - bool warn; - - m = gfc_match_char ('('); - if (m == MATCH_NO) - return m; - - open = XCNEW (gfc_open); - - m = match_open_element (open); - - if (m == MATCH_ERROR) - goto cleanup; - if (m == MATCH_NO) - { - m = gfc_match_expr (&open->unit); - if (m == MATCH_ERROR) - goto cleanup; - } - - for (;;) - { - if (gfc_match_char (')') == MATCH_YES) - break; - if (gfc_match_char (',') != MATCH_YES) - goto syntax; - - m = match_open_element (open); - if (m == MATCH_ERROR) - goto cleanup; - if (m == MATCH_NO) - goto syntax; - } - - if (gfc_match_eos () == MATCH_NO) - goto syntax; - - if (gfc_pure (NULL)) - { - gfc_error ("OPEN statement not allowed in PURE procedure at %C"); - goto cleanup; - } - - gfc_unset_implicit_pure (NULL); +#define warn_or_error(...) \ +{ \ + if (warn) \ + gfc_warning (0, __VA_ARGS__); \ + else \ + { \ + gfc_error (__VA_ARGS__); \ + return false; \ + } \ +} - warn = (open->err || open->iostat) ? true : false; + bool warn = (open->err || open->iostat) ? true : false; /* Checks on the ACCESS specifier. */ if (open->access && open->access->expr_type == EXPR_CONSTANT) @@ -2250,14 +2188,11 @@ gfc_match_open (void) static const char *access_f2003[] = { "STREAM", NULL }; static const char *access_gnu[] = { "APPEND", NULL }; - if (!is_char_type ("ACCESS", open->access)) - goto cleanup; - if (!compare_to_allowed_values ("ACCESS", access_f95, access_f2003, access_gnu, open->access->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->access->where)) + return false; } /* Checks on the ACTION specifier. */ @@ -2266,21 +2201,20 @@ gfc_match_open (void) gfc_char_t *str = open->action->value.character.string; static const char *action[] = { "READ", "WRITE", "READWRITE", NULL }; - if (!is_char_type ("ACTION", open->action)) - goto cleanup; - if (!compare_to_allowed_values ("ACTION", action, NULL, NULL, - str, "OPEN", warn)) - goto cleanup; + str, "OPEN", warn, &open->action->where)) + return false; /* With READONLY, only allow ACTION='READ'. */ if (open->readonly && (gfc_wide_strlen (str) != 4 || gfc_wide_strncasecmp (str, "READ", 4) != 0)) { - gfc_error ("ACTION type conflicts with READONLY specifier at %C"); - goto cleanup; + gfc_error ("ACTION type conflicts with READONLY specifier at %L", + &open->action->where); + return false; } } + /* If we see READONLY and no ACTION, set ACTION='READ'. */ else if (open->readonly && open->action == NULL) { @@ -2291,27 +2225,10 @@ gfc_match_open (void) /* Checks on the ASYNCHRONOUS specifier. */ if (open->asynchronous) { - if (!gfc_notify_std (GFC_STD_F2003, "ASYNCHRONOUS= at %C " - "not allowed in Fortran 95")) - goto cleanup; - - if (!is_char_type ("ASYNCHRONOUS", open->asynchronous)) - goto cleanup; - - if (open->asynchronous->ts.kind != 1) - { - gfc_error ("ASYNCHRONOUS= specifier at %L must be of default " - "CHARACTER kind", &open->asynchronous->where); - return MATCH_ERROR; - } - - if (open->asynchronous->expr_type == EXPR_ARRAY - || open->asynchronous->expr_type == EXPR_STRUCTURE) - { - gfc_error ("ASYNCHRONOUS= specifier at %L must be scalar", - &open->asynchronous->where); - return MATCH_ERROR; - } + if (!gfc_notify_std (GFC_STD_F2003, "ASYNCHRONOUS= at %L " + "not allowed in Fortran 95", + &open->asynchronous->where)) + return false; if (open->asynchronous->expr_type == EXPR_CONSTANT) { @@ -2319,20 +2236,17 @@ gfc_match_open (void) if (!compare_to_allowed_values ("ASYNCHRONOUS", asynchronous, NULL, NULL, open->asynchronous->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->asynchronous->where)) + return false; } } /* Checks on the BLANK specifier. */ if (open->blank) { - if (!gfc_notify_std (GFC_STD_F2003, "BLANK= at %C " - "not allowed in Fortran 95")) - goto cleanup; - - if (!is_char_type ("BLANK", open->blank)) - goto cleanup; + if (!gfc_notify_std (GFC_STD_F2003, "BLANK= at %L " + "not allowed in Fortran 95", &open->blank->where)) + return false; if (open->blank->expr_type == EXPR_CONSTANT) { @@ -2340,36 +2254,27 @@ gfc_match_open (void) if (!compare_to_allowed_values ("BLANK", blank, NULL, NULL, open->blank->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->blank->where)) + return false; } } /* Checks on the CARRIAGECONTROL specifier. */ - if (open->cc) + if (open->cc && open->cc->expr_type == EXPR_CONSTANT) { - if (!is_char_type ("CARRIAGECONTROL", open->cc)) - goto cleanup; - - if (open->cc->expr_type == EXPR_CONSTANT) - { - static const char *cc[] = { "LIST", "FORTRAN", "NONE", NULL }; - if (!compare_to_allowed_values ("CARRIAGECONTROL", cc, NULL, NULL, - open->cc->value.character.string, - "OPEN", warn)) - goto cleanup; - } + static const char *cc[] = { "LIST", "FORTRAN", "NONE", NULL }; + if (!compare_to_allowed_values ("CARRIAGECONTROL", cc, NULL, NULL, + open->cc->value.character.string, + "OPEN", warn, &open->cc->where)) + return false; } /* Checks on the DECIMAL specifier. */ if (open->decimal) { - if (!gfc_notify_std (GFC_STD_F2003, "DECIMAL= at %C " - "not allowed in Fortran 95")) - goto cleanup; - - if (!is_char_type ("DECIMAL", open->decimal)) - goto cleanup; + if (!gfc_notify_std (GFC_STD_F2003, "DECIMAL= at %L " + "not allowed in Fortran 95", &open->decimal->where)) + return false; if (open->decimal->expr_type == EXPR_CONSTANT) { @@ -2377,8 +2282,8 @@ gfc_match_open (void) if (!compare_to_allowed_values ("DECIMAL", decimal, NULL, NULL, open->decimal->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->decimal->where)) + return false; } } @@ -2389,25 +2294,19 @@ gfc_match_open (void) { static const char *delim[] = { "APOSTROPHE", "QUOTE", "NONE", NULL }; - if (!is_char_type ("DELIM", open->delim)) - goto cleanup; - if (!compare_to_allowed_values ("DELIM", delim, NULL, NULL, open->delim->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->delim->where)) + return false; } } /* Checks on the ENCODING specifier. */ if (open->encoding) { - if (!gfc_notify_std (GFC_STD_F2003, "ENCODING= at %C " - "not allowed in Fortran 95")) - goto cleanup; - - if (!is_char_type ("ENCODING", open->encoding)) - goto cleanup; + if (!gfc_notify_std (GFC_STD_F2003, "ENCODING= at %L " + "not allowed in Fortran 95", &open->encoding->where)) + return false; if (open->encoding->expr_type == EXPR_CONSTANT) { @@ -2415,8 +2314,8 @@ gfc_match_open (void) if (!compare_to_allowed_values ("ENCODING", encoding, NULL, NULL, open->encoding->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->encoding->where)) + return false; } } @@ -2425,13 +2324,10 @@ gfc_match_open (void) { static const char *form[] = { "FORMATTED", "UNFORMATTED", NULL }; - if (!is_char_type ("FORM", open->form)) - goto cleanup; - if (!compare_to_allowed_values ("FORM", form, NULL, NULL, open->form->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->form->where)) + return false; } /* Checks on the PAD specifier. */ @@ -2439,13 +2335,10 @@ gfc_match_open (void) { static const char *pad[] = { "YES", "NO", NULL }; - if (!is_char_type ("PAD", open->pad)) - goto cleanup; - if (!compare_to_allowed_values ("PAD", pad, NULL, NULL, open->pad->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->pad->where)) + return false; } /* Checks on the POSITION specifier. */ @@ -2453,24 +2346,18 @@ gfc_match_open (void) { static const char *position[] = { "ASIS", "REWIND", "APPEND", NULL }; - if (!is_char_type ("POSITION", open->position)) - goto cleanup; - if (!compare_to_allowed_values ("POSITION", position, NULL, NULL, open->position->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->position->where)) + return false; } /* Checks on the ROUND specifier. */ if (open->round) { - if (!gfc_notify_std (GFC_STD_F2003, "ROUND= at %C " - "not allowed in Fortran 95")) - goto cleanup; - - if (!is_char_type ("ROUND", open->round)) - goto cleanup; + if (!gfc_notify_std (GFC_STD_F2003, "ROUND= at %L " + "not allowed in Fortran 95", &open->round->where)) + return false; if (open->round->expr_type == EXPR_CONSTANT) { @@ -2480,36 +2367,27 @@ gfc_match_open (void) if (!compare_to_allowed_values ("ROUND", round, NULL, NULL, open->round->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->round->where)) + return false; } } /* Checks on the SHARE specifier. */ - if (open->share) + if (open->share && open->share->expr_type == EXPR_CONSTANT) { - if (!is_char_type ("SHARE", open->share)) - goto cleanup; - - if (open->share->expr_type == EXPR_CONSTANT) - { - static const char *share[] = { "DENYNONE", "DENYRW", NULL }; - if (!compare_to_allowed_values ("SHARE", share, NULL, NULL, - open->share->value.character.string, - "OPEN", warn)) - goto cleanup; - } + static const char *share[] = { "DENYNONE", "DENYRW", NULL }; + if (!compare_to_allowed_values ("SHARE", share, NULL, NULL, + open->share->value.character.string, + "OPEN", warn, &open->share->where)) + return false; } /* Checks on the SIGN specifier. */ - if (open->sign) + if (open->sign) { - if (!gfc_notify_std (GFC_STD_F2003, "SIGN= at %C " - "not allowed in Fortran 95")) - goto cleanup; - - if (!is_char_type ("SIGN", open->sign)) - goto cleanup; + if (!gfc_notify_std (GFC_STD_F2003, "SIGN= at %L " + "not allowed in Fortran 95", &open->sign->where)) + return false; if (open->sign->expr_type == EXPR_CONSTANT) { @@ -2518,28 +2396,18 @@ gfc_match_open (void) if (!compare_to_allowed_values ("SIGN", sign, NULL, NULL, open->sign->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->sign->where)) + return false; } } -#define warn_or_error(...) \ -{ \ - if (warn) \ - gfc_warning (0, __VA_ARGS__); \ - else \ - { \ - gfc_error (__VA_ARGS__); \ - goto cleanup; \ - } \ -} - /* Checks on the RECL specifier. */ if (open->recl && open->recl->expr_type == EXPR_CONSTANT && open->recl->ts.type == BT_INTEGER && mpz_sgn (open->recl->value.integer) != 1) { - warn_or_error ("RECL in OPEN statement at %C must be positive"); + warn_or_error ("RECL in OPEN statement at %L must be positive", + &open->recl->where); } /* Checks on the STATUS specifier. */ @@ -2548,13 +2416,10 @@ gfc_match_open (void) static const char *status[] = { "OLD", "NEW", "SCRATCH", "REPLACE", "UNKNOWN", NULL }; - if (!is_char_type ("STATUS", open->status)) - goto cleanup; - if (!compare_to_allowed_values ("STATUS", status, NULL, NULL, open->status->value.character.string, - "OPEN", warn)) - goto cleanup; + "OPEN", warn, &open->status->where)) + return false; /* F2003, 9.4.5: If the STATUS= specifier has the value NEW or REPLACE, the FILE= specifier shall appear. */ @@ -2566,8 +2431,9 @@ gfc_match_open (void) { char *s = gfc_widechar_to_char (open->status->value.character.string, -1); - warn_or_error ("The STATUS specified in OPEN statement at %C is " - "%qs and no FILE specifier is present", s); + warn_or_error ("The STATUS specified in OPEN statement at %L is " + "%qs and no FILE specifier is present", + &open->status->where, s); free (s); } @@ -2576,9 +2442,9 @@ gfc_match_open (void) if (gfc_wide_strncasecmp (open->status->value.character.string, "scratch", 7) == 0 && open->file) { - warn_or_error ("The STATUS specified in OPEN statement at %C " + warn_or_error ("The STATUS specified in OPEN statement at %L " "cannot have the value SCRATCH if a FILE specifier " - "is present"); + "is present", &open->status->where); } } @@ -2587,8 +2453,9 @@ gfc_match_open (void) { if (open->unit) { - gfc_error ("UNIT specifier not allowed with NEWUNIT at %C"); - goto cleanup; + gfc_error ("UNIT specifier not allowed with NEWUNIT at %L", + &open->newunit->where); + return false; } if (!open->file && @@ -2598,14 +2465,15 @@ gfc_match_open (void) "scratch", 7) != 0))) { gfc_error ("NEWUNIT specifier must have FILE= " - "or STATUS='scratch' at %C"); - goto cleanup; + "or STATUS='scratch' at %L", &open->newunit->where); + return false; } } else if (!open->unit) { - gfc_error ("OPEN statement at %C must have UNIT or NEWUNIT specified"); - goto cleanup; + gfc_error ("OPEN statement at %L must have UNIT or NEWUNIT specified", + where); + return false; } /* Things that are not allowed for unformatted I/O. */ @@ -2615,20 +2483,39 @@ gfc_match_open (void) && gfc_wide_strncasecmp (open->form->value.character.string, "unformatted", 11) == 0) { - const char *spec = (open->delim ? "DELIM " - : (open->pad ? "PAD " : open->blank - ? "BLANK " : "")); + locus *loc; + const char *spec; + if (open->delim) + { + loc = &open->delim->where; + spec = "DELIM "; + } + else if (open->pad) + { + loc = &open->pad->where; + spec = "PAD "; + } + else if (open->blank) + { + loc = &open->blank->where; + spec = "BLANK "; + } + else + { + loc = where; + spec = ""; + } - warn_or_error ("%s specifier at %C not allowed in OPEN statement for " - "unformatted I/O", spec); + warn_or_error ("%s specifier at %L not allowed in OPEN statement for " + "unformatted I/O", spec, loc); } if (open->recl && open->access && open->access->expr_type == EXPR_CONSTANT && gfc_wide_strncasecmp (open->access->value.character.string, "stream", 6) == 0) { - warn_or_error ("RECL specifier not allowed in OPEN statement at %C for " - "stream I/O"); + warn_or_error ("RECL specifier not allowed in OPEN statement at %L for " + "stream I/O", &open->recl->where); } if (open->position @@ -2640,11 +2527,64 @@ gfc_match_open (void) || gfc_wide_strncasecmp (open->access->value.character.string, "append", 6) == 0)) { - warn_or_error ("POSITION specifier in OPEN statement at %C only allowed " - "for stream or sequential ACCESS"); + warn_or_error ("POSITION specifier in OPEN statement at %L only allowed " + "for stream or sequential ACCESS", &open->position->where); } + return true; #undef warn_or_error +} + + +/* Match an OPEN statement. */ + +match +gfc_match_open (void) +{ + gfc_open *open; + match m; + + m = gfc_match_char ('('); + if (m == MATCH_NO) + return m; + + open = XCNEW (gfc_open); + + m = match_open_element (open); + + if (m == MATCH_ERROR) + goto cleanup; + if (m == MATCH_NO) + { + m = gfc_match_expr (&open->unit); + if (m == MATCH_ERROR) + goto cleanup; + } + + for (;;) + { + if (gfc_match_char (')') == MATCH_YES) + break; + if (gfc_match_char (',') != MATCH_YES) + goto syntax; + + m = match_open_element (open); + if (m == MATCH_ERROR) + goto cleanup; + if (m == MATCH_NO) + goto syntax; + } + + if (gfc_match_eos () == MATCH_NO) + goto syntax; + + if (gfc_pure (NULL)) + { + gfc_error ("OPEN statement not allowed in PURE procedure at %C"); + goto cleanup; + } + + gfc_unset_implicit_pure (NULL); new_st.op = EXEC_OPEN; new_st.ext.open = open; @@ -2689,8 +2629,6 @@ match_close_element (gfc_close *close) if (m != MATCH_NO) return m; m = match_etag (&tag_iomsg, &close->iomsg); - if (m == MATCH_YES && !check_char_variable (close->iomsg)) - return MATCH_ERROR; if (m != MATCH_NO) return m; m = match_out_tag (&tag_iostat, &close->iostat); @@ -2711,7 +2649,6 @@ gfc_match_close (void) { gfc_close *close; match m; - bool warn; m = gfc_match_char ('('); if (m == MATCH_NO) @@ -2757,22 +2694,6 @@ gfc_match_close (void) gfc_unset_implicit_pure (NULL); - warn = (close->iostat || close->err) ? true : false; - - /* Checks on the STATUS specifier. */ - if (close->status && close->status->expr_type == EXPR_CONSTANT) - { - static const char *status[] = { "KEEP", "DELETE", NULL }; - - if (!is_char_type ("STATUS", close->status)) - goto cleanup; - - if (!compare_to_allowed_values ("STATUS", status, NULL, NULL, - close->status->value.character.string, - "CLOSE", warn)) - goto cleanup; - } - new_st.op = EXEC_CLOSE; new_st.ext.close = close; return MATCH_YES; @@ -2786,34 +2707,14 @@ cleanup: } -/* Resolve everything in a gfc_close structure. */ - -bool -gfc_resolve_close (gfc_close *close) +static bool +check_close_constraints (gfc_close *close, locus *where) { - RESOLVE_TAG (&tag_unit, close->unit); - RESOLVE_TAG (&tag_iomsg, close->iomsg); - RESOLVE_TAG (&tag_iostat, close->iostat); - RESOLVE_TAG (&tag_status, close->status); - - if (!gfc_reference_st_label (close->err, ST_LABEL_TARGET)) - return false; + bool warn = (close->iostat || close->err) ? true : false; if (close->unit == NULL) { - /* Find a locus from one of the arguments to close, when UNIT is - not specified. */ - locus loc = gfc_current_locus; - if (close->status) - loc = close->status->where; - else if (close->iostat) - loc = close->iostat->where; - else if (close->iomsg) - loc = close->iomsg->where; - else if (close->err) - loc = close->err->where; - - gfc_error ("CLOSE statement at %L requires a UNIT number", &loc); + gfc_error ("CLOSE statement at %L requires a UNIT number", where); return false; } @@ -2825,9 +2726,36 @@ gfc_resolve_close (gfc_close *close) &close->unit->where); } + /* Checks on the STATUS specifier. */ + if (close->status && close->status->expr_type == EXPR_CONSTANT) + { + static const char *status[] = { "KEEP", "DELETE", NULL }; + + if (!compare_to_allowed_values ("STATUS", status, NULL, NULL, + close->status->value.character.string, + "CLOSE", warn, &close->status->where)) + return false; + } + return true; } +/* Resolve everything in a gfc_close structure. */ + +bool +gfc_resolve_close (gfc_close *close, locus *where) +{ + RESOLVE_TAG (&tag_unit, close->unit); + RESOLVE_TAG (&tag_iomsg, close->iomsg); + RESOLVE_TAG (&tag_iostat, close->iostat); + RESOLVE_TAG (&tag_status, close->status); + + if (!gfc_reference_st_label (close->err, ST_LABEL_TARGET)) + return false; + + return check_close_constraints (close, where); +} + /* Free a gfc_filepos structure. */ @@ -2852,8 +2780,6 @@ match_file_element (gfc_filepos *fp) if (m != MATCH_NO) return m; m = match_etag (&tag_iomsg, &fp->iomsg); - if (m == MATCH_YES && !check_char_variable (fp->iomsg)) - return MATCH_ERROR; if (m != MATCH_NO) return m; m = match_out_tag (&tag_iostat, &fp->iostat); @@ -3227,8 +3153,6 @@ match_dt_element (io_kind k, gfc_dt *dt) } m = match_etag (&tag_e_async, &dt->asynchronous); - if (m == MATCH_YES && !is_char_type ("ASYNCHRONOUS", dt->asynchronous)) - return MATCH_ERROR; if (m != MATCH_NO) return m; m = match_etag (&tag_e_blank, &dt->blank); @@ -3259,8 +3183,6 @@ match_dt_element (io_kind k, gfc_dt *dt) if (m != MATCH_NO) return m; m = match_etag (&tag_iomsg, &dt->iomsg); - if (m == MATCH_YES && !check_char_variable (dt->iomsg)) - return MATCH_ERROR; if (m != MATCH_NO) return m; @@ -3330,28 +3252,26 @@ gfc_free_dt (gfc_dt *dt) } +static const char * +io_kind_name (io_kind k); + +static bool +check_io_constraints (io_kind k, gfc_dt *dt, gfc_code *io_code, + locus *spec_end); + /* Resolve everything in a gfc_dt structure. */ bool -gfc_resolve_dt (gfc_dt *dt, locus *loc) +gfc_resolve_dt (gfc_code *dt_code, gfc_dt *dt, locus *loc) { gfc_expr *e; io_kind k; - locus tmp; /* This is set in any case. */ gcc_assert (dt->dt_io_kind); k = dt->dt_io_kind->value.iokind; - tmp = gfc_current_locus; - gfc_current_locus = *loc; - if (!resolve_tag (&tag_format, dt->format_expr)) - { - gfc_current_locus = tmp; - return false; - } - gfc_current_locus = tmp; - + RESOLVE_TAG (&tag_format, dt->format_expr); RESOLVE_TAG (&tag_rec, dt->rec); RESOLVE_TAG (&tag_spos, dt->pos); RESOLVE_TAG (&tag_advance, dt->advance); @@ -3367,6 +3287,18 @@ gfc_resolve_dt (gfc_dt *dt, locus *loc) RESOLVE_TAG (&tag_e_decimal, dt->decimal); RESOLVE_TAG (&tag_e_async, dt->asynchronous); + /* Check I/O constraints. + To validate NAMELIST we need to check if we were also given an I/O list, + which is stored in code->block->next with op EXEC_TRANSFER. + Note that the I/O list was already resolved from resolve_transfer. */ + gfc_code *io_code = NULL; + if (dt_code && dt_code->block && dt_code->block->next + && dt_code->block->next->op == EXEC_TRANSFER) + io_code = dt_code->block->next; + + if (!check_io_constraints (k, dt, io_code, loc)) + return false; + e = dt->io_unit; if (e == NULL) { @@ -3821,11 +3753,13 @@ terminate_io (gfc_code *io_code) /* Check the constraints for a data transfer statement. The majority of the - constraints appearing in 9.4 of the standard appear here. Some are handled - in resolve_tag and others in gfc_resolve_dt. Also set the async_io_dt flag - and, if necessary, the asynchronous flag on the SIZE argument. */ + constraints appearing in 9.4 of the standard appear here. -static match + Tag expressions are already resolved by resolve_tag, which includes + verifying the type, that they are scalar, and verifying that BT_CHARACTER + tags are of default kind. */ + +static bool check_io_constraints (io_kind k, gfc_dt *dt, gfc_code *io_code, locus *spec_end) { @@ -3835,11 +3769,10 @@ if (condition) \ if ((arg)->lb != NULL)\ gfc_error ((msg), (arg));\ else\ - gfc_error ((msg), &gfc_current_locus);\ - m = MATCH_ERROR;\ + gfc_error ((msg), spec_end);\ + return false;\ } - match m; gfc_expr *expr; gfc_symbol *sym = NULL; bool warn, unformatted; @@ -3848,8 +3781,6 @@ if (condition) \ unformatted = dt->format_expr == NULL && dt->format_label == NULL && dt->namelist == NULL; - m = MATCH_YES; - expr = dt->io_unit; if (expr && expr->expr_type == EXPR_VARIABLE && expr->ts.type == BT_CHARACTER) @@ -3867,7 +3798,7 @@ if (condition) \ io_constraint (dt->rec != NULL, "REC tag at %L is incompatible with internal file", &dt->rec->where); - + io_constraint (dt->pos != NULL, "POS tag at %L is incompatible with internal file", &dt->pos->where); @@ -3884,7 +3815,7 @@ if (condition) \ { if (!gfc_notify_std (GFC_STD_F2003, "Internal file at %L with " "namelist", &expr->where)) - m = MATCH_ERROR; + return false; } io_constraint (dt->advance != NULL, @@ -3897,87 +3828,57 @@ if (condition) \ if (gfc_pure (NULL) && (k == M_READ || k == M_WRITE)) { - gfc_error ("IO UNIT in %s statement at %C must be " + gfc_error ("IO UNIT in %s statement at %L must be " "an internal file in a PURE procedure", - io_kind_name (k)); - return MATCH_ERROR; + io_kind_name (k), &expr->where); + return false; } - + if (k == M_READ || k == M_WRITE) gfc_unset_implicit_pure (NULL); } - if (k != M_READ) - { - io_constraint (dt->end, "END tag not allowed with output at %L", - &dt->end_where); - - io_constraint (dt->eor, "EOR tag not allowed with output at %L", - &dt->eor_where); - - io_constraint (dt->blank, "BLANK= specifier not allowed with output at %L", - &dt->blank->where); - - io_constraint (dt->pad, "PAD= specifier not allowed with output at %L", - &dt->pad->where); - - io_constraint (dt->size, "SIZE= specifier not allowed with output at %L", - &dt->size->where); - } - else - { - io_constraint (dt->size && dt->advance == NULL, - "SIZE tag at %L requires an ADVANCE tag", - &dt->size->where); - - io_constraint (dt->eor && dt->advance == NULL, - "EOR tag at %L requires an ADVANCE tag", - &dt->eor_where); - } - - if (dt->asynchronous) + if (dt->asynchronous) { int num; static const char * asynchronous[] = { "YES", "NO", NULL }; + /* Note: gfc_reduce_init_expr reports an error if not init-expr. */ if (!gfc_reduce_init_expr (dt->asynchronous)) - { - gfc_error ("ASYNCHRONOUS= specifier at %L must be an initialization " - "expression", &dt->asynchronous->where); - return MATCH_ERROR; - } - - if (!is_char_type ("ASYNCHRONOUS", dt->asynchronous)) - return MATCH_ERROR; - - if (dt->asynchronous->ts.kind != 1) - { - gfc_error ("ASYNCHRONOUS= specifier at %L must be of default " - "CHARACTER kind", &dt->asynchronous->where); - return MATCH_ERROR; - } - - if (dt->asynchronous->expr_type == EXPR_ARRAY - || dt->asynchronous->expr_type == EXPR_STRUCTURE) - { - gfc_error ("ASYNCHRONOUS= specifier at %L must be scalar", - &dt->asynchronous->where); - return MATCH_ERROR; - } + return false; if (!compare_to_allowed_values ("ASYNCHRONOUS", asynchronous, NULL, NULL, dt->asynchronous->value.character.string, - io_kind_name (k), warn, &num)) - return MATCH_ERROR; + io_kind_name (k), warn, &dt->asynchronous->where, &num)) + return false; - /* Best to put this here because the yes/no info is still around. */ - async_io_dt = num == 0; - if (async_io_dt && dt->size) - dt->size->symtree->n.sym->attr.asynchronous = 1; + /* For "YES", mark related symbols as asynchronous. */ + if (num == 0) + { + /* SIZE variable. */ + if (dt->size) + dt->size->symtree->n.sym->attr.asynchronous = 1; + + /* Variables in a NAMELIST. */ + if (dt->namelist) + for (gfc_namelist *nl = dt->namelist->namelist; nl; nl = nl->next) + nl->sym->attr.asynchronous = 1; + + /* Variables in an I/O list. */ + for (gfc_code *xfer = io_code; xfer && xfer->op == EXEC_TRANSFER; + xfer = xfer->next) + { + gfc_expr *expr = xfer->expr1; + while (expr != NULL && expr->expr_type == EXPR_OP + && expr->value.op.op == INTRINSIC_PARENTHESES) + expr = expr->value.op.op1; + + if (expr && expr->expr_type == EXPR_VARIABLE) + expr->symtree->n.sym->attr.asynchronous = 1; + } + } } - else - async_io_dt = false; if (dt->id) { @@ -3993,36 +3894,31 @@ if (condition) \ if (dt->decimal) { - if (!gfc_notify_std (GFC_STD_F2003, "DECIMAL= at %C " - "not allowed in Fortran 95")) - return MATCH_ERROR; + if (!gfc_notify_std (GFC_STD_F2003, "DECIMAL= at %L " + "not allowed in Fortran 95", &dt->decimal->where)) + return false; if (dt->decimal->expr_type == EXPR_CONSTANT) { static const char * decimal[] = { "COMMA", "POINT", NULL }; - if (!is_char_type ("DECIMAL", dt->decimal)) - return MATCH_ERROR; - if (!compare_to_allowed_values ("DECIMAL", decimal, NULL, NULL, dt->decimal->value.character.string, - io_kind_name (k), warn)) - return MATCH_ERROR; + io_kind_name (k), warn, + &dt->decimal->where)) + return false; io_constraint (unformatted, "the DECIMAL= specifier at %L must be with an " "explicit format expression", &dt->decimal->where); } } - + if (dt->blank) { - if (!gfc_notify_std (GFC_STD_F2003, "BLANK= at %C " - "not allowed in Fortran 95")) - return MATCH_ERROR; - - if (!is_char_type ("BLANK", dt->blank)) - return MATCH_ERROR; + if (!gfc_notify_std (GFC_STD_F2003, "BLANK= at %L " + "not allowed in Fortran 95", &dt->blank->where)) + return false; if (dt->blank->expr_type == EXPR_CONSTANT) { @@ -4031,8 +3927,9 @@ if (condition) \ if (!compare_to_allowed_values ("BLANK", blank, NULL, NULL, dt->blank->value.character.string, - io_kind_name (k), warn)) - return MATCH_ERROR; + io_kind_name (k), warn, + &dt->blank->where)) + return false; io_constraint (unformatted, "the BLANK= specifier at %L must be with an " @@ -4042,12 +3939,9 @@ if (condition) \ if (dt->pad) { - if (!gfc_notify_std (GFC_STD_F2003, "PAD= at %C " - "not allowed in Fortran 95")) - return MATCH_ERROR; - - if (!is_char_type ("PAD", dt->pad)) - return MATCH_ERROR; + if (!gfc_notify_std (GFC_STD_F2003, "PAD= at %L " + "not allowed in Fortran 95", &dt->pad->where)) + return false; if (dt->pad->expr_type == EXPR_CONSTANT) { @@ -4055,8 +3949,9 @@ if (condition) \ if (!compare_to_allowed_values ("PAD", pad, NULL, NULL, dt->pad->value.character.string, - io_kind_name (k), warn)) - return MATCH_ERROR; + io_kind_name (k), warn, + &dt->pad->where)) + return false; io_constraint (unformatted, "the PAD= specifier at %L must be with an " @@ -4066,12 +3961,9 @@ if (condition) \ if (dt->round) { - if (!gfc_notify_std (GFC_STD_F2003, "ROUND= at %C " - "not allowed in Fortran 95")) - return MATCH_ERROR; - - if (!is_char_type ("ROUND", dt->round)) - return MATCH_ERROR; + if (!gfc_notify_std (GFC_STD_F2003, "ROUND= at %L " + "not allowed in Fortran 95", &dt->round->where)) + return false; if (dt->round->expr_type == EXPR_CONSTANT) { @@ -4081,20 +3973,18 @@ if (condition) \ if (!compare_to_allowed_values ("ROUND", round, NULL, NULL, dt->round->value.character.string, - io_kind_name (k), warn)) - return MATCH_ERROR; + io_kind_name (k), warn, + &dt->round->where)) + return false; } } - + if (dt->sign) { /* When implemented, change the following to use gfc_notify_std F2003. - if (gfc_notify_std (GFC_STD_F2003, "SIGN= at %C " - "not allowed in Fortran 95") == false) - return MATCH_ERROR; */ - - if (!is_char_type ("SIGN", dt->sign)) - return MATCH_ERROR; + if (gfc_notify_std (GFC_STD_F2003, "SIGN= at %L " + "not allowed in Fortran 95", &dt->sign->where) == false) + return false; */ if (dt->sign->expr_type == EXPR_CONSTANT) { @@ -4103,8 +3993,8 @@ if (condition) \ if (!compare_to_allowed_values ("SIGN", sign, NULL, NULL, dt->sign->value.character.string, - io_kind_name (k), warn)) - return MATCH_ERROR; + io_kind_name (k), warn, &dt->sign->where)) + return false; io_constraint (unformatted, "SIGN= specifier at %L must be with an " @@ -4118,12 +4008,9 @@ if (condition) \ if (dt->delim) { - if (!gfc_notify_std (GFC_STD_F2003, "DELIM= at %C " - "not allowed in Fortran 95")) - return MATCH_ERROR; - - if (!is_char_type ("DELIM", dt->delim)) - return MATCH_ERROR; + if (!gfc_notify_std (GFC_STD_F2003, "DELIM= at %L " + "not allowed in Fortran 95", &dt->delim->where)) + return false; if (dt->delim->expr_type == EXPR_CONSTANT) { @@ -4131,13 +4018,14 @@ if (condition) \ if (!compare_to_allowed_values ("DELIM", delim, NULL, NULL, dt->delim->value.character.string, - io_kind_name (k), warn)) - return MATCH_ERROR; + io_kind_name (k), warn, + &dt->delim->where)) + return false; io_constraint (k == M_READ, "DELIM= specifier at %L not allowed in a " "READ statement", &dt->delim->where); - + io_constraint (dt->format_label != &format_asterisk && dt->namelist == NULL, "DELIM= specifier at %L must have FMT=*", @@ -4148,7 +4036,7 @@ if (condition) \ "NML= specifier", &dt->delim->where); } } - + if (dt->namelist) { io_constraint (io_code && dt->namelist, @@ -4225,17 +4113,41 @@ if (condition) \ io_constraint (dt->eor && not_no && k == M_READ, "EOR tag at %L requires an ADVANCE = %", - &dt->eor_where); + &dt->eor_where); } - expr = dt->format_expr; - if (!gfc_simplify_expr (expr, 0) - || !check_format_string (expr, k == M_READ)) - return MATCH_ERROR; + if (k != M_READ) + { + io_constraint (dt->end, "END tag not allowed with output at %L", + &dt->end_where); - return m; -} + io_constraint (dt->eor, "EOR tag not allowed with output at %L", + &dt->eor_where); + + io_constraint (dt->blank, + "BLANK= specifier not allowed with output at %L", + &dt->blank->where); + + io_constraint (dt->pad, "PAD= specifier not allowed with output at %L", + &dt->pad->where); + + io_constraint (dt->size, "SIZE= specifier not allowed with output at %L", + &dt->size->where); + } + else + { + io_constraint (dt->size && dt->advance == NULL, + "SIZE tag at %L requires an ADVANCE tag", + &dt->size->where); + + io_constraint (dt->eor && dt->advance == NULL, + "EOR tag at %L requires an ADVANCE tag", + &dt->eor_where); + } + + return true; #undef io_constraint +} /* Match a READ, WRITE or PRINT statement. */ @@ -4248,7 +4160,7 @@ match_io (io_kind k) gfc_symbol *sym; int comma_flag; locus where; - locus spec_end, control; + locus control; gfc_dt *dt; match m; @@ -4451,9 +4363,6 @@ loop: get_io_list: - /* Used in check_io_constraints, where no locus is available. */ - spec_end = gfc_current_locus; - /* Save the IO kind for later use. */ dt->dt_io_kind = gfc_get_iokind_expr (&gfc_current_locus, k); @@ -4485,12 +4394,11 @@ get_io_list: if (flag_dec_format_defaults) dt->dec_ext = 1; - /* A full IO statement has been matched. Check the constraints. spec_end is - supplied for cases where no locus is supplied. */ - m = check_io_constraints (k, dt, io_code, &spec_end); - - if (m == MATCH_ERROR) - goto cleanup; + /* Check the format string now. */ + if (dt->format_expr + && (!gfc_simplify_expr (dt->format_expr, 0) + || !check_format_string (dt->format_expr, k == M_READ))) + return MATCH_ERROR; new_st.op = (k == M_READ) ? EXEC_READ : EXEC_WRITE; new_st.ext.dt = dt; @@ -4610,8 +4518,6 @@ match_inquire_element (gfc_inquire *inquire) RETM m = match_etag (&tag_file, &inquire->file); RETM m = match_ltag (&tag_err, &inquire->err); RETM m = match_etag (&tag_iomsg, &inquire->iomsg); - if (m == MATCH_YES && !check_char_variable (inquire->iomsg)) - return MATCH_ERROR; RETM m = match_out_tag (&tag_iostat, &inquire->iostat); RETM m = match_vtag (&tag_exist, &inquire->exist); RETM m = match_vtag (&tag_opened, &inquire->opened); @@ -4633,8 +4539,6 @@ match_inquire_element (gfc_inquire *inquire) RETM m = match_vtag (&tag_write, &inquire->write); RETM m = match_vtag (&tag_readwrite, &inquire->readwrite); RETM m = match_vtag (&tag_s_async, &inquire->asynchronous); - if (m == MATCH_YES && !is_char_type ("ASYNCHRONOUS", inquire->asynchronous)) - return MATCH_ERROR; RETM m = match_vtag (&tag_s_delim, &inquire->delim); RETM m = match_vtag (&tag_s_decimal, &inquire->decimal); RETM m = match_out_tag (&tag_size, &inquire->size); @@ -4914,8 +4818,6 @@ match_wait_element (gfc_wait *wait) RETM m = match_ltag (&tag_end, &wait->end); RETM m = match_ltag (&tag_eor, &wait->eor); RETM m = match_etag (&tag_iomsg, &wait->iomsg); - if (m == MATCH_YES && !check_char_variable (wait->iomsg)) - return MATCH_ERROR; RETM m = match_out_tag (&tag_iostat, &wait->iostat); RETM m = match_etag (&tag_id, &wait->id); RETM return MATCH_NO; diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 97de6dd..ccd2a5e 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -9941,9 +9941,6 @@ resolve_transfer (gfc_code *code) "an assumed-size array", &code->loc); return; } - - if (async_io_dt && exp->expr_type == EXPR_VARIABLE) - exp->symtree->n.sym->attr.asynchronous = 1; } @@ -12003,14 +12000,14 @@ start: break; case EXEC_OPEN: - if (!gfc_resolve_open (code->ext.open)) + if (!gfc_resolve_open (code->ext.open, &code->loc)) break; resolve_branch (code->ext.open->err, code); break; case EXEC_CLOSE: - if (!gfc_resolve_close (code->ext.close)) + if (!gfc_resolve_close (code->ext.close, &code->loc)) break; resolve_branch (code->ext.close->err, code); @@ -12052,7 +12049,7 @@ start: case EXEC_READ: case EXEC_WRITE: - if (!gfc_resolve_dt (code->ext.dt, &code->loc)) + if (!gfc_resolve_dt (code, code->ext.dt, &code->loc)) break; resolve_branch (code->ext.dt->err, code); @@ -15009,11 +15006,6 @@ resolve_fl_namelist (gfc_symbol *sym) } } - if (async_io_dt) - { - for (nl = sym->namelist; nl; nl = nl->next) - nl->sym->attr.asynchronous = 1; - } return true; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8c44253..d8fa35a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,29 @@ +2020-04-09 Fritz Reese + + PR fortran/87923 + * gfortran.dg/f2003_io_8.f03: Fix expected error messages. + * gfortran.dg/io_constraints_8.f90: Likewise. + * gfortran.dg/iomsg_2.f90: Likewise. + * gfortran.dg/pr66725.f90: Likewise. + * gfortran.dg/pr88205.f90: Likewise. + * gfortran.dg/write_check4.f90: Likewise. + * gfortran.dg/asynchronous_5.f03: New test. + * gfortran.dg/io_constraints_15.f90: Likewise. + * gfortran.dg/io_constraints_16.f90: Likewise. + * gfortran.dg/io_constraints_17.f90: Likewise. + * gfortran.dg/io_constraints_18.f90: Likewise. + * gfortran.dg/io_tags_1.f90: Likewise. + * gfortran.dg/io_tags_10.f90: Likewise. + * gfortran.dg/io_tags_2.f90: Likewise. + * gfortran.dg/io_tags_3.f90: Likewise. + * gfortran.dg/io_tags_4.f90: Likewise. + * gfortran.dg/io_tags_5.f90: Likewise. + * gfortran.dg/io_tags_6.f90: Likewise. + * gfortran.dg/io_tags_7.f90: Likewise. + * gfortran.dg/io_tags_8.f90: Likewise. + * gfortran.dg/io_tags_9.f90: Likewise. + * gfortran.dg/write_check5.f90: Likewise. + 2020-04-09 Richard Sandiford * gcc.target/aarch64/sve/acle/general/attributes_1.c: New test. diff --git a/gcc/testsuite/gfortran.dg/asynchronous_5.f03 b/gcc/testsuite/gfortran.dg/asynchronous_5.f03 new file mode 100644 index 0000000..fcd281d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/asynchronous_5.f03 @@ -0,0 +1,43 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! +! Covers code introduced by the fix to PR fortran/87923. +! The idea is that the variables in a namelist or I/O list used for +! asynchronous I/O will be marked with the asynchronous attribute. +! +! At this time, "asynchronous" is treated as "volatile" (see trans-decl.c). +! Thus, every variable referenced in an "asynchronous=yes" I/O list +! should obtain the "volatile" specifier in its declaration. +! + +type t + character(4) :: comp_async +end type + +character(2) :: ccvar_async +type(t) :: dvar_async +integer :: ivar_async +real :: rvar_async +logical :: lvar_async +type(t), dimension(2) :: darrvar_async +integer :: ivar_noasync + +namelist /names/ ivar_async, rvar_async, lvar_async + +open(1, asynchronous="yes") +write(1, asynchronous="yes") dvar_async, ccvar_async +write(1, asynchronous="yes") dvar_async%comp_async, darrvar_async +read(1, asynchronous="yes", nml=names) + +open(2, asynchronous="no") +read(2, asynchronous="no") ivar_noasync + +end + +! { dg-final { scan-tree-dump-times "volatile.*?ccvar_async" 1 "original" } } +! { dg-final { scan-tree-dump-times "volatile.*?dvar_async" 1 "original" } } +! { dg-final { scan-tree-dump-times "volatile.*?ivar_async" 1 "original" } } +! { dg-final { scan-tree-dump-times "volatile.*?rvar_async" 1 "original" } } +! { dg-final { scan-tree-dump-times "volatile.*?lvar_async" 1 "original" } } +! { dg-final { scan-tree-dump-times "volatile.*?darrvar_async" 1 "original" } } +! { dg-final { scan-tree-dump-not "volatile.*?ivar_noasync" "original" } } diff --git a/gcc/testsuite/gfortran.dg/f2003_io_8.f03 b/gcc/testsuite/gfortran.dg/f2003_io_8.f03 index 4d2f002..5604e04 100644 --- a/gcc/testsuite/gfortran.dg/f2003_io_8.f03 +++ b/gcc/testsuite/gfortran.dg/f2003_io_8.f03 @@ -9,5 +9,5 @@ character(25) :: msg open(10, file='mydata_f2003_io_8', asynchronous="yes", blank="null") write(10,'(10f8.3)', asynchronous='no', decimal="comma", id=j) a ! { dg-error "must be with ASYNCHRONOUS=" } read(10,'(10f8.3)', id=j, decimal="comma", blank="zero") b ! { dg-error "must be with ASYNCHRONOUS=" } -read(10,'(10f8.3)', asynchronous=msg, decimal="comma", blank="zero") b ! { dg-error "must be an initialization expression" } +read(10,'(10f8.3)', asynchronous=msg, decimal="comma", blank="zero") b ! { dg-error "does not reduce to a constant expression" } end diff --git a/gcc/testsuite/gfortran.dg/io_constraints_15.f90 b/gcc/testsuite/gfortran.dg/io_constraints_15.f90 new file mode 100644 index 0000000..47a5bf6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_constraints_15.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! +! PR fortran/87923 +! +program p + open (1, blank=char(1000,4)) ! { dg-error "must be a character string of default kind" } + open (2, decimal=char(1000,4)) ! { dg-error "must be a character string of default kind" } + open (3, encoding=char(1000,4)) ! { dg-error "must be a character string of default kind" } + open (4, round=char(1000,4)) ! { dg-error "must be a character string of default kind" } + open (5, sign=char(1000,4)) ! { dg-error "must be a character string of default kind" } +end diff --git a/gcc/testsuite/gfortran.dg/io_constraints_16.f90 b/gcc/testsuite/gfortran.dg/io_constraints_16.f90 new file mode 100644 index 0000000..dcbbbae --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_constraints_16.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! +! PR fortran/87923 +! +program p + read (1, blank=char(1000,4)) ! { dg-error "must be a character string of default kind" } + read (1, delim=char(1000,4)) ! { dg-error "must be a character string of default kind" } + read (1, pad=char(1000,4)) ! { dg-error "must be a character string of default kind" } + read (1, round=char(1000,4)) ! { dg-error "must be a character string of default kind" } + read (1, sign=char(1000,4)) ! { dg-error "must be a character string of default kind" } +end diff --git a/gcc/testsuite/gfortran.dg/io_constraints_17.f90 b/gcc/testsuite/gfortran.dg/io_constraints_17.f90 new file mode 100644 index 0000000..5864351 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_constraints_17.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! +! PR fortran/87923 +! +program p + write (1, blank=char(1000,4)) ! { dg-error "must be a character string of default kind" } + write (1, delim=char(1000,4)) ! { dg-error "must be a character string of default kind" } + write (1, pad=char(1000,4)) ! { dg-error "must be a character string of default kind" } + write (1, round=char(1000,4)) ! { dg-error "must be a character string of default kind" } + write (1, sign=char(1000,4)) ! { dg-error "must be a character string of default kind" } +end diff --git a/gcc/testsuite/gfortran.dg/io_constraints_18.f90 b/gcc/testsuite/gfortran.dg/io_constraints_18.f90 new file mode 100644 index 0000000..1694871 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_constraints_18.f90 @@ -0,0 +1,9 @@ +! { dg-options "-fdec" } +! { dg-do compile } +! +! PR fortran/87923 +! +program p + open (1, carriagecontrol=char(1000,4)) ! { dg-error "must be a character string of default kind" } + open (2, share=char(1000,4)) ! { dg-error "must be a character string of default kind" } +end diff --git a/gcc/testsuite/gfortran.dg/io_constraints_8.f90 b/gcc/testsuite/gfortran.dg/io_constraints_8.f90 index 216a41b..e3272e4 100644 --- a/gcc/testsuite/gfortran.dg/io_constraints_8.f90 +++ b/gcc/testsuite/gfortran.dg/io_constraints_8.f90 @@ -14,7 +14,7 @@ integer :: i OPEN(99, access=4_'direct') ! { dg-error "must be a character string of default kind" } OPEN(99, action=4_'read') ! { dg-error "must be a character string of default kind" } -OPEN(99, asynchronous=4_'no') ! { dg-error "must be of default CHARACTER kind" } +OPEN(99, asynchronous=4_'no') ! { dg-error "must be a character string of default kind" } OPEN(99, blank=4_'null') ! { dg-error "must be a character string of default kind" } OPEN(99, decimal=4_'comma') ! { dg-error "must be a character string of default kind" } OPEN(99, delim=4_'quote') ! { dg-error "must be a character string of default kind" } diff --git a/gcc/testsuite/gfortran.dg/io_tags_1.f90 b/gcc/testsuite/gfortran.dg/io_tags_1.f90 new file mode 100644 index 0000000..2ada161 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_1.f90 @@ -0,0 +1,19 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + + +backspace (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +backspace (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +backspace (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +backspace (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +backspace (1, iomsg='') ! { dg-error "Non-variable expression" } +backspace (1, iomsg='no') ! { dg-error "Non-variable expression" } +backspace (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +backspace (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +backspace (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +backspace (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +backspace (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } +backspace (1, iomsg=['no']) ! { dg-error "IOMSG tag at ... must be scalar" } +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_10.f90 b/gcc/testsuite/gfortran.dg/io_tags_10.f90 new file mode 100644 index 0000000..377ac61 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_10.f90 @@ -0,0 +1,103 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +write (1, blank='') ! { dg-error "BLANK specifier in WRITE statement at ... has invalid value" } + +write (1, asynchronous=1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +write (1, asynchronous=1e1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +write (1, asynchronous=1d1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +write (1, asynchronous=.false.) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +write (1, asynchronous='') ! { dg-error "ASYNCHRONOUS specifier in WRITE statement at ... has invalid value" } +write (1, asynchronous='no') +write (1, asynchronous=null()) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +write (1, asynchronous=(1)) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +write (1, asynchronous=(1., 0.)) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +write (1, asynchronous=[1]) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +write (1, asynchronous=['']) ! { dg-error "ASYNCHRONOUS tag at ... must be scalar" } + +write (1, blank=1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +write (1, blank=1e1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +write (1, blank=1d1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +write (1, blank=.false.) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +write (1, blank='no') ! { dg-error "BLANK specifier in WRITE statement at ... has invalid value" } +write (1, blank=null()) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +write (1, blank=(1)) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +write (1, blank=(1., 0.)) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +write (1, blank=[1]) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +write (1, blank=['']) ! { dg-error "BLANK tag at ... must be scalar" } + +write (1, delim=1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +write (1, delim=1e1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +write (1, delim=1d1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +write (1, delim=.false.) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +write (1, delim='') ! { dg-error "DELIM specifier in WRITE statement at ... has invalid value" } +write (1, delim='no') ! { dg-error "DELIM specifier in WRITE statement at ... has invalid value" } +write (1, delim=null()) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +write (1, delim=(1)) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +write (1, delim=(1., 0.)) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +write (1, delim=[1]) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +write (1, delim=['']) ! { dg-error "DELIM tag at ... must be scalar" } + +write (1, decimal=1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +write (1, decimal=1e1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +write (1, decimal=1d1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +write (1, decimal=.false.) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +write (1, decimal='') ! { dg-error "DECIMAL specifier in WRITE statement at ... has invalid value" } +write (1, decimal='no') ! { dg-error "DECIMAL specifier in WRITE statement at ... has invalid value" } +write (1, decimal=null()) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +write (1, decimal=(1)) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +write (1, decimal=(1., 0.)) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +write (1, decimal=[1]) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +write (1, decimal=['']) ! { dg-error "DECIMAL tag at ... must be scalar" } + +write (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +write (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +write (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +write (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +write (1, iomsg='') ! { dg-error "Non-variable expression" } +write (1, iomsg='no') ! { dg-error "Non-variable expression" } +write (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +write (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +write (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +write (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +write (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } + +write (1, pad=1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +write (1, pad=1e1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +write (1, pad=1d1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +write (1, pad=.false.) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +write (1, pad='') ! { dg-error "PAD specifier in WRITE statement at ... has invalid value" } +write (1, pad='no') ! { dg-error "the PAD= specifier at ... must be with an explicit format expression" } +write (1, pad=null()) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +write (1, pad=(1)) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +write (1, pad=(1., 0.)) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +write (1, pad=[1]) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +write (1, pad=['']) ! { dg-error "PAD tag at ... must be scalar" } + +write (1, round=1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +write (1, round=1e1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +write (1, round=1d1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +write (1, round=.false.) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +write (1, round='') ! { dg-error "ROUND specifier in WRITE statement at ... has invalid value" } +write (1, round='no') ! { dg-error "ROUND specifier in WRITE statement at ... has invalid value" } +write (1, round=null()) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +write (1, round=(1)) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +write (1, round=(1., 0.)) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +write (1, round=[1]) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +write (1, round=['']) ! { dg-error "ROUND tag at ... must be scalar" } + +write (1, sign=1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +write (1, sign=1e1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +write (1, sign=1d1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +write (1, sign=.false.) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +write (1, sign='') ! { dg-error "SIGN specifier in WRITE statement at ... has invalid value" } +write (1, sign='no') ! { dg-error "SIGN specifier in WRITE statement at ... has invalid value" } +write (1, sign=null()) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +write (1, sign=(1)) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +write (1, sign=(1., 0.)) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +write (1, sign=[1]) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +write (1, sign=['']) ! { dg-error "SIGN tag at ... must be scalar" } + +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_2.f90 b/gcc/testsuite/gfortran.dg/io_tags_2.f90 new file mode 100644 index 0000000..3eb1137 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_2.f90 @@ -0,0 +1,30 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +close (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +close (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +close (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +close (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +close (1, iomsg='') ! { dg-error "Non-variable expression" } +close (1, iomsg='no') ! { dg-error "Non-variable expression" } +close (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +close (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +close (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +close (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +close (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } +close (1, iomsg=['no']) ! { dg-error "IOMSG tag at ... must be scalar" } + +close (1, status=1) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +close (1, status=1e1) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +close (1, status=1d1) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +close (1, status=.false.) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +close (1, status='') ! { dg-error "STATUS specifier in CLOSE statement at ... has invalid value" } +close (1, status='no') ! { dg-error "STATUS specifier in CLOSE statement at ... has invalid value" } +close (1, status=null()) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +close (1, status=(1)) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +close (1, status=(1., 0.)) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +close (1, status=[1]) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +close (1, status=['']) ! { dg-error "STATUS tag at ... must be scalar" } +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_3.f90 b/gcc/testsuite/gfortran.dg/io_tags_3.f90 new file mode 100644 index 0000000..198342b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_3.f90 @@ -0,0 +1,17 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +endfile (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +endfile (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +endfile (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +endfile (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +endfile (1, iomsg='') ! { dg-error "Non-variable expression" } +endfile (1, iomsg='no') ! { dg-error "Non-variable expression" } +endfile (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +endfile (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +endfile (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +endfile (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +endfile (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_4.f90 b/gcc/testsuite/gfortran.dg/io_tags_4.f90 new file mode 100644 index 0000000..9396ef4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_4.f90 @@ -0,0 +1,17 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +flush (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +flush (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +flush (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +flush (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +flush (1, iomsg='') ! { dg-error "Non-variable expression" } +flush (1, iomsg='no') ! { dg-error "Non-variable expression" } +flush (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +flush (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +flush (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +flush (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +flush (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_5.f90 b/gcc/testsuite/gfortran.dg/io_tags_5.f90 new file mode 100644 index 0000000..a602661 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_5.f90 @@ -0,0 +1,17 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +inquire (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +inquire (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +inquire (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +inquire (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +inquire (1, iomsg='') ! { dg-error "Non-variable expression" } +inquire (1, iomsg='no') ! { dg-error "Non-variable expression" } +inquire (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +inquire (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +inquire (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +inquire (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +inquire (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_6.f90 b/gcc/testsuite/gfortran.dg/io_tags_6.f90 new file mode 100644 index 0000000..a8cc383 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_6.f90 @@ -0,0 +1,175 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +open (1, access=1) ! { dg-error "ACCESS tag at ... must be of type CHARACTER" } +open (1, access=1e1) ! { dg-error "ACCESS tag at ... must be of type CHARACTER" } +open (1, access=1d1) ! { dg-error "ACCESS tag at ... must be of type CHARACTER" } +open (1, access=.false.) ! { dg-error "ACCESS tag at ... must be of type CHARACTER" } +open (1, access='') ! { dg-error "ACCESS specifier in OPEN statement at ... has invalid value" } +open (1, access='no') ! { dg-error "ACCESS specifier in OPEN statement at ... has invalid value" } +open (1, access=null()) ! { dg-error "ACCESS tag at ... must be of type CHARACTER" } +open (1, access=(1)) ! { dg-error "ACCESS tag at ... must be of type CHARACTER" } +open (1, access=(1., 0.)) ! { dg-error "ACCESS tag at ... must be of type CHARACTER" } +open (1, access=[1]) ! { dg-error "ACCESS tag at ... must be of type CHARACTER" } +open (1, access=['']) ! { dg-error "ACCESS tag at ... must be scalar" } + +open (1, action=1) ! { dg-error "ACTION tag at ... must be of type CHARACTER" } +open (1, action=1e1) ! { dg-error "ACTION tag at ... must be of type CHARACTER" } +open (1, action=1d1) ! { dg-error "ACTION tag at ... must be of type CHARACTER" } +open (1, action=.false.) ! { dg-error "ACTION tag at ... must be of type CHARACTER" } +open (1, action='') ! { dg-error "ACTION specifier in OPEN statement at ... has invalid value" } +open (1, action='no') ! { dg-error "ACTION specifier in OPEN statement at ... has invalid value" } +open (1, action=null()) ! { dg-error "ACTION tag at ... must be of type CHARACTER" } +open (1, action=(1)) ! { dg-error "ACTION tag at ... must be of type CHARACTER" } +open (1, action=(1., 0.)) ! { dg-error "ACTION tag at ... must be of type CHARACTER" } +open (1, action=[1]) ! { dg-error "ACTION tag at ... must be of type CHARACTER" } +open (1, action=['']) ! { dg-error "ACTION tag at ... must be scalar" } + +open (1, asynchronous=1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +open (1, asynchronous=1e1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +open (1, asynchronous=1d1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +open (1, asynchronous=.false.) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +open (1, asynchronous='') ! { dg-error "ASYNCHRONOUS specifier in OPEN statement at ... has invalid value" } +open (1, asynchronous='no') +open (1, asynchronous=null()) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +open (1, asynchronous=(1)) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +open (1, asynchronous=(1., 0.)) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +open (1, asynchronous=[1]) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +open (1, asynchronous=['']) ! { dg-error "ASYNCHRONOUS tag at ... must be scalar" } + +open (1, blank=1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +open (1, blank=1e1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +open (1, blank=1d1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +open (1, blank=.false.) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +open (1, blank='') ! { dg-error "BLANK specifier in OPEN statement at ... has invalid value" } +open (1, blank='no') ! { dg-error "BLANK specifier in OPEN statement at ... has invalid value" } +open (1, blank=null()) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +open (1, blank=(1)) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +open (1, blank=(1., 0.)) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +open (1, blank=[1]) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +open (1, blank=['']) ! { dg-error "BLANK tag at ... must be scalar" } + +open (1, delim=1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +open (1, delim=1e1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +open (1, delim=1d1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +open (1, delim=.false.) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +open (1, delim='') ! { dg-error "DELIM specifier in OPEN statement at ... has invalid value" } +open (1, delim='no') ! { dg-error "DELIM specifier in OPEN statement at ... has invalid value" } +open (1, delim=null()) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +open (1, delim=(1)) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +open (1, delim=(1., 0.)) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +open (1, delim=[1]) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +open (1, delim=['']) ! { dg-error "DELIM tag at ... must be scalar" } + +open (1, decimal=1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +open (1, decimal=1e1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +open (1, decimal=1d1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +open (1, decimal=.false.) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +open (1, decimal='') ! { dg-error "DECIMAL specifier in OPEN statement at ... has invalid value" } +open (1, decimal='no') ! { dg-error "DECIMAL specifier in OPEN statement at ... has invalid value" } +open (1, decimal=null()) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +open (1, decimal=(1)) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +open (1, decimal=(1., 0.)) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +open (1, decimal=[1]) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +open (1, decimal=['']) ! { dg-error "DECIMAL tag at ... must be scalar" } + +open (1, encoding=1) ! { dg-error "ENCODING tag at ... must be of type CHARACTER" } +open (1, encoding=1e1) ! { dg-error "ENCODING tag at ... must be of type CHARACTER" } +open (1, encoding=1d1) ! { dg-error "ENCODING tag at ... must be of type CHARACTER" } +open (1, encoding=.false.) ! { dg-error "ENCODING tag at ... must be of type CHARACTER" } +open (1, encoding='') ! { dg-error "ENCODING specifier in OPEN statement at ... has invalid value" } +open (1, encoding='no') ! { dg-error "ENCODING specifier in OPEN statement at ... has invalid value" } +open (1, encoding=null()) ! { dg-error "ENCODING tag at ... must be of type CHARACTER" } +open (1, encoding=(1)) ! { dg-error "ENCODING tag at ... must be of type CHARACTER" } +open (1, encoding=(1., 0.)) ! { dg-error "ENCODING tag at ... must be of type CHARACTER" } +open (1, encoding=[1]) ! { dg-error "ENCODING tag at ... must be of type CHARACTER" } +open (1, encoding=['']) ! { dg-error "ENCODING tag at ... must be scalar" } + +open (1, form=1) ! { dg-error "FORM tag at ... must be of type CHARACTER" } +open (1, form=1e1) ! { dg-error "FORM tag at ... must be of type CHARACTER" } +open (1, form=1d1) ! { dg-error "FORM tag at ... must be of type CHARACTER" } +open (1, form=.false.) ! { dg-error "FORM tag at ... must be of type CHARACTER" } +open (1, form='') ! { dg-error "FORM specifier in OPEN statement at ... has invalid value" } +open (1, form='no') ! { dg-error "FORM specifier in OPEN statement at ... has invalid value" } +open (1, form=null()) ! { dg-error "FORM tag at ... must be of type CHARACTER" } +open (1, form=(1)) ! { dg-error "FORM tag at ... must be of type CHARACTER" } +open (1, form=(1., 0.)) ! { dg-error "FORM tag at ... must be of type CHARACTER" } +open (1, form=[1]) ! { dg-error "FORM tag at ... must be of type CHARACTER" } +open (1, form=['']) ! { dg-error "FORM tag at ... must be scalar" } + +open (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +open (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +open (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +open (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +open (1, iomsg='') ! { dg-error "Non-variable expression" } +open (1, iomsg='no') ! { dg-error "Non-variable expression" } +open (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +open (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +open (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +open (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +open (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } + +open (1, pad=1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +open (1, pad=1e1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +open (1, pad=1d1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +open (1, pad=.false.) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +open (1, pad='') ! { dg-error "PAD specifier in OPEN statement at ... has invalid value" } +open (1, pad='no') +open (1, pad=null()) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +open (1, pad=(1)) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +open (1, pad=(1., 0.)) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +open (1, pad=[1]) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +open (1, pad=['']) ! { dg-error "PAD tag at ... must be scalar" } + +open (1, position=1) ! { dg-error "POSITION tag at ... must be of type CHARACTER" } +open (1, position=1e1) ! { dg-error "POSITION tag at ... must be of type CHARACTER" } +open (1, position=1d1) ! { dg-error "POSITION tag at ... must be of type CHARACTER" } +open (1, position=.false.) ! { dg-error "POSITION tag at ... must be of type CHARACTER" } +open (1, position='') ! { dg-error "POSITION specifier in OPEN statement at ... has invalid value" } +open (1, position='no') ! { dg-error "POSITION specifier in OPEN statement at ... has invalid value" } +open (1, position=null()) ! { dg-error "POSITION tag at ... must be of type CHARACTER" } +open (1, position=(1)) ! { dg-error "POSITION tag at ... must be of type CHARACTER" } +open (1, position=(1., 0.)) ! { dg-error "POSITION tag at ... must be of type CHARACTER" } +open (1, position=[1]) ! { dg-error "POSITION tag at ... must be of type CHARACTER" } +open (1, position=['']) ! { dg-error "POSITION tag at ... must be scalar" } + +open (1, round=1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +open (1, round=1e1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +open (1, round=1d1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +open (1, round=.false.) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +open (1, round='') ! { dg-error "ROUND specifier in OPEN statement at ... has invalid value" } +open (1, round='no') ! { dg-error "ROUND specifier in OPEN statement at ... has invalid value" } +open (1, round=null()) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +open (1, round=(1)) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +open (1, round=(1., 0.)) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +open (1, round=[1]) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +open (1, round=['']) ! { dg-error "ROUND tag at ... must be scalar" } + +open (1, sign=1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +open (1, sign=1e1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +open (1, sign=1d1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +open (1, sign=.false.) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +open (1, sign='') ! { dg-error "SIGN specifier in OPEN statement at ... has invalid value" } +open (1, sign='no') ! { dg-error "SIGN specifier in OPEN statement at ... has invalid value" } +open (1, sign=null()) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +open (1, sign=(1)) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +open (1, sign=(1., 0.)) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +open (1, sign=[1]) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +open (1, sign=['']) ! { dg-error "SIGN tag at ... must be scalar" } + +open (1, status=1) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +open (1, status=1e1) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +open (1, status=1d1) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +open (1, status=.false.) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +open (1, status='') ! { dg-error "STATUS specifier in OPEN statement at ... has invalid value" } +open (1, status='no') ! { dg-error "STATUS specifier in OPEN statement at ... has invalid value" } +open (1, status=null()) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +open (1, status=(1)) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +open (1, status=(1., 0.)) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +open (1, status=[1]) ! { dg-error "STATUS tag at ... must be of type CHARACTER" } +open (1, status=['']) ! { dg-error "STATUS tag at ... must be scalar" } + + +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_7.f90 b/gcc/testsuite/gfortran.dg/io_tags_7.f90 new file mode 100644 index 0000000..12e3189 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_7.f90 @@ -0,0 +1,103 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +read (1, asynchronous=1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +read (1, asynchronous=1e1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +read (1, asynchronous=1d1) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +read (1, asynchronous=.false.) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +read (1, asynchronous='') ! { dg-error "ASYNCHRONOUS specifier in READ statement at ... has invalid value" } +read (1, asynchronous='no') +read (1, asynchronous=null()) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +read (1, asynchronous=(1)) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +read (1, asynchronous=(1., 0.)) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +read (1, asynchronous=[1]) ! { dg-error "ASYNCHRONOUS tag at ... must be of type CHARACTER" } +read (1, asynchronous=['']) ! { dg-error "ASYNCHRONOUS tag at ... must be scalar" } + +read (1, blank=1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +read (1, blank=1e1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +read (1, blank=1d1) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +read (1, blank=.false.) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +read (1, blank='') ! { dg-error "BLANK specifier in READ statement at ... has invalid value" } +read (1, blank='no') ! { dg-error "BLANK specifier in READ statement at ... has invalid value" } +read (1, blank=null()) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +read (1, blank=(1)) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +read (1, blank=(1., 0.)) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +read (1, blank=[1]) ! { dg-error "BLANK tag at ... must be of type CHARACTER" } +read (1, blank=['']) ! { dg-error "BLANK tag at ... must be scalar" } + +read (1, delim=1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +read (1, delim=1e1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +read (1, delim=1d1) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +read (1, delim=.false.) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +read (1, delim='') ! { dg-error "DELIM specifier in READ statement at ... has invalid value" } +read (1, delim='no') ! { dg-error "DELIM specifier in READ statement at ... has invalid value" } +read (1, delim=null()) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +read (1, delim=(1)) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +read (1, delim=(1., 0.)) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +read (1, delim=[1]) ! { dg-error "DELIM tag at ... must be of type CHARACTER" } +read (1, delim=['']) ! { dg-error "DELIM tag at ... must be scalar" } + +read (1, decimal=1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +read (1, decimal=1e1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +read (1, decimal=1d1) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +read (1, decimal=.false.) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +read (1, decimal='') ! { dg-error "DECIMAL specifier in READ statement at ... has invalid value" } +read (1, decimal='no') ! { dg-error "DECIMAL specifier in READ statement at ... has invalid value" } +read (1, decimal=null()) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +read (1, decimal=(1)) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +read (1, decimal=(1., 0.)) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +read (1, decimal=[1]) ! { dg-error "DECIMAL tag at ... must be of type CHARACTER" } +read (1, decimal=['']) ! { dg-error "DECIMAL tag at ... must be scalar" } + +read (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +read (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +read (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +read (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +read (1, iomsg='') ! { dg-error "Non-variable expression" } +read (1, iomsg='no') ! { dg-error "Non-variable expression" } +read (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +read (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +read (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +read (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +read (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } + +read (1, pad=1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +read (1, pad=1e1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +read (1, pad=1d1) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +read (1, pad=.false.) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +read (1, pad='') ! { dg-error "PAD specifier in READ statement at ... has invalid value" } +read (1, pad='no') ! { dg-error "the PAD= specifier at ... must be with an explicit format expression" } +read (1, pad=null()) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +read (1, pad=(1)) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +read (1, pad=(1., 0.)) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +read (1, pad=[1]) ! { dg-error "PAD tag at ... must be of type CHARACTER" } +read (1, pad=['']) ! { dg-error "PAD tag at ... must be scalar" } + +read (1, round=1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +read (1, round=1e1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +read (1, round=1d1) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +read (1, round=.false.) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +read (1, round='') ! { dg-error "ROUND specifier in READ statement at ... has invalid value" } +read (1, round='no') ! { dg-error "ROUND specifier in READ statement at ... has invalid value" } +read (1, round=null()) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +read (1, round=(1)) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +read (1, round=(1., 0.)) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +read (1, round=[1]) ! { dg-error "ROUND tag at ... must be of type CHARACTER" } +read (1, round=['']) ! { dg-error "ROUND tag at ... must be scalar" } + +read (1, sign=1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +read (1, sign=1e1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +read (1, sign=1d1) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +read (1, sign=.false.) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +read (1, sign='') ! { dg-error "SIGN specifier in READ statement at ... has invalid value" } +read (1, sign='no') ! { dg-error "SIGN specifier in READ statement at ... has invalid value" } +read (1, sign=null()) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +read (1, sign=(1)) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +read (1, sign=(1., 0.)) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +read (1, sign=[1]) ! { dg-error "SIGN tag at ... must be of type CHARACTER" } +read (1, sign=['']) ! { dg-error "SIGN tag at ... must be scalar" } + + +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_8.f90 b/gcc/testsuite/gfortran.dg/io_tags_8.f90 new file mode 100644 index 0000000..f37210e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_8.f90 @@ -0,0 +1,18 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +rewind (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +rewind (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +rewind (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +rewind (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +rewind (1, iomsg='') ! { dg-error "Non-variable expression" } +rewind (1, iomsg='no') ! { dg-error "Non-variable expression" } +rewind (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +rewind (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +rewind (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +rewind (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +rewind (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } + +end diff --git a/gcc/testsuite/gfortran.dg/io_tags_9.f90 b/gcc/testsuite/gfortran.dg/io_tags_9.f90 new file mode 100644 index 0000000..55f9545 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_tags_9.f90 @@ -0,0 +1,18 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! Based on PR fortran/66724, also covers fortran/66725 and fortran/87923. +! + +wait (1, iomsg=1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +wait (1, iomsg=1e1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +wait (1, iomsg=1d1) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +wait (1, iomsg=.false.) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +wait (1, iomsg='') ! { dg-error "Non-variable expression" } +wait (1, iomsg='no') ! { dg-error "Non-variable expression" } +wait (1, iomsg=null()) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +wait (1, iomsg=(1)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +wait (1, iomsg=(1., 0.)) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +wait (1, iomsg=[1]) ! { dg-error "IOMSG tag at ... must be of type CHARACTER" } +wait (1, iomsg=['']) ! { dg-error "IOMSG tag at ... must be scalar" } + +end diff --git a/gcc/testsuite/gfortran.dg/iomsg_2.f90 b/gcc/testsuite/gfortran.dg/iomsg_2.f90 index 29500ed0..5023692 100644 --- a/gcc/testsuite/gfortran.dg/iomsg_2.f90 +++ b/gcc/testsuite/gfortran.dg/iomsg_2.f90 @@ -2,30 +2,30 @@ subroutine foo1 implicit none integer i - open(1, iomsg=666) ! { dg-error "IOMSG must be" } - open(1, iomsg='sgk') ! { dg-error "IOMSG must be" } - open(1, iomsg=i) ! { dg-error "IOMSG must be" } - close(1, iomsg=666) ! { dg-error "IOMSG must be" } - close(1, iomsg='sgk') ! { dg-error "IOMSG must be" } - close(1, iomsg=i) ! { dg-error "IOMSG must be" } + open(1, iomsg=666) ! { dg-error "must be of type CHARACTER" } + open(1, iomsg='sgk') ! { dg-error "Non-variable expression" } + open(1, iomsg=i) ! { dg-error "must be of type CHARACTER" } + close(1, iomsg=666) ! { dg-error "must be of type CHARACTER" } + close(1, iomsg='sgk') ! { dg-error "Non-variable expression" } + close(1, iomsg=i) ! { dg-error "must be of type CHARACTER" } end subroutine foo1 subroutine foo implicit none integer i real :: x = 1 - write(1, *, iomsg='sgk') x ! { dg-error "IOMSG must be" } - write(1, *, iomsg=i) x ! { dg-error "IOMSG must be" } - read(1, *, iomsg='sgk') x ! { dg-error "IOMSG must be" } - read(1, *, iomsg=i) x ! { dg-error "IOMSG must be" } - flush(1, iomsg='sgk') ! { dg-error "IOMSG must be" } - flush(1, iomsg=i) ! { dg-error "IOMSG must be" } - rewind(1, iomsg='sgk') ! { dg-error "IOMSG must be" } - rewind(1, iomsg=i) ! { dg-error "IOMSG must be" } - backspace(1,iomsg='sgk') ! { dg-error "IOMSG must be" } - backspace(1,iomsg=i) ! { dg-error "IOMSG must be" } - wait(1, iomsg='sgk') ! { dg-error "IOMSG must be" } - wait(1, iomsg=i) ! { dg-error "IOMSG must be" } + write(1, *, iomsg='sgk') x ! { dg-error "Non-variable expression" } + write(1, *, iomsg=i) x ! { dg-error "must be of type CHARACTER" } + read(1, *, iomsg='sgk') x ! { dg-error "Non-variable expression" } + read(1, *, iomsg=i) x ! { dg-error "must be of type CHARACTER" } + flush(1, iomsg='sgk') ! { dg-error "Non-variable expression" } + flush(1, iomsg=i) ! { dg-error "must be of type CHARACTER" } + rewind(1, iomsg='sgk') ! { dg-error "Non-variable expression" } + rewind(1, iomsg=i) ! { dg-error "must be of type CHARACTER" } + backspace(1,iomsg='sgk') ! { dg-error "Non-variable expression" } + backspace(1,iomsg=i) ! { dg-error "must be of type CHARACTER" } + wait(1, iomsg='sgk') ! { dg-error "Non-variable expression" } + wait(1, iomsg=i) ! { dg-error "must be of type CHARACTER" } end subroutine foo subroutine bar diff --git a/gcc/testsuite/gfortran.dg/pr66725.f90 b/gcc/testsuite/gfortran.dg/pr66725.f90 index 8ad97f7..d845646 100644 --- a/gcc/testsuite/gfortran.dg/pr66725.f90 +++ b/gcc/testsuite/gfortran.dg/pr66725.f90 @@ -3,29 +3,29 @@ ! program foo - open(unit=1,access = 999) ! { dg-error "ACCESS requires" } - open(unit=1,action = 999) ! { dg-error "ACTION requires" } - open(unit=1,asynchronous = 999) ! { dg-error "ASYNCHRONOUS requires" } - open(unit=1,blank = 999) ! { dg-error "BLANK requires" } - open(unit=1,decimal = 999) ! { dg-error "DECIMAL requires" } - open(unit=1,delim = 999) ! { dg-error "DELIM requires" } - open(unit=1,encoding = 999) ! { dg-error "ENCODING requires" } - open(unit=1,form = 999) ! { dg-error "FORM requires" } - open(unit=1,pad = 999) ! { dg-error "PAD requires" } - open(unit=1,position = 999) ! { dg-error "POSITION requires" } - open(unit=1,round = 999) ! { dg-error "ROUND requires" } - open(unit=1,sign = 999) ! { dg-error "SIGN requires" } - open(unit=1,status = 999) ! { dg-error "STATUS requires" } + open(unit=1,access = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,action = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,asynchronous = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,blank = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,decimal = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,delim = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,encoding = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,form = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,pad = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,position = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,round = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,sign = 999) ! { dg-error "must be of type CHARACTER" } + open(unit=1,status = 999) ! { dg-error "must be of type CHARACTER" } - close(unit=1, status=999) ! { dg-error "STATUS requires" } + close(unit=1, status=999) ! { dg-error "must be of type CHARACTER" } - write (unit=1, asynchronous=257) ! { dg-error "ASYNCHRONOUS requires" } - write (unit=1, delim=257) ! { dg-error "DELIM requires" } - write (unit=1, decimal=257) ! { dg-error "DECIMAL requires" } - write (unit=1, round=257) ! { dg-error "ROUND requires" } - write (unit=1, sign=257) ! { dg-error "SIGN requires" } + write (unit=1, asynchronous=257) ! { dg-error "must be of type CHARACTER" } + write (unit=1, delim=257) ! { dg-error "must be of type CHARACTER" } + write (unit=1, decimal=257) ! { dg-error "must be of type CHARACTER" } + write (unit=1, round=257) ! { dg-error "must be of type CHARACTER" } + write (unit=1, sign=257) ! { dg-error "must be of type CHARACTER" } - write (unit=1, blank=257) ! { dg-error "BLANK requires" } - write (unit=1, pad=257) ! { dg-error "PAD requires" } + write (unit=1, blank=257) ! { dg-error "must be of type CHARACTER" } + write (unit=1, pad=257) ! { dg-error "must be of type CHARACTER" } end program foo diff --git a/gcc/testsuite/gfortran.dg/pr88205.f90 b/gcc/testsuite/gfortran.dg/pr88205.f90 index d9e0806..419bad3 100644 --- a/gcc/testsuite/gfortran.dg/pr88205.f90 +++ b/gcc/testsuite/gfortran.dg/pr88205.f90 @@ -2,13 +2,13 @@ ! PR fortran/88205 subroutine s1 real, parameter :: status = 0 - open (newunit=n, status=status) ! { dg-error "STATUS requires" } + open (newunit=n, status=status) ! { dg-error "must be of type CHARACTER" } end subroutine s2 complex, parameter :: status = 0 - open (newunit=n, status=status) ! { dg-error "STATUS requires" } + open (newunit=n, status=status) ! { dg-error "must be of type CHARACTER" } end program p logical, parameter :: status = .false. - open (newunit=a, status=status) ! { dg-error "STATUS requires" } + open (newunit=a, status=status) ! { dg-error "must be of type CHARACTER" } end diff --git a/gcc/testsuite/gfortran.dg/write_check4.f90 b/gcc/testsuite/gfortran.dg/write_check4.f90 index f418ba8..107baca 100644 --- a/gcc/testsuite/gfortran.dg/write_check4.f90 +++ b/gcc/testsuite/gfortran.dg/write_check4.f90 @@ -11,7 +11,7 @@ no = "no" open (unit=10, asynchronous = no) ! Ok, it isn't a transfer stmt write(*,*, asynchronous="Y"//"E"//trim("S ")) ! Ok, it is an init expr - write(*,*, asynchronous=no) ! { dg-error "must be an initialization expression" } + write(*,*, asynchronous=no) ! { dg-error "does not reduce to a constant expression" } read (*,*, asynchronous="Y"//"e"//trim("S ")) - read (*,*, asynchronous=no) ! { dg-error "must be an initialization expression" } + read (*,*, asynchronous=no) ! { dg-error "does not reduce to a constant expression" } end diff --git a/gcc/testsuite/gfortran.dg/write_check5.f90 b/gcc/testsuite/gfortran.dg/write_check5.f90 new file mode 100644 index 0000000..296c51a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/write_check5.f90 @@ -0,0 +1,24 @@ +! { dg-do compile } +! +! The asynchronous specifier for a data transfer statement shall be +! an initialization expression +! + +module write_check5 +contains + +function no() + implicit none + character(3) :: no + no = "yes" +endfunction + +end module + +use write_check5 +implicit none + +open (unit=10, asynchronous=no()) ! Ok, it isn't a transfer stmt +write(*,*, asynchronous=no()) ! { dg-error "must be an intrinsic function" } +read (*,*, asynchronous=no()) ! { dg-error "must be an intrinsic function" } +end -- cgit v1.1 From fef3d8b4a072757a0a4970b3ce566c354de150d3 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 10 Apr 2020 00:16:23 +0000 Subject: Daily bump. --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ef1034d..475ee88 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20200409 +20200410 -- cgit v1.1 From d09f80ae014613edb0197b36d94242f83da75696 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 9 Apr 2020 17:42:37 -0700 Subject: compiler: look up composite literal keys in the global namespace A composite literal key may not have a global definition, so Gogo::define_global_names may not see it. In order to correctly handle the case in which a predeclared identifier is used as a composite literal key, do an explicit check of the global namespace. Test case is https://golang.org/cl/227783. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/227784 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index c5e8b29..b3cc9ec 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -4a31d064fd6996f64b620104e849292af8f25e12 +b31fbf7d8f23508cfbd578c5c44b13eefd8f359e The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 42ad93b..deac874 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -16032,9 +16032,17 @@ Composite_literal_key_expression::do_lower(Gogo* gogo, Named_object*, Named_object* no = gogo->lookup(this->name_, NULL); if (no == NULL) { - go_error_at(this->location(), "reference to undefined name %qs", - Gogo::message_name(this->name_).c_str()); - return Expression::make_error(this->location()); + // Gogo::lookup doesn't look in the global namespace, and names + // used in composite literal keys aren't seen by + // Gogo::define_global_names, so we have to look in the global + // namespace ourselves. + no = gogo->lookup_global(Gogo::unpack_hidden_name(this->name_).c_str()); + if (no == NULL) + { + go_error_at(this->location(), "reference to undefined name %qs", + Gogo::message_name(this->name_).c_str()); + return Expression::make_error(this->location()); + } } return Expression::make_unknown_reference(no, this->location()); } -- cgit v1.1 From d79a22eddc694970316992927c669dd801e07557 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 8 Apr 2020 16:51:01 -0700 Subject: libgo: update to final 1.14.2 release Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/227551 --- gcc/go/gofrontend/MERGE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index b3cc9ec..138425a 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -b31fbf7d8f23508cfbd578c5c44b13eefd8f359e +89fbf55a409d37ae898e5c4ea4250035f86bed1b The first line of this file holds the git revision number of the last merge done from the gofrontend repository. -- cgit v1.1 From 6c4a05f251ae8a39fa896524defaf4228328c259 Mon Sep 17 00:00:00 2001 From: Bin Cheng Date: Fri, 10 Apr 2020 12:38:53 +0800 Subject: Simplify co_await_expander. gcc/cp 2020-04-10 Bin Cheng * coroutines.cc (co_await_expander): Simplify. gcc/testsuite 2020-04-10 Bin Cheng * g++.dg/coroutines/co-await-syntax-10.C: New test. * g++.dg/coroutines/co-await-syntax-11.C: New test. --- gcc/cp/ChangeLog | 4 + gcc/cp/coroutines.cc | 25 +-- gcc/testsuite/ChangeLog | 5 + .../g++.dg/coroutines/co-await-syntax-10.C | 40 ++++ .../g++.dg/coroutines/co-await-syntax-11.C | 205 +++++++++++++++++++++ 5 files changed, 257 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/co-await-syntax-10.C create mode 100644 gcc/testsuite/g++.dg/coroutines/co-await-syntax-11.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 49246e8..38f86cd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2020-04-10 Bin Cheng + + * coroutines.cc (co_await_expander): Simplify. + 2020-04-09 Jason Merrill PR c++/94523 diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 936be06..ab06c0a 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -1389,34 +1389,13 @@ co_await_expander (tree *stmt, int * /*do_subtree*/, void *d) return NULL_TREE; coro_aw_data *data = (coro_aw_data *) d; - enum tree_code stmt_code = TREE_CODE (*stmt); tree stripped_stmt = *stmt; - - /* Look inside <(void) (expr)> cleanup */ - if (stmt_code == CLEANUP_POINT_EXPR) - { - stripped_stmt = TREE_OPERAND (*stmt, 0); - stmt_code = TREE_CODE (stripped_stmt); - if (stmt_code == EXPR_STMT - && (TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CONVERT_EXPR - || TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CAST_EXPR) - && VOID_TYPE_P (TREE_TYPE (EXPR_STMT_EXPR (stripped_stmt)))) - { - stripped_stmt = TREE_OPERAND (EXPR_STMT_EXPR (stripped_stmt), 0); - stmt_code = TREE_CODE (stripped_stmt); - } - } - tree *buried_stmt = NULL; tree saved_co_await = NULL_TREE; enum tree_code sub_code = NOP_EXPR; - if (stmt_code == EXPR_STMT - && TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CO_AWAIT_EXPR) - saved_co_await - = EXPR_STMT_EXPR (stripped_stmt); /* hopefully, a void exp. */ - else if (stmt_code == MODIFY_EXPR || stmt_code == INIT_EXPR) + if (stmt_code == MODIFY_EXPR || stmt_code == INIT_EXPR) { sub_code = TREE_CODE (TREE_OPERAND (stripped_stmt, 1)); if (sub_code == CO_AWAIT_EXPR) @@ -1435,6 +1414,8 @@ co_await_expander (tree *stmt, int * /*do_subtree*/, void *d) else if ((stmt_code == CONVERT_EXPR || stmt_code == NOP_EXPR) && TREE_CODE (TREE_OPERAND (stripped_stmt, 0)) == CO_AWAIT_EXPR) saved_co_await = TREE_OPERAND (stripped_stmt, 0); + else if (stmt_code == CO_AWAIT_EXPR) + saved_co_await = stripped_stmt; if (!saved_co_await) return NULL_TREE; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d8fa35a..72e0d51 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-10 Bin Cheng + + * g++.dg/coroutines/co-await-syntax-10.C: New test. + * g++.dg/coroutines/co-await-syntax-11.C: New test. + 2020-04-09 Fritz Reese PR fortran/87923 diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-syntax-10.C b/gcc/testsuite/g++.dg/coroutines/co-await-syntax-10.C new file mode 100644 index 0000000..8304344 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/co-await-syntax-10.C @@ -0,0 +1,40 @@ +// { dg-additional-options "-std=c++17 -w" } + +#include "coro.h" + +class await { +public: + class promise_type { + public: + std::suspend_always initial_suspend() const noexcept { return {}; } + std::suspend_always final_suspend() const noexcept { return {}; } + void unhandled_exception() noexcept { } + await get_return_object() { return await{}; } + void return_void() {} + }; + bool await_ready() const noexcept { return false; } + bool await_suspend(std::coroutine_handle<>) noexcept {return true;} + void await_resume() { } +}; + +class mycoro { +public: + class promise_type { + public: + std::suspend_always initial_suspend() const noexcept { return {}; } + std::suspend_always final_suspend() const noexcept { return {}; } + void unhandled_exception() noexcept { } + mycoro get_return_object() { return mycoro{}; } + void return_void() {} + }; +}; +mycoro foo(await awaitable) { + co_return co_await awaitable; +} + +mycoro bar() +{ + auto t = [&]() -> await { co_return; }(); + return foo (t); +} + diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-syntax-11.C b/gcc/testsuite/g++.dg/coroutines/co-await-syntax-11.C new file mode 100644 index 0000000..69810ab --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/co-await-syntax-11.C @@ -0,0 +1,205 @@ +// { dg-additional-options "-std=c++17 -w" } + +#include +#include +#include +#include +#include + +struct any { + template any(T &&) noexcept; +}; + +template +auto get_awaiter_impl(T &&value, int) noexcept + -> decltype(static_cast(value).operator co_await()) { + return static_cast(value).operator co_await(); +} +template +T &&get_awaiter_impl(T &&value, any) noexcept; +template +auto get_awaiter(T &&value) noexcept + -> decltype(get_awaiter_impl(static_cast(value), 123)) { + return get_awaiter_impl(static_cast(value), 123); +} + +template struct awaitable_traits { + using awaiter_t = decltype(get_awaiter(std::declval())); + using await_result_t = decltype(std::declval().await_resume()); +}; + +template class when_all_ready_awaitable; +template +class when_all_ready_awaitable> { +public: + explicit when_all_ready_awaitable(std::tuple &&tasks) noexcept + : m_tasks(std::move(tasks)) {} + auto operator co_await() &&noexcept { + struct awaiter { + awaiter(when_all_ready_awaitable &awaitable) noexcept + : m_awaitable(awaitable) {} + bool await_ready() const noexcept { return false; } + bool await_suspend() noexcept { return false; } + std::tuple &&await_resume() noexcept { + return std::move(m_awaitable.m_tasks); + } + when_all_ready_awaitable& m_awaitable; + }; + return awaiter{*this}; + } + std::tuple m_tasks; +}; + +inline void *operator new(std::size_t, void *__p) noexcept; + +template +class when_all_task_promise final{ +public: + using coroutine_handle_t = std::coroutine_handle; + RESULT &&result() &&; +}; +template class when_all_task final { +public: + using promise_type = when_all_task_promise; + using coroutine_handle_t = typename promise_type::coroutine_handle_t; + decltype(auto) result() &; + decltype(auto) result() && { + return std::move(m_coroutine.promise()).result(); + } + decltype(auto) non_void_result() && { + if constexpr (std::is_void_v) + ; + else + return std::move(*this).result(); + } + coroutine_handle_t m_coroutine; +}; +class task; +template ::await_result_t, + std::enable_if_t, int> = 0> +when_all_task make_when_all_task(AWAITABLE awaitable); + +template +inline auto when_all_ready(AWAITABLES &&... awaitables) { + return when_all_ready_awaitable< + std::tuple>::await_result_t>...>>( + std::make_tuple( + make_when_all_task(std::forward(awaitables))...)); +} + +template class fmap_awaiter { + using awaiter_t = typename awaitable_traits::awaiter_t; + +public: + fmap_awaiter(FUNC &&func, AWAITABLE &&awaitable) noexcept + : m_func(static_cast(func)), + m_awaiter(get_awaiter(static_cast(awaitable))) {} + decltype(auto) await_ready() noexcept { + return static_cast(m_awaiter).await_ready(); + } + template + decltype(auto) await_suspend(std::coroutine_handle coro) noexcept {} + template ().await_resume()), + std::enable_if_t, int> = 0> + decltype(auto) await_resume() noexcept { + return std::invoke(static_cast(m_func), + static_cast(m_awaiter).await_resume()); + } + +private: + FUNC &&m_func; + awaiter_t m_awaiter; +}; +template class fmap_awaitable { +public: + template < + typename FUNC_ARG, typename AWAITABLE_ARG, + std::enable_if_t && + std::is_constructible_v, + int> = 0> + explicit fmap_awaitable(FUNC_ARG &&func, AWAITABLE_ARG &&awaitable) noexcept + : m_func(static_cast(func)), + m_awaitable(static_cast(awaitable)) {} + auto operator co_await() && { + return fmap_awaiter(static_cast(m_func), + static_cast(m_awaitable)); + } + +private: + FUNC m_func; + AWAITABLE m_awaitable; +}; + +template +auto fmap(FUNC &&func, AWAITABLE &&awaitable) { + return fmap_awaitable>, + std::remove_cv_t>>( + std::forward(func), std::forward(awaitable)); +} +template +auto when_all(AWAITABLES &&... awaitables) { + return fmap( + [](auto &&taskTuple) { + decltype(auto) __trans_tmp_1 = std::apply( + [](auto &&... tasks) { + return std::make_tuple( + static_cast(tasks).non_void_result()...); + }, + static_cast(taskTuple)); + return __trans_tmp_1; + }, + when_all_ready(std::forward(awaitables)...)); +} +class async_mutex_scoped_lock_operation; +class async_mutex { +public: + async_mutex() noexcept; + async_mutex_scoped_lock_operation scoped_lock_async() noexcept; +}; +class async_mutex_lock { +public: + explicit async_mutex_lock(); + ~async_mutex_lock(); + +private: + async_mutex *m_mutex; +}; +class async_mutex_scoped_lock_operation { +public: + async_mutex_lock await_resume() const noexcept; +}; +class task { +public: + class promise_type { + public: + auto initial_suspend() noexcept { return std::suspend_always{}; } + auto final_suspend() noexcept { return std::suspend_always{}; } + task get_return_object() noexcept { return task{}; } + void unhandled_exception() noexcept {} + void return_value(int value) noexcept { v = value; } + int result(){ return v; } + int v = 0; + }; +public: + task() noexcept {} + auto operator co_await() const &noexcept { + struct awaitable { + std::coroutine_handle m_coroutine; + decltype(auto) await_resume() { + return this->m_coroutine.promise().result(); + } + }; + return awaitable{}; + } +}; +void foo() { + (void) []() -> task { + auto makeTask = [](int x) -> task { co_return x; }; + async_mutex_scoped_lock_operation op; + co_await when_all(std::move(op), makeTask(123)); + }(); +} -- cgit v1.1 From 7478addd84ab6808307f4f285ab05f3a76bbb257 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Fri, 10 Apr 2020 09:35:09 +0200 Subject: libphobos: Use libdruntime as a convenience library for libphobos. As a prerequesite for PR94304, it becomes easier to manage selectively compiling sublibraries when there's only one library to link to. So a druntime convenience library is built to be part of phobos, however separate druntime library is still built and installed, to allow linking only to the core runtime explicitly, rather than pulling in the entire standard library with it. The gdc driver no longer generates an '-lgdruntime' option, and the inclusion of the libdruntime library path has been removed from the testsuite. gcc/d/ChangeLog: * d-spec.cc (LIBDRUNTIME): Remove. (LIBDRUNTIME_PROFILE): Remove. (lang_specific_driver): Don't link in libgdruntime. gcc/testsuite/ChangeLog: * lib/gdc.exp (gdc_link_flags): Remove libdruntime library path. libphobos/ChangeLog: * d_rules.am (libdgruntime_la_LINK): Move to libdruntime/Makefile.am. (libgphobos_la_LINK): Move to src/Makefile.am * libdruntime/Makefile.am: Add libgdruntime_convenience library. * libdruntime/Makefile.in: Regenerate. * src/Makefile.am (libgphobos_la_LIBADD): Add libgdruntime_convenience library. (libgphobos_la_DEPENDENCIES): Likewise. * src/Makefile.in: Regenerate. * testsuite/lib/libphobos.exp: Remove libdruntime library paths. * testsuite/testsuite_flags.in: Likewise. --- gcc/d/ChangeLog | 6 ++++++ gcc/d/d-spec.cc | 14 +------------- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/lib/gdc.exp | 14 ++------------ 4 files changed, 13 insertions(+), 25 deletions(-) (limited to 'gcc') diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 73fd184..5f7e967 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,9 @@ +2020-04-10 Iain Buclaw + + * d-spec.cc (LIBDRUNTIME): Remove. + (LIBDRUNTIME_PROFILE): Remove. + (lang_specific_driver): Don't link in libgdruntime. + 2020-04-07 Iain Buclaw PR d/94425 diff --git a/gcc/d/d-spec.cc b/gcc/d/d-spec.cc index 8a0c7ca..e084422 100644 --- a/gcc/d/d-spec.cc +++ b/gcc/d/d-spec.cc @@ -44,13 +44,6 @@ along with GCC; see the file COPYING3. If not see #define LIBPHOBOS_PROFILE LIBPHOBOS #endif -#ifndef LIBDRUNTIME -#define LIBDRUNTIME "gdruntime" -#endif -#ifndef LIBDRUNTIME_PROFILE -#define LIBDRUNTIME_PROFILE LIBDRUNTIME -#endif - /* What do with libgphobos. */ enum phobos_action { @@ -322,7 +315,7 @@ lang_specific_driver (cl_decoded_option **in_decoded_options, /* Make sure to have room for the trailing NULL argument. - needstdcxx might add `-lstdcxx' - - libphobos adds `-Bstatic -lphobos -ldruntime -Bdynamic' + - libphobos adds `-Bstatic -lphobos -Bdynamic' - only_source adds 1 more arg, also maybe add `-o'. */ num_args = argc + need_stdcxx + shared_libgcc + need_phobos * 4 + 2; new_decoded_options = XNEWVEC (cl_decoded_option, num_args); @@ -442,11 +435,6 @@ lang_specific_driver (cl_decoded_option **in_decoded_options, CL_DRIVER, &new_decoded_options[j]); added_libraries++; j++; - generate_option (OPT_l, - saw_profile_flag ? LIBDRUNTIME_PROFILE : LIBDRUNTIME, 1, - CL_DRIVER, &new_decoded_options[j]); - added_libraries++; - j++; #ifdef HAVE_LD_STATIC_DYNAMIC if (phobos_library == PHOBOS_DYNAMIC && static_link) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 72e0d51..bced3e2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-04-10 Iain Buclaw + + * lib/gdc.exp (gdc_link_flags): Remove libdruntime library paths. + 2020-04-10 Bin Cheng * g++.dg/coroutines/co-await-syntax-10.C: New test. diff --git a/gcc/testsuite/lib/gdc.exp b/gcc/testsuite/lib/gdc.exp index ddc6d90..3912d9c 100644 --- a/gcc/testsuite/lib/gdc.exp +++ b/gcc/testsuite/lib/gdc.exp @@ -146,16 +146,11 @@ proc gdc_link_flags { paths } { append flags "-L${gccpath}/libphobos/src/.libs " append ld_library_path ":${gccpath}/libphobos/src/.libs" } - if { [file exists "${gccpath}/libphobos/libdruntime/.libs/libgdruntime.a"] \ - || [file exists "${gccpath}/libphobos/libdruntime/.libs/libgdruntime.${shlib_ext}"] } { - append flags "-L${gccpath}/libphobos/libdruntime/.libs " - append ld_library_path ":${gccpath}/libphobos/libdruntime/.libs" - } # Static linking is default. If only the shared lib is available adjust # flags to always use it. If both are available, set SHARED_OPTION which # will be added to PERMUTE_ARGS - if { [file exists "${gccpath}/libphobos/libdruntime/.libs/libgdruntime.${shlib_ext}"] } { - if { [file exists "${gccpath}/libphobos/libdruntime/.libs/libgdruntime.a"] } { + if { [file exists "${gccpath}/libphobos/src/.libs/libgphobos.${shlib_ext}"] } { + if { [file exists "${gccpath}/libphobos/src/.libs/libgphobos.a"] } { set SHARED_OPTION "-shared-libphobos" } else { append flags "-shared-libphobos " @@ -181,11 +176,6 @@ proc gdc_link_flags { paths } { append flags "-B${libphobos} -L${libphobos} " append ld_library_path ":${libphobos}" } - set libdruntime [lookfor_file ${tool_root_dir} libgdruntime] - if { $libdruntime != "" } { - append flags "-L${libdruntime} " - append ld_library_path ":${libdruntime}" - } set libiberty [lookfor_file ${tool_root_dir} libiberty] if { $libiberty != "" } { append flags "-L${libiberty} " -- cgit v1.1 From ff3f862b451496dd4afbe2dbfae82afab59a42c6 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Wed, 4 Mar 2020 17:58:33 +0100 Subject: Handle 'omp declare target' attribute set for both OpenACC and OpenMP 'target' [PR89433, PR93465] ... which as of PR89433 commit b48f44bf77a39fefc238a16cf1225c6464c82406 causes an ICE. Not sure if this is actually supposed to be valid or invalid code. Until the interactions between OpenACC and OpenMP 'target' get defined properly, make this a compile-time error. gcc/ PR middle-end/89433 PR middle-end/93465 * omp-general.c (oacc_verify_routine_clauses): Diagnose if "#pragma omp declare target" has also been applied. gcc/testsuite/ PR middle-end/89433 PR middle-end/93465 * c-c++-common/goacc-gomp/pr93465-1.c: New file. --- gcc/ChangeLog | 7 +++ gcc/omp-general.c | 13 ++++++ gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/c-c++-common/goacc-gomp/pr93465-1.c | 56 +++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/goacc-gomp/pr93465-1.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bce700e..33e980b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2020-04-10 Thomas Schwinge + + PR middle-end/89433 + PR middle-end/93465 + * omp-general.c (oacc_verify_routine_clauses): Diagnose if + "#pragma omp declare target" has also been applied. + 2020-04-09 Jozef Lawrynowicz * config/msp430/msp430.c (msp430_expand_epilogue): Use emit_jump_insn diff --git a/gcc/omp-general.c b/gcc/omp-general.c index f107f4c..49023f4 100644 --- a/gcc/omp-general.c +++ b/gcc/omp-general.c @@ -1776,6 +1776,19 @@ oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc, = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)); if (attr != NULL_TREE) { + /* Diagnose if "#pragma omp declare target" has also been applied. */ + if (TREE_VALUE (attr) == NULL_TREE) + { + /* See ; the semantics of combining + OpenACC and OpenMP 'target' are not clear. */ + error_at (loc, + "cannot apply %<%s%> to %qD, which has also been" + " marked with an OpenMP 'declare target' directive", + routine_str, fndecl); + /* Incompatible. */ + return -1; + } + /* If a "#pragma acc routine" has already been applied, just verify this one for compatibility. */ /* Collect previous directive's clauses. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bced3e2..235d481 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-10 Thomas Schwinge + + PR middle-end/89433 + PR middle-end/93465 + * c-c++-common/goacc-gomp/pr93465-1.c: New file. + 2020-04-10 Iain Buclaw * lib/gdc.exp (gdc_link_flags): Remove libdruntime library paths. diff --git a/gcc/testsuite/c-c++-common/goacc-gomp/pr93465-1.c b/gcc/testsuite/c-c++-common/goacc-gomp/pr93465-1.c new file mode 100644 index 0000000..c8b9135 --- /dev/null +++ b/gcc/testsuite/c-c++-common/goacc-gomp/pr93465-1.c @@ -0,0 +1,56 @@ +#pragma omp declare target +#pragma acc routine seq /* { dg-error "cannot apply '#pragma acc routine' to '\(void \)?f1\(\\(\\)\)?', which has also been marked with an OpenMP 'declare target' directive" } */ +void f1 (void) {} +#pragma omp end declare target + +#pragma omp declare target +void f1 (void); + +#pragma acc routine seq /* { dg-error "cannot apply '#pragma acc routine' to '\(void \)?f1\(\\(\\)\)?', which has also been marked with an OpenMP 'declare target' directive" } */ +void f1 (void); + + + +#pragma omp declare target +#pragma acc routine /* { dg-error "cannot apply '#pragma acc routine' to '\(void \)?f2\(\\(\\)\)?', which has also been marked with an OpenMP 'declare target' directive" } */ +extern void f2 (void); +#pragma omp end declare target + +#pragma omp declare target +extern void f2 (void); +#pragma omp end declare target + +#pragma acc routine gang /* { dg-error "cannot apply '#pragma acc routine' to '\(void \)?f2\(\\(\\)\)?', which has also been marked with an OpenMP 'declare target' directive" } */ +extern void f2 (void); + + +#pragma omp declare target +#pragma acc routine gang /* { dg-error "cannot apply '#pragma acc routine' to '\(void \)?f3\(\\(\\)\)?', which has also been marked with an OpenMP 'declare target' directive" } */ +void f3 (void); +#pragma omp end declare target + +#pragma omp declare target +void f3 (void) {} +#pragma omp end declare target + +#pragma acc routine (f3) gang /* { dg-error "cannot apply '#pragma acc routine' to '\(void \)?f3\(\\(\\)\)?', which has also been marked with an OpenMP 'declare target' directive" } */ + + +/* Surprisingly, this diagnosis also works for '#pragma acc routine' first, + followed by '#pragma omp declare target'; the latter gets applied first. */ + + +#pragma acc routine /* { dg-error "cannot apply '#pragma acc routine' to '\(void \)?f4\(\\(\\)\)?', which has also been marked with an OpenMP 'declare target' directive" } */ +extern void f4 (void); + +#pragma omp declare target +extern void f4 (void); +#pragma omp end declare target + + +#pragma acc routine gang /* { dg-error "cannot apply '#pragma acc routine' to '\(void \)?f5\(\\(\\)\)?', which has also been marked with an OpenMP 'declare target' directive" } */ +void f5 (void) {} + +#pragma omp declare target +extern void f5 (void); +#pragma omp end declare target -- cgit v1.1 From ecc66362ee58e6b591245eaa3a1ce18f06a31e8c Mon Sep 17 00:00:00 2001 From: Fritz Reese Date: Fri, 10 Apr 2020 11:24:28 -0400 Subject: Fix UNRESOLVED testcase gfortran.dg/asynchronous_5.f03. gcc/testsuite/ChangeLog: 2020-04-10 Fritz Reese * gfortran.dg/asynchronous_5.f03: Add -fdump-tree-original and fix patterns for scan-tree-dump. --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gfortran.dg/asynchronous_5.f03 | 18 +++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 235d481..833c559 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-10 Fritz Reese + + * gfortran.dg/asynchronous_5.f03: Add -fdump-tree-original and fix + patterns for scan-tree-dump. + 2020-04-10 Thomas Schwinge PR middle-end/89433 diff --git a/gcc/testsuite/gfortran.dg/asynchronous_5.f03 b/gcc/testsuite/gfortran.dg/asynchronous_5.f03 index fcd281d..6a0ee24 100644 --- a/gcc/testsuite/gfortran.dg/asynchronous_5.f03 +++ b/gcc/testsuite/gfortran.dg/asynchronous_5.f03 @@ -1,5 +1,5 @@ ! { dg-do compile } -! { dg-options "-std=f2003" } +! { dg-options "-std=f2003 -fdump-tree-original" } ! ! Covers code introduced by the fix to PR fortran/87923. ! The idea is that the variables in a namelist or I/O list used for @@ -14,19 +14,17 @@ type t character(4) :: comp_async end type -character(2) :: ccvar_async type(t) :: dvar_async integer :: ivar_async real :: rvar_async logical :: lvar_async -type(t), dimension(2) :: darrvar_async integer :: ivar_noasync namelist /names/ ivar_async, rvar_async, lvar_async open(1, asynchronous="yes") write(1, asynchronous="yes") dvar_async, ccvar_async -write(1, asynchronous="yes") dvar_async%comp_async, darrvar_async +write(1, asynchronous="yes") dvar_async%comp_async read(1, asynchronous="yes", nml=names) open(2, asynchronous="no") @@ -34,10 +32,8 @@ read(2, asynchronous="no") ivar_noasync end -! { dg-final { scan-tree-dump-times "volatile.*?ccvar_async" 1 "original" } } -! { dg-final { scan-tree-dump-times "volatile.*?dvar_async" 1 "original" } } -! { dg-final { scan-tree-dump-times "volatile.*?ivar_async" 1 "original" } } -! { dg-final { scan-tree-dump-times "volatile.*?rvar_async" 1 "original" } } -! { dg-final { scan-tree-dump-times "volatile.*?lvar_async" 1 "original" } } -! { dg-final { scan-tree-dump-times "volatile.*?darrvar_async" 1 "original" } } -! { dg-final { scan-tree-dump-not "volatile.*?ivar_noasync" "original" } } +! { dg-final { scan-tree-dump "volatile +struct +\[^ \]+ +dvar_async" "original" } } +! { dg-final { scan-tree-dump "volatile +\[^ \]+ +ivar_async" "original" } } +! { dg-final { scan-tree-dump "volatile +\[^ \]+ +rvar_async" "original" } } +! { dg-final { scan-tree-dump "volatile +\[^ \]+ +lvar_async" "original" } } +! { dg-final { scan-tree-dump-not "volatile +\[^ \]+ +ivar_noasync" "original" } } -- cgit v1.1 From e26bd694c790b7c8f68c6736b2683c60a8fcbcfe Mon Sep 17 00:00:00 2001 From: Fritz Reese Date: Fri, 10 Apr 2020 11:28:45 -0400 Subject: Fix typo in gfortran.dg/asynchronous_5.f03 from last commit. 2020-04-10 Fritz Reese * gfortran.dg/asynchronous_5.f03: Fix typo in testcase and add IMPLICIT NONE. --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gfortran.dg/asynchronous_5.f03 | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 833c559..407bfef 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2020-04-10 Fritz Reese + * gfortran.dg/asynchronous_5.f03: Fix typo in testcase and add + IMPLICIT NONE. + +2020-04-10 Fritz Reese + * gfortran.dg/asynchronous_5.f03: Add -fdump-tree-original and fix patterns for scan-tree-dump. diff --git a/gcc/testsuite/gfortran.dg/asynchronous_5.f03 b/gcc/testsuite/gfortran.dg/asynchronous_5.f03 index 6a0ee24..88ed2c9 100644 --- a/gcc/testsuite/gfortran.dg/asynchronous_5.f03 +++ b/gcc/testsuite/gfortran.dg/asynchronous_5.f03 @@ -10,6 +10,8 @@ ! should obtain the "volatile" specifier in its declaration. ! +implicit none + type t character(4) :: comp_async end type @@ -23,7 +25,7 @@ integer :: ivar_noasync namelist /names/ ivar_async, rvar_async, lvar_async open(1, asynchronous="yes") -write(1, asynchronous="yes") dvar_async, ccvar_async +write(1, asynchronous="yes") dvar_async write(1, asynchronous="yes") dvar_async%comp_async read(1, asynchronous="yes", nml=names) -- cgit v1.1