From 11e811d8e2f63667f60f73731bb934273f5882b8 Mon Sep 17 00:00:00 2001 From: Julian Brown Date: Wed, 12 Oct 2022 20:44:57 +0000 Subject: OpenACC: Don't gang-privatize artificial variables [PR90115] This patch prevents compiler-generated artificial variables from being treated as privatization candidates for OpenACC. The rationale is that e.g. "gang-private" variables actually must be shared by each worker and vector spawned within a particular gang, but that sharing is not necessary for any compiler-generated variable (at least at present, but no such need is anticipated either). Variables on the stack (and machine registers) are already private per-"thread" (gang, worker and/or vector), and that's fine for artificial variables. We're restricting this to blocks, as we still need to understand what it means for a 'DECL_ARTIFICIAL' to appear in a 'private' clause. Several tests need their scan output patterns adjusted to compensate. 2022-10-14 Julian Brown PR middle-end/90115 gcc/ * omp-low.cc (oacc_privatization_candidate_p): Artificial vars are not privatization candidates. libgomp/ * testsuite/libgomp.oacc-fortran/declare-1.f90: Adjust scan output. * testsuite/libgomp.oacc-fortran/host_data-5.F90: Likewise. * testsuite/libgomp.oacc-fortran/if-1.f90: Likewise. * testsuite/libgomp.oacc-fortran/print-1.f90: Likewise. * testsuite/libgomp.oacc-fortran/privatized-ref-2.f90: Likewise. Co-authored-by: Thomas Schwinge --- gcc/omp-low.cc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'gcc') diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc index a880973..82a93d0 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -10710,6 +10710,28 @@ oacc_privatization_candidate_p (const location_t loc, const tree c, } } + /* If an artificial variable has been added to a bind, e.g. + a compiler-generated temporary structure used by the Fortran front-end, do + not consider it as a privatization candidate. Note that variables on + the stack are private per-thread by default: making them "gang-private" + for OpenACC actually means to share a single instance of a variable + amongst all workers and threads spawned within each gang. + At present, no compiler-generated artificial variables require such + sharing semantics, so this is safe. */ + + if (res && block && DECL_ARTIFICIAL (decl)) + { + res = false; + + if (dump_enabled_p ()) + { + oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl); + dump_printf (l_dump_flags, + "isn%'t candidate for adjusting OpenACC privatization " + "level: %s\n", "artificial"); + } + } + if (res) { if (dump_enabled_p ()) -- cgit v1.1 From 826df6d0cc706bf83cdb228b43f9b4890e8b2fbd Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 28 Oct 2022 10:31:02 +0200 Subject: Adjust gcc.dg/vect/pr100756.c for V8SI and V16SI The following adjusts the testcase to require no epilogue also for larger vectors than V4SI. * gcc.dg/vect/pr100756.c: Adjust for larger vectors. --- gcc/testsuite/gcc.dg/vect/pr100756.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/vect/pr100756.c b/gcc/testsuite/gcc.dg/vect/pr100756.c index c1362f2..7847f3e 100644 --- a/gcc/testsuite/gcc.dg/vect/pr100756.c +++ b/gcc/testsuite/gcc.dg/vect/pr100756.c @@ -7,7 +7,7 @@ foo (int * restrict a, int n) int i, result = 0; a = __builtin_assume_aligned (a, __BIGGEST_ALIGNMENT__); - for (i = 0; i < n * 4; i++) + for (i = 0; i < n * 16; i++) result += a[i]; return result; } -- cgit v1.1 From 89999f2358724fa4e71c7c3b4de340582c0e43da Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 28 Oct 2022 11:03:56 +0200 Subject: openmp: Allow optional comma after directive-specifier in C/C++ Previously we've been allowing that comma only in C++ when in attribute form (which was the reason why it has been allowed), but 5.1 allows that even in pragma form in C/C++ (with clarifications in 5.2) and 5.2 also in Fortran (which this patch doesn't implement). Note, for directives which take an argument (== unnamed clause), comma is not allowed in between the directive name and the argument, like the directive-1.c testcase shows. 2022-10-28 Jakub Jelinek gcc/c/ * c-parser.cc (c_parser_omp_all_clauses): Allow optional comma before the first clause. (c_parser_omp_allocate, c_parser_omp_atomic, c_parser_omp_depobj, c_parser_omp_flush, c_parser_omp_scan_loop_body, c_parser_omp_ordered, c_finish_omp_declare_variant, c_parser_omp_declare_target, c_parser_omp_declare_reduction, c_parser_omp_requires, c_parser_omp_error, c_parser_omp_assumption_clauses): Likewise. gcc/cp/ * parser.cc (cp_parser_omp_all_clauses): Allow optional comma before the first clause even in pragma syntax. (cp_parser_omp_allocate, cp_parser_omp_atomic, cp_parser_omp_depobj, cp_parser_omp_flush, cp_parser_omp_scan_loop_body, cp_parser_omp_ordered, cp_parser_omp_assumption_clauses, cp_finish_omp_declare_variant, cp_parser_omp_declare_target, cp_parser_omp_declare_reduction_exprs, cp_parser_omp_requires, cp_parser_omp_error): Likewise. gcc/testsuite/ * c-c++-common/gomp/directive-1.c: New test. * c-c++-common/gomp/clauses-6.c: New test. * c-c++-common/gomp/declare-variant-2.c (f75a): Declare. (f75): Use f75a as variant instead of f1 and don't expect error. * g++.dg/gomp/clause-4.C (foo): Don't expect error on comma before first clause. * gcc.dg/gomp/clause-2.c (foo): Likewise. --- gcc/c/c-parser.cc | 64 ++- gcc/cp/parser.cc | 73 +-- gcc/testsuite/c-c++-common/gomp/clauses-6.c | 604 +++++++++++++++++++++ .../c-c++-common/gomp/declare-variant-2.c | 3 +- gcc/testsuite/c-c++-common/gomp/directive-1.c | 28 + gcc/testsuite/g++.dg/gomp/clause-4.C | 2 +- gcc/testsuite/gcc.dg/gomp/clause-2.c | 2 +- 7 files changed, 687 insertions(+), 89 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/clauses-6.c create mode 100644 gcc/testsuite/c-c++-common/gomp/directive-1.c (limited to 'gcc') diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 5bdcd93..4d1dcb1 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -17460,7 +17460,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, if (nested && c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) break; - if (!first) + if (!first || nested != 2) { if (c_parser_next_token_is (parser, CPP_COMMA)) c_parser_consume_token (parser); @@ -18547,6 +18547,9 @@ c_parser_omp_allocate (location_t loc, c_parser *parser) { tree allocator = NULL_TREE; tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE); + if (c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME)) { matching_parens parens; @@ -18685,7 +18688,6 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc) bool structured_block = false; bool swapped = false; bool non_lvalue_p; - bool first = true; tree clauses = NULL_TREE; bool capture = false; bool compare = false; @@ -18696,13 +18698,10 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc) while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { - if (!first - && c_parser_next_token_is (parser, CPP_COMMA) + if (c_parser_next_token_is (parser, CPP_COMMA) && c_parser_peek_2nd_token (parser)->type == CPP_NAME) c_parser_consume_token (parser); - first = false; - if (c_parser_next_token_is (parser, CPP_NAME)) { const char *p @@ -19646,6 +19645,8 @@ c_parser_omp_depobj (c_parser *parser) parens.skip_until_found_close (parser); tree clause = NULL_TREE; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); location_t c_loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -19722,6 +19723,9 @@ c_parser_omp_flush (c_parser *parser) location_t loc = c_parser_peek_token (parser)->location; c_parser_consume_pragma (parser); enum memmodel mo = MEMMODEL_LAST; + if (c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME)) { const char *p @@ -19814,6 +19818,9 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed) c_parser_consume_pragma (parser); + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) { const char *p @@ -20597,9 +20604,14 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context, return false; } - if (c_parser_next_token_is (parser, CPP_NAME)) + int n = 1; + if (c_parser_next_token_is (parser, CPP_COMMA)) + n = 2; + + if (c_parser_peek_nth_token (parser, n)->type == CPP_NAME) { - const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + const char *p + = IDENTIFIER_POINTER (c_parser_peek_nth_token (parser, n)->value); if (!strcmp ("depend", p) || !strcmp ("doacross", p)) { @@ -22472,6 +22484,10 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) parens.require_close (parser); + if (c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); + const char *clause = ""; location_t match_loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_NAME)) @@ -22641,7 +22657,9 @@ c_parser_omp_declare_target (c_parser *parser) tree clauses = NULL_TREE; int device_type = 0; bool only_device_type = true; - if (c_parser_next_token_is (parser, CPP_NAME)) + if (c_parser_next_token_is (parser, CPP_NAME) + || (c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME)) clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK, "#pragma omp declare target"); else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) @@ -23062,10 +23080,14 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context) initializer.set_error (); if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) bad = true; - else if (c_parser_next_token_is (parser, CPP_NAME) - && strcmp (IDENTIFIER_POINTER + else if (c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); + if (!bad + && (c_parser_next_token_is (parser, CPP_NAME) + && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), - "initializer") == 0) + "initializer") == 0)) { c_parser_consume_token (parser); pop_scope (); @@ -23258,7 +23280,6 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context) static void c_parser_omp_requires (c_parser *parser) { - bool first = true; enum omp_requires new_req = (enum omp_requires) 0; c_parser_consume_pragma (parser); @@ -23266,13 +23287,10 @@ c_parser_omp_requires (c_parser *parser) location_t loc = c_parser_peek_token (parser)->location; while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { - if (!first - && c_parser_next_token_is (parser, CPP_COMMA) + if (c_parser_next_token_is (parser, CPP_COMMA) && c_parser_peek_2nd_token (parser)->type == CPP_NAME) c_parser_consume_token (parser); - first = false; - if (c_parser_next_token_is (parser, CPP_NAME)) { const char *p @@ -23543,7 +23561,6 @@ c_parser_omp_error (c_parser *parser, enum pragma_context context) int at_compilation = -1; int severity_fatal = -1; tree message = NULL_TREE; - bool first = true; bool bad = false; location_t loc = c_parser_peek_token (parser)->location; @@ -23551,13 +23568,10 @@ c_parser_omp_error (c_parser *parser, enum pragma_context context) while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { - if (!first - && c_parser_next_token_is (parser, CPP_COMMA) + if (c_parser_next_token_is (parser, CPP_COMMA) && c_parser_peek_2nd_token (parser)->type == CPP_NAME) c_parser_consume_token (parser); - first = false; - if (!c_parser_next_token_is (parser, CPP_NAME)) break; @@ -23713,7 +23727,6 @@ c_parser_omp_error (c_parser *parser, enum pragma_context context) static void c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume) { - bool first = true; bool no_openmp = false; bool no_openmp_routines = false; bool no_parallelism = false; @@ -23729,13 +23742,10 @@ c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume) while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { - if (!first - && c_parser_next_token_is (parser, CPP_COMMA) + if (c_parser_next_token_is (parser, CPP_COMMA) && c_parser_peek_2nd_token (parser)->type == CPP_NAME) c_parser_consume_token (parser); - first = false; - if (!c_parser_next_token_is (parser, CPP_NAME)) break; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index e685f19..9bdc609 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -40443,12 +40443,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, if (nested && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) break; - if (!first - /* OpenMP 5.1 allows optional comma in between directive-name and - clauses everywhere, but as we aren't done with OpenMP 5.0 - implementation yet, let's allow it for now only in C++11 - attributes. */ - || (parser->lexer->in_omp_attribute_pragma && nested != 2)) + if (!first || nested != 2) { if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); @@ -40881,9 +40876,7 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) location_t loc = pragma_tok->location; tree nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE); - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if (parser->lexer->in_omp_attribute_pragma - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); @@ -41004,7 +40997,6 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) enum tree_code code = ERROR_MARK, opcode = NOP_EXPR; enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED; bool structured_block = false; - bool first = true; tree clauses = NULL_TREE; bool capture = false; bool compare = false; @@ -41015,14 +41007,10 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if ((!first || parser->lexer->in_omp_attribute_pragma) - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); - first = false; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -41976,11 +41964,9 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) tree clause = NULL_TREE; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; - location_t c_loc = cp_lexer_peek_token (parser->lexer)->location; - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if (parser->lexer->in_omp_attribute_pragma - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); + location_t c_loc = cp_lexer_peek_token (parser->lexer)->location; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -42063,9 +42049,7 @@ static void cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) { enum memmodel mo = MEMMODEL_LAST; - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if (parser->lexer->in_omp_attribute_pragma - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -42790,8 +42774,7 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) cp_lexer_consume_token (parser->lexer); - if (parser->lexer->in_omp_attribute_pragma - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -43593,9 +43576,7 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, location_t loc = pragma_tok->location; int n = 1; - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if (parser->lexer->in_omp_attribute_pragma - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) n = 2; if (cp_lexer_nth_token_is (parser->lexer, n, CPP_NAME)) @@ -45949,7 +45930,6 @@ static void cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, bool is_assume) { - bool first = true; bool no_openmp = false; bool no_openmp_routines = false; bool no_parallelism = false; @@ -45965,14 +45945,10 @@ cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if ((!first || parser->lexer->in_omp_attribute_pragma) - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); - first = false; - if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)) break; @@ -46209,9 +46185,7 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, location_t finish_loc = get_finish (varid.get_location ()); location_t varid_loc = make_location (caret_loc, start_loc, finish_loc); - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if (parser->lexer->in_omp_attribute_pragma - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); @@ -46287,11 +46261,6 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs) cp_lexer_consume_token (parser->lexer); if (strcmp (kind, "simd") == 0) { - /* For now only in C++ attributes, do it always for OpenMP 5.1. - if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) - && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) - cp_lexer_consume_token (parser->lexer); */ - cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, "#pragma omp declare simd", pragma_tok); @@ -46549,9 +46518,7 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) int device_type = 0; bool only_device_type = true; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - || (parser->lexer->in_omp_attribute_pragma - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + || (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))) clauses = cp_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK, @@ -46801,9 +46768,7 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser) if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) return false; - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if (parser->lexer->in_omp_attribute_pragma - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); @@ -47235,20 +47200,15 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok, static bool cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) { - bool first = true; enum omp_requires new_req = (enum omp_requires) 0; location_t loc = pragma_tok->location; while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if ((!first || parser->lexer->in_omp_attribute_pragma) - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); - first = false; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -47402,20 +47362,15 @@ cp_parser_omp_error (cp_parser *parser, cp_token *pragma_tok, int at_compilation = -1; int severity_fatal = -1; tree message = NULL_TREE; - bool first = true; bool bad = false; location_t loc = pragma_tok->location; while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - /* For now only in C++ attributes, do it always for OpenMP 5.1. */ - if ((!first || parser->lexer->in_omp_attribute_pragma) - && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); - first = false; - if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) break; diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-6.c b/gcc/testsuite/c-c++-common/gomp/clauses-6.c new file mode 100644 index 0000000..3502647 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/clauses-6.c @@ -0,0 +1,604 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99" { target c } } */ + +typedef enum omp_allocator_handle_t +#if __cplusplus >= 201103L +: __UINTPTR_TYPE__ +#endif +{ + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + __omp_allocator_handle_t_max__ = __UINTPTR_MAX__ +} omp_allocator_handle_t; + +typedef enum omp_sync_hint_t { +omp_sync_hint_none = 0x0, +omp_lock_hint_none = omp_sync_hint_none, +omp_sync_hint_uncontended = 0x1, +omp_lock_hint_uncontended = omp_sync_hint_uncontended, +omp_sync_hint_contended = 0x2, +omp_lock_hint_contended = omp_sync_hint_contended, +omp_sync_hint_nonspeculative = 0x4, +omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative, +omp_sync_hint_speculative = 0x8, +omp_lock_hint_speculative = omp_sync_hint_speculative +} omp_sync_hint_t; + +typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t { + char __omp_depend_t__[2 * sizeof (void *)]; +} omp_depend_t; + +int t; +#pragma omp threadprivate (t) + +#pragma omp declare target +int f, l, ll, r, r2; + +void +foo (int d, int m, int i1, int i2, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int ntm) +{ + #pragma omp distribute parallel for, \ + private (p), firstprivate (f), collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), order(concurrent), allocate (omp_default_mem_alloc:f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp distribute parallel for simd, \ + private (p), firstprivate (f), collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), if(simd: i1), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), nontemporal(ntm), \ + safelen(8), simdlen(4), aligned(q: 32), order(concurrent), allocate (omp_default_mem_alloc:f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp distribute simd, \ + private (p), firstprivate (f), collapse(1), dist_schedule(static, 16), \ + safelen(8), simdlen(4), aligned(q: 32), reduction(+:r), if(i1), nontemporal(ntm), \ + order(concurrent), allocate (omp_default_mem_alloc:f) + for (int i = 0; i < 64; i++) + ll++; +} + +void +qux (int p) +{ + #pragma omp loop, bind(teams), order(concurrent), \ + private (p), lastprivate (l), collapse(1), reduction(+:r) + for (l = 0; l < 64; ++l) + ll++; +} +#pragma omp end declare target + +void +baz (int d, int m, int i1, int i2, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int ntm) +{ + #pragma omp distribute parallel for, \ + private (p), firstprivate (f), collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), copyin(t), allocate (p) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp distribute parallel for, \ + private (p), firstprivate (f), collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), order(concurrent), allocate (p) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp distribute parallel for simd, \ + private (p), firstprivate (f), collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), if(simd: i1), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), nontemporal(ntm), \ + safelen(8), simdlen(4), aligned(q: 32), copyin(t), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp distribute parallel for simd, \ + private (p), firstprivate (f), collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), if(simd: i1), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), nontemporal(ntm), \ + safelen(8), simdlen(4), aligned(q: 32), order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp distribute simd, \ + private (p), firstprivate (f), collapse(1), dist_schedule(static, 16), \ + safelen(8), simdlen(4), aligned(q: 32), reduction(+:r), if(i1), nontemporal(ntm), \ + order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp loop, bind(parallel), order(concurrent), \ + private (p), lastprivate (l), collapse(1), reduction(+:r) + for (l = 0; l < 64; ++l) + ll++; +} + +void +bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm, + int n1, int n2) +{ + #pragma omp for simd, \ + private (p), firstprivate (f), lastprivate (l), linear (ll:1), reduction(+:r), schedule(static, 4), collapse(1), nowait, \ + safelen(8), simdlen(4), aligned(q: 32), nontemporal(ntm), if(i1), order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel for, \ + private (p), firstprivate (f), if (parallel: i2), default(shared), shared(s), copyin(t), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), linear (ll:1), ordered, schedule(static, 4), collapse(1), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel for, \ + private (p), firstprivate (f), if (parallel: i2), default(shared), shared(s), copyin(t), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), linear (ll:1), schedule(static, 4), collapse(1), order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel for simd, \ + private (p), firstprivate (f), if (i2), default(shared), shared(s), copyin(t), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), linear (ll:1), schedule(static, 4), collapse(1), \ + safelen(8), simdlen(4), aligned(q: 32), nontemporal(ntm), order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel sections, \ + private (p), firstprivate (f), if (parallel: i2), default(shared), shared(s), copyin(t), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), allocate (f) + { + #pragma omp section + {} + #pragma omp section + {} + } + #pragma omp target parallel, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + nowait, depend(inout: dd[0]), allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + ; + #pragma omp target parallel for, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), linear (ll:1), ordered, schedule(static, 4), collapse(1), nowait, depend(inout: dd[0]), \ + allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target parallel for, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), linear (ll:1), schedule(static, 4), collapse(1), nowait, depend(inout: dd[0]), order(concurrent), \ + allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target parallel for simd, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), linear (ll:1), schedule(static, 4), collapse(1), \ + safelen(8), simdlen(4), aligned(q: 32), nowait, depend(inout: dd[0]), nontemporal(ntm), if (simd: i3), order(concurrent), \ + allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target teams, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + shared(s), default(shared), reduction(+:r), num_teams(nte - 1:nte), thread_limit(tl), nowait depend(inout: dd[0]), \ + allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + ; + #pragma omp target teams distribute, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), order(concurrent), \ + collapse(1), dist_schedule(static, 16), nowait, depend(inout: dd[0]), allocate (omp_default_mem_alloc:f), in_reduction(+:r2), \ + has_device_addr(hda) + for (int i = 0; i < 64; i++) + ; + #pragma omp target teams distribute parallel for, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + shared(s), default(shared), reduction(+:r), num_teams(nte-1:nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), nowait, depend(inout: dd[0]), order(concurrent), \ + allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target teams distribute parallel for simd, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), order(concurrent), \ + safelen(8), simdlen(4), aligned(q: 32), nowait, depend(inout: dd[0]), nontemporal(ntm), if (simd: i3), \ + allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target teams distribute simd, \ + device(d), map (tofrom: m), if (i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + shared(s), default(shared), reduction(+:r), num_teams(nte-1:nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), order(concurrent), \ + safelen(8), simdlen(4), aligned(q: 32), nowait depend(inout: dd[0]), nontemporal(ntm), \ + allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target simd, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + safelen(8), simdlen(4), lastprivate (l), linear(ll: 1), aligned(q: 32), reduction(+:r), \ + nowait depend(inout: dd[0]), nontemporal(ntm), if(simd:i3), order(concurrent), \ + allocate (omp_default_mem_alloc:f), in_reduction(+:r2), has_device_addr(hda) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction(+:r2), allocate (r2) + #pragma omp taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), if(simd: i2), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), in_reduction(+:r2), nontemporal(ntm), \ + order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction(+:r), allocate (r) + #pragma omp taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(i1), final(fi), mergeable, nogroup, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), in_reduction(+:r), nontemporal(ntm), \ + order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskwait + #pragma omp taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), if(taskloop: i1), final(fi), priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(+:r), if (simd: i3), nontemporal(ntm), \ + order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target, nowait, depend(inout: dd[0]), in_reduction(+:r2) + #pragma omp teams distribute, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), allocate (omp_default_mem_alloc: f), order(concurrent) + for (int i = 0; i < 64; i++) + ; + #pragma omp target + #pragma omp teams distribute parallel for, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte-1:nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), order(concurrent), allocate (omp_default_mem_alloc: f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target + #pragma omp teams distribute parallel for simd, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), order(concurrent), \ + safelen(8), simdlen(4), aligned(q: 32), if (simd: i3), nontemporal(ntm), \ + allocate (omp_default_mem_alloc: f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp target + #pragma omp teams distribute simd, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte-1:nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), order(concurrent), \ + safelen(8), simdlen(4), aligned(q: 32), if(i3), nontemporal(ntm), \ + allocate (omp_default_mem_alloc: f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp teams distribute parallel for, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), copyin(t), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp teams distribute parallel for, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte-1:nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), order(concurrent), \ + if (parallel: i2), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp teams distribute parallel for simd, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), \ + safelen(8), simdlen(4), aligned(q: 32), if (simd: i3), nontemporal(ntm), copyin(t), \ + allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp teams distribute parallel for simd, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte-1:nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), \ + if (parallel: i2), num_threads (nth), proc_bind(spread), \ + lastprivate (l), schedule(static, 4), order(concurrent), \ + safelen(8), simdlen(4), aligned(q: 32), if (simd: i3), nontemporal(ntm), \ + allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp teams distribute simd, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), \ + collapse(1), dist_schedule(static, 16), order(concurrent), \ + safelen(8), simdlen(4), aligned(q: 32), if(i3), nontemporal(ntm), allocate(f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master, \ + private (p), firstprivate (f), if (parallel: i2), default(shared), shared(s), reduction(+:r), \ + num_threads (nth), proc_bind(spread), copyin(t), allocate (f) + ; + #pragma omp parallel masked, \ + private (p), firstprivate (f), if (parallel: i2), default(shared), shared(s), reduction(+:r), \ + num_threads (nth), proc_bind(spread), copyin(t), allocate (f), filter (d) + ; + #pragma omp taskgroup, task_reduction (+:r2), allocate (r2) + #pragma omp master taskloop, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), final(fi), mergeable, priority (pp), \ + reduction(default, +:r), in_reduction(+:r2), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction (+:r2), allocate (r2) + #pragma omp masked taskloop, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), final(fi), mergeable, priority (pp), \ + reduction(default, +:r), in_reduction(+:r2), allocate (f), filter (d) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction (+:r2), allocate (r2) + #pragma omp master taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), if(simd: i2), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), in_reduction(+:r2), nontemporal(ntm), \ + order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction (+:r2), allocate (r2) + #pragma omp masked taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), if(simd: i2), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), in_reduction(+:r2), nontemporal(ntm), \ + order(concurrent), allocate (f), filter (d) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master taskloop, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), final(fi), mergeable, priority (pp), \ + reduction(default, +:r), if (parallel: i2), num_threads (nth), proc_bind(spread), copyin(t), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel masked taskloop, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), final(fi), mergeable, priority (pp), \ + reduction(default, +:r), if (parallel: i2), num_threads (nth), proc_bind(spread), copyin(t), allocate (f), filter (d) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), if(simd: i2), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), nontemporal(ntm), if (parallel: i2), num_threads (nth), proc_bind(spread), copyin(t), \ + order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel masked taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), grainsize (g), collapse(1), untied, if(taskloop: i1), if(simd: i2), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), nontemporal(ntm), if (parallel: i2), num_threads (nth), proc_bind(spread), copyin(t), \ + order(concurrent), allocate (f), filter (d) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction (+:r2), allocate (r2) + #pragma omp master taskloop, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), untied, if(i1), final(fi), mergeable, priority (pp), \ + reduction(default, +:r), in_reduction(+:r2) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction (+:r2), allocate (r2) + #pragma omp mastked taskloop, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), untied, if(i1), final(fi), mergeable, priority (pp), \ + reduction(default, +:r), in_reduction(+:r2), filter (d) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction (+:r2), allocate (r2) + #pragma omp master taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), untied, if(i1), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), in_reduction(+:r2), nontemporal(ntm), \ + order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup, task_reduction (+:r2), allocate (r2) + #pragma omp masked taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), untied, if(i1), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), in_reduction(+:r2), nontemporal(ntm), \ + order(concurrent), allocate (f), filter (d) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master taskloop, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), untied, if(i1), final(fi), mergeable, priority (pp), \ + reduction(default, +:r), num_threads (nth), proc_bind(spread), copyin(t), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel masked taskloop, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), untied, if(i1), final(fi), mergeable, priority (pp), \ + reduction(default, +:r), num_threads (nth), proc_bind(spread), copyin(t), allocate (f), filter (d) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), untied, if(i1), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), nontemporal(ntm), num_threads (nth), proc_bind(spread), copyin(t), \ + order(concurrent), allocate (f) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel masked taskloop simd, \ + private (p), firstprivate (f), lastprivate (l), shared (s), default(shared), num_tasks (nta), collapse(1), untied, if(i1), final(fi), mergeable, priority (pp), \ + safelen(8), simdlen(4), linear(ll: 1), aligned(q: 32), reduction(default, +:r), nontemporal(ntm), num_threads (nth), proc_bind(spread), copyin(t), \ + order(concurrent), allocate (f), filter (d) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp loop, bind(thread), order(concurrent), \ + private (p), lastprivate (l), collapse(1), reduction(+:r) + for (l = 0; l < 64; ++l) + ll++; + #pragma omp parallel loop, \ + private (p), firstprivate (f), if (parallel: i2), default(shared), shared(s), copyin(t), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), collapse(1), bind(parallel), order(concurrent), allocate (f) + for (l = 0; l < 64; l++) + ll++; + #pragma omp parallel loop, \ + private (p), firstprivate (f), if (parallel: i2), default(shared), shared(s), copyin(t), reduction(+:r), num_threads (nth), proc_bind(spread), \ + lastprivate (l), collapse(1), allocate (f) + for (l = 0; l < 64; l++) + ll++; + #pragma omp teams loop, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte-1:nte), thread_limit(tl), \ + collapse(1), lastprivate (l), bind(teams), allocate (f) + for (l = 0; l < 64; ++l) + ; + #pragma omp teams loop, \ + private(p), firstprivate (f), shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), \ + collapse(1), lastprivate (l), order(concurrent), allocate (f) + for (l = 0; l < 64; ++l) + ; + #pragma omp target parallel loop, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + nowait depend(inout: dd[0]), lastprivate (l), bind(parallel), order(concurrent), collapse(1), \ + allocate (omp_default_mem_alloc: f), in_reduction(+:r2), has_device_addr(hda) + for (l = 0; l < 64; ++l) + ; + #pragma omp target parallel loop, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + if (parallel: i2), default(shared), shared(s), reduction(+:r), num_threads (nth), proc_bind(spread), \ + nowait depend(inout: dd[0]), lastprivate (l), order(concurrent), collapse(1), \ + allocate (omp_default_mem_alloc: f), in_reduction(+:r2), has_device_addr(hda) + for (l = 0; l < 64; ++l) + ; + #pragma omp target teams loop, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + shared(s), default(shared), reduction(+:r), num_teams(nte-1:nte), thread_limit(tl), nowait depend(inout: dd[0]), \ + lastprivate (l), bind(teams), collapse(1), \ + allocate (omp_default_mem_alloc: f), in_reduction(+:r2), has_device_addr(hda) + for (l = 0; l < 64; ++l) + ; + #pragma omp target teams loop, \ + device(d), map (tofrom: m), if (target: i1), private (p), firstprivate (f), defaultmap(tofrom: scalar), is_device_ptr (idp), \ + shared(s), default(shared), reduction(+:r), num_teams(nte), thread_limit(tl), nowait depend(inout: dd[0]), \ + lastprivate (l), order(concurrent), collapse(1), \ + allocate (omp_default_mem_alloc: f), in_reduction(+:r2), has_device_addr(hda) + for (l = 0; l < 64; ++l) + ; + #pragma omp critical + ; + #pragma omp critical (foobar),hint(omp_sync_hint_none) + ; + #pragma omp taskwait, depend (inout: dd[0]) + ; + #pragma omp taskgroup, task_reduction(+:r2),allocate (r2) + ; + #pragma omp atomic, update,seq_cst,hint(omp_sync_hint_none) + p++; + #pragma omp atomic, read, hint(omp_sync_hint_none),relaxed + f = p; + #pragma omp atomic,write, release hint(omp_sync_hint_none) + p = f; + #pragma omp flush + ; + #pragma omp flush, acq_rel + ; + #pragma omp flush, acquire + ; + #pragma omp flush, release + ; + #pragma omp flush, seq_cst + ; + #pragma omp flush (p, f) + ; + #pragma omp simd, \ + private (p),lastprivate (l),linear (ll:1),reduction(+:r),collapse(1),safelen(8),simdlen(4),aligned(q: 32), \ + nontemporal(ntm),if(i1) + for (int i = 0; i < 64; i++) + #pragma omp ordered, simd + ll++; + #pragma omp for, \ + private (p),firstprivate (f),lastprivate (l),linear (ll:1),reduction(+:r),schedule(static, 4),collapse(1),nowait, \ + ordered, allocate (f) + for (int i = 0; i < 64; i++) + #pragma omp ordered, threads + ll++; + #pragma omp for, ordered (1) + for (l = 0; l < 64; l++) + { + #pragma omp ordered, depend (sink: l - 1) + ; + #pragma omp ordered, depend (source) + ; + } + extern omp_depend_t depobj; + #pragma omp depobj(depobj),depend(in : dd[0]) + ; + #pragma omp parallel + { + if (p) { + #pragma omp cancel, parallel + ; + } else { + #pragma omp cancellation point, parallel + ; + } + } + #pragma omp scope, private (p), firstprivate (f), reduction(+:r), nowait, \ + allocate(omp_default_mem_alloc: r) + ; + #pragma omp scope, private (p), firstprivate (f), reduction(task, +:r), \ + allocate (omp_default_mem_alloc: f) + ; + extern int t2; + #pragma omp threadprivate (t2) + extern int t2; + #pragma omp declare reduction (dr: int: omp_out += omp_in),initializer (omp_priv = 0) + #pragma omp assume, no_openmp, no_openmp_routines, no_parallelism, \ + absent (atomic, barrier, cancel, cancellation point), \ + absent (critical, depobj), \ + absent (distribute, flush, loop, masked, master, nothing, ordered), \ + absent (parallel, scan, scope, section, sections, simd, single, task), \ + absent (taskgroup, taskloop, taskwait, taskyield), \ + absent (target, teams, for, error), holds (n1 < n2) + if (0) + ; + #pragma omp assume, contains (simd) + #pragma omp for simd + for (int i = 0; i < 64; i++) + ; +} + +void corge1 (); + +void +corge () +{ + #pragma omp declare variant (corge1),match (construct={parallel,for}) + extern void corge2 (); + #pragma omp parallel + #pragma omp for + for (int i = 0; i < 5; i++) + corge2 (); + #pragma omp declare simd, simdlen(4),linear(l),aligned(p:4),uniform(p),inbranch + #pragma omp declare simd,simdlen(8),notinbranch + extern int corge3 (int l, int *p); + #pragma omp declare simd, simdlen(4),linear(l),aligned(p:4),uniform(p),inbranch + #pragma omp declare simd, simdlen(8),notinbranch + extern int corge4 (int l, int *p); + #pragma omp declare simd, simdlen(4),linear(l),aligned(p:4),uniform(p),inbranch + #pragma omp declare simd, simdlen(8),notinbranch + extern int corge5 (int l, int *p); + #pragma omp declare target + extern void corge6 (); + #pragma omp end declare target +} + +int +garply (int a, int *c, int *d, int *e, int *f) +{ + int i; + #pragma omp simd, reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan, exclusive (a) + a += c[i]; + } + #pragma omp simd, reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) + d[i] = a; + } + return a; +} diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c index 5554059..3c2c12c 100644 --- a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c @@ -149,7 +149,8 @@ void f72 (void); void f73 (void); #pragma omp declare variant (f1) match(construct={requires}) /* { dg-error "selector 'requires' not allowed for context selector set 'construct'" } */ void f74 (void); -#pragma omp declare variant (f1),match(construct={parallel}) /* { dg-error "expected 'match' before ','" } */ +void f75a (void); +#pragma omp declare variant (f75a),match(construct={parallel}) void f75 (void); #pragma omp declare variant (f1) match(implementation={atomic_default_mem_order("relaxed")}) /* { dg-error "expected identifier before string constant" } */ void f76 (void); diff --git a/gcc/testsuite/c-c++-common/gomp/directive-1.c b/gcc/testsuite/c-c++-common/gomp/directive-1.c new file mode 100644 index 0000000..e1218bd --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/directive-1.c @@ -0,0 +1,28 @@ +int thr; +#pragma omp threadprivate, (thr) /* { dg-error "expected '\\\(' before ',' token" } */ + /* { dg-error "expected end of line before ',' token" "" { target c++ } .-1 } */ +#pragma omp declare reduction, (foo: int : omp_out += omp_in), initializer (omp_priv = 0) /* { dg-error "expected '\\\(' before ',' token" } */ +void f1 (void); +#pragma omp declare variant, (f1), match (user={condition(true)}) /* { dg-error "expected '\\\(' before ',' token" } */ +void f2 (void); +int j; +#pragma omp declare target, (j) /* { dg-error "expected end of line before ',' token" } */ + +typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t { + char __omp_depend_t__[2 * sizeof (void *)]; +} omp_depend_t; +extern omp_depend_t d; + +void +foo (void) +{ + int i, k = 0, l = 0; + #pragma omp allocate, (i) /* { dg-error "expected '\\\(' before ',' token" } */ + /* { dg-error "expected end of line before ',' token" "" { target c++ } .-1 } */ + /* { dg-message "not yet supported" "" { target *-*-* } .-2 } */ + #pragma omp critical, (bar) /* { dg-error "expected '#pragma omp' clause before '\\\(' token" } */ + ; + #pragma omp flush, (k, l) /* { dg-error "expected '\\\(' or end of line before ',' token" "" { target c } } */ + /* { dg-error "expected end of line before ',' token" "" { target c++ } .-1 } */ + #pragma omp depobj, (d) depend(in : l) /* { dg-error "expected '\\\(' before ',' token" } */ +} diff --git a/gcc/testsuite/g++.dg/gomp/clause-4.C b/gcc/testsuite/g++.dg/gomp/clause-4.C index 06b91e8..db191e2 100644 --- a/gcc/testsuite/g++.dg/gomp/clause-4.C +++ b/gcc/testsuite/g++.dg/gomp/clause-4.C @@ -14,7 +14,7 @@ foo (int x) ; #pragma omp p num_threads(4),if(1),private(x) ; -#pragma omp p, num_threads (4), if (1), private (x) // { dg-error "clause before" } +#pragma omp p, num_threads (4), if (1), private (x) ; #pragma omp p num_threads (4), if (1), private (x), // { dg-error "clause before" } ; diff --git a/gcc/testsuite/gcc.dg/gomp/clause-2.c b/gcc/testsuite/gcc.dg/gomp/clause-2.c index 4b12fc8..4d37c41 100644 --- a/gcc/testsuite/gcc.dg/gomp/clause-2.c +++ b/gcc/testsuite/gcc.dg/gomp/clause-2.c @@ -14,7 +14,7 @@ foo (int x) ; #pragma omp p num_threads(4),if(1),private(x) ; -#pragma omp p, num_threads (4), if (1), private (x) /* { dg-error "clause before" } */ +#pragma omp p, num_threads (4), if (1), private (x) ; #pragma omp p num_threads (4), if (1), private (x), /* { dg-error "clause before" } */ ; -- cgit v1.1 From 084128583212bd64308f50c2ab5f4c03be40e48c Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 28 Oct 2022 13:50:57 +0200 Subject: tree-optimization/107435 - ICE with recurrence vectorization This implements the missed conversion from pointer to integer. PR tree-optimization/107435 * tree-vect-loop.cc (vectorizable_recurr): Convert initial value to vector component type. * gcc.dg/torture/pr107435.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr107435.c | 23 +++++++++++++++++++++++ gcc/tree-vect-loop.cc | 6 ++++++ 2 files changed, 29 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/torture/pr107435.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/torture/pr107435.c b/gcc/testsuite/gcc.dg/torture/pr107435.c new file mode 100644 index 0000000..1012896 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr107435.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-mavx2" { target x86_64-*-* i?86-*-* } } */ + +struct qlist_head { + struct qlist_head *next; +}; +void +qlist_add (struct qlist_head *new, struct qlist_head *head) +{ + struct qlist_head *prev = head; + new->next = head->next; + prev->next = new; +} +struct { + struct qlist_head queue_link; +} free_list, prealloc[64]; +void +dbpf_open_cache_initialize() +{ + int i = 0; + for (; i < 64; i++) + qlist_add(&prealloc[i].queue_link, &free_list.queue_link); +} diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index d5c2bff..aacbb12 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -8469,6 +8469,12 @@ vectorizable_recurr (loop_vec_info loop_vinfo, stmt_vec_info stmt_info, edge pe = loop_preheader_edge (LOOP_VINFO_LOOP (loop_vinfo)); basic_block bb = gimple_bb (phi); tree preheader = PHI_ARG_DEF_FROM_EDGE (phi, pe); + if (!useless_type_conversion_p (TREE_TYPE (vectype), TREE_TYPE (preheader))) + { + gimple_seq stmts = NULL; + preheader = gimple_convert (&stmts, TREE_TYPE (vectype), preheader); + gsi_insert_seq_on_edge_immediate (pe, stmts); + } tree vec_init = build_vector_from_val (vectype, preheader); vec_init = vect_init_vector (loop_vinfo, stmt_info, vec_init, vectype, NULL); -- cgit v1.1 From 1add3635563b39e3c0e9bed4930d11b3f605fdd3 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 28 Oct 2022 14:20:36 +0200 Subject: tree-optimization/107447 - avoid hoisting returns-twice calls in LIM The following makes sure to not hoist returns-twice calls in LIM since we have no way to move the abnormal edge associated with it and we are prone having stray abnormal edges in the IL which will then cause IL verification failures even when the actual call does not return twice. PR tree-optimization/107447 * tree-ssa-loop-im.cc (determine_max_movement): Do not hoist returns-twice calls. * gcc.dg/torture/pr107447.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr107447.c | 23 +++++++++++++++++++++++ gcc/tree-ssa-loop-im.cc | 13 +++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr107447.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/torture/pr107447.c b/gcc/testsuite/gcc.dg/torture/pr107447.c new file mode 100644 index 0000000..06f7b7b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr107447.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ + +int n; + +void +bar (int, int); + +__attribute__ ((noinline, returns_twice)) int +zero (void) +{ + return 0; +} + +void +foo (void) +{ + (void) zero (); + + n = 0; + + for (;;) + bar (zero (), n); +} diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc index 2ea8150..2119d40 100644 --- a/gcc/tree-ssa-loop-im.cc +++ b/gcc/tree-ssa-loop-im.cc @@ -835,10 +835,15 @@ determine_max_movement (gimple *stmt, bool must_preserve_exec) return true; } - else - FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_USE) - if (!add_dependency (val, lim_data, loop, true)) - return false; + + /* A stmt that receives abnormal edges cannot be hoisted. */ + if (is_a (stmt) + && (gimple_call_flags (stmt) & ECF_RETURNS_TWICE)) + return false; + + FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_USE) + if (!add_dependency (val, lim_data, loop, true)) + return false; if (gimple_vuse (stmt)) { -- cgit v1.1 From 031a400e49d8db156c43f9ec0b21ab0c2aee8c6d Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 28 Oct 2022 15:03:49 +0200 Subject: tree-optimization/107407 - wrong code with DSE So what happens is that we elide processing of this check with /* In addition to kills we can remove defs whose only use is another def in defs. That can only ever be PHIs of which we track two for simplicity reasons, the first and last in {first,last}_phi_def (we fail for multiple PHIs anyways). We can also ignore defs that feed only into already visited PHIs. */ else if (single_imm_use (vdef, &use_p, &use_stmt) && (use_stmt == first_phi_def || use_stmt == last_phi_def || (gimple_code (use_stmt) == GIMPLE_PHI && bitmap_bit_p (visited, SSA_NAME_VERSION (PHI_RESULT (use_stmt)))))) where we have the last PHI being the outer loop virtual PHI and the first PHI being the loop exit PHI of the outer loop and we've already processed the single immediate use of the outer loop PHI, the inner loop PHI. But we still have to perform the above check! It's easiest to perform the check when we visit the PHI node instead of delaying it to the actual processing loop. PR tree-optimization/107407 * tree-ssa-dse.cc (dse_classify_store): Perform backedge varying index check when collecting PHI uses rather than after optimizing processing of the candidate defs. * gcc.dg/torture/pr107407.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr107407.c | 26 ++++++++++++++++++++++++++ gcc/tree-ssa-dse.cc | 17 +++++++++-------- 2 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr107407.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/torture/pr107407.c b/gcc/testsuite/gcc.dg/torture/pr107407.c new file mode 100644 index 0000000..228fce1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr107407.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ + +int *a; +int c[4]; +int d; + +static int +f(char k, int j) +{ + for (; k <= 3; k++) + { + a = &c[k]; + for (; d <= 1; d++) + *a = 3; + } + *a = 0; +} + +int main() +{ + int i; + f(0, 0); + if (c[0] != 3) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc index c14e5e4..82976bd 100644 --- a/gcc/tree-ssa-dse.cc +++ b/gcc/tree-ssa-dse.cc @@ -978,14 +978,6 @@ dse_classify_store (ao_ref *ref, gimple *stmt, if (gimple_code (temp) == GIMPLE_PHI) { - /* If we visit this PHI by following a backedge then we have to - make sure ref->ref only refers to SSA names that are invariant - with respect to the loop represented by this PHI node. */ - if (dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), - gimple_bb (temp)) - && !for_each_index (ref->ref ? &ref->ref : &ref->base, - check_name, gimple_bb (temp))) - return DSE_STORE_LIVE; defvar = PHI_RESULT (temp); bitmap_set_bit (visited, SSA_NAME_VERSION (defvar)); } @@ -1019,6 +1011,15 @@ dse_classify_store (ao_ref *ref, gimple *stmt, if (!bitmap_bit_p (visited, SSA_NAME_VERSION (PHI_RESULT (use_stmt)))) { + /* If we visit this PHI by following a backedge then we have + to make sure ref->ref only refers to SSA names that are + invariant with respect to the loop represented by this + PHI node. */ + if (dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), + gimple_bb (use_stmt)) + && !for_each_index (ref->ref ? &ref->ref : &ref->base, + check_name, gimple_bb (use_stmt))) + return DSE_STORE_LIVE; defs.safe_push (use_stmt); if (!first_phi_def) first_phi_def = as_a (use_stmt); -- cgit v1.1 From 95decac3ce8c8c7c5302cd6fac005a10463de165 Mon Sep 17 00:00:00 2001 From: Andre Vieira Date: Fri, 28 Oct 2022 15:05:11 +0100 Subject: vect: Reject non-byte offsets for gather/scatters [PR107346] The ada failure reported in the PR was being caused by vect_check_gather_scatter failing to deal with bit offsets that weren't multiples of BITS_PER_UNIT. This patch makes vect_check_gather_scatter reject memory accesses with such offsets. gcc/ChangeLog: PR tree-optimization/107346 * tree-vect-data-refs.cc (vect_check_gather_scatter): Reject offsets that aren't multiples of BITS_PER_UNIT. --- gcc/tree-vect-data-refs.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc index 4a23d61..6c89279 100644 --- a/gcc/tree-vect-data-refs.cc +++ b/gcc/tree-vect-data-refs.cc @@ -4016,6 +4016,11 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, if (reversep) return false; + /* PR 107346. Packed structs can have fields at offsets that are not + multiples of BITS_PER_UNIT. Do not use gather/scatters in such cases. */ + if (!multiple_p (pbitpos, BITS_PER_UNIT)) + return false; + poly_int64 pbytepos = exact_div (pbitpos, BITS_PER_UNIT); if (TREE_CODE (base) == MEM_REF) -- cgit v1.1 From 4fe34cdcc80ac225b80670eabc38ac5e31ce8a5a Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Fri, 28 Oct 2022 14:40:25 +0000 Subject: c: tree: target: C2x (...) function prototypes and va_start relaxation C2x allows function prototypes to be given as (...), a prototype meaning a variable-argument function with no named arguments. To allow such functions to access their arguments, requirements for va_start calls are relaxed so it ignores all but its first argument (i.e. subsequent arguments, if any, can be arbitrary pp-token sequences). Implement this feature accordingly. The va_start relaxation in is itself easy: __builtin_va_start already supports a second argument of 0 instead of a parameter name, and calls get converted internally to the form using 0 for that argument, so just needs changing to use a variadic macro that passes 0 as the second argument of __builtin_va_start. (This is done only in C2x mode, on the expectation that users of older standard would expect unsupported uses of va_start to be diagnosed.) For the (...) functions, it's necessary to distinguish these from unprototyped functions, whereas previously C++ (...) functions and unprototyped functions both used NULL TYPE_ARG_TYPES. A flag is added to tree_type_common to mark the (...) functions; as discussed on gcc@, doing things this way is likely to be safer for unchanged code in GCC than adding a different form of representation in TYPE_ARG_TYPES, or adding a flag that instead signals that the function is unprototyped. There was previously an option -fallow-parameterless-variadic-functions to enable support for (...) prototypes. The support was incomplete - it treated the functions as unprototyped, and only parsed some declarations, not e.g. "int g (int (...));". This option is changed into a no-op ignored option; (...) is always accepted syntactically, with a pedwarn_c11 call to given required diagnostics when appropriate. The peculiarity of a parameter list with __attribute__ followed by '...' being accepted with that option is removed. Interfaces in tree.cc that create function types are adjusted to set this flag as appropriate. It is of course possible that some existing users of the functions to create variable-argument functions actually wanted unprototyped functions in the no-named-argument case, rather than functions with a (...) prototype; some such cases in c-common.cc (for built-in functions and implicit function declarations) turn out to need updating for that reason. I didn't do anything to change how the C++ front end creates (...) function types. It's very likely there are unchanged places in the compiler that in fact turn out to need changes to work properly with (...) function prototypes. Target setup_incoming_varargs hooks, where they used the information passed about the last named argument, needed updating to avoid using that information in the (...) case. Note that apart from the x86 changes, I haven't done any testing of those target changes beyond building cc1 to check for syntax errors. It's possible further target-specific fixes will be needed; target maintainers should watch out for failures of c2x-stdarg-4.c or c2x-stdarg-split-1a.c, the execution tests, which would indicate that this feature is not working correctly. Those tests also verify the case where there are named arguments but the last named argument has a declaration that results in undefined behavior in previous C standard versions, such as a type changed by the default argument promotions. Bootstrapped with no regressions for x86_64-pc-linux-gnu. gcc/ * config/aarch64/aarch64.cc (aarch64_setup_incoming_varargs): Check TYPE_NO_NAMED_ARGS_STDARG_P. * config/alpha/alpha.cc (alpha_setup_incoming_varargs): Likewise. * config/arc/arc.cc (arc_setup_incoming_varargs): Likewise. * config/arm/arm.cc (arm_setup_incoming_varargs): Likewise. * config/csky/csky.cc (csky_setup_incoming_varargs): Likewise. * config/epiphany/epiphany.cc (epiphany_setup_incoming_varargs): Likewise. * config/fr30/fr30.cc (fr30_setup_incoming_varargs): Likewise. * config/frv/frv.cc (frv_setup_incoming_varargs): Likewise. * config/ft32/ft32.cc (ft32_setup_incoming_varargs): Likewise. * config/i386/i386.cc (ix86_setup_incoming_varargs): Likewise. * config/ia64/ia64.cc (ia64_setup_incoming_varargs): Likewise. * config/loongarch/loongarch.cc (loongarch_setup_incoming_varargs): Likewise. * config/m32r/m32r.cc (m32r_setup_incoming_varargs): Likewise. * config/mcore/mcore.cc (mcore_setup_incoming_varargs): Likewise. * config/mips/mips.cc (mips_setup_incoming_varargs): Likewise. * config/mmix/mmix.cc (mmix_setup_incoming_varargs): Likewise. * config/nds32/nds32.cc (nds32_setup_incoming_varargs): Likewise. * config/nios2/nios2.cc (nios2_setup_incoming_varargs): Likewise. * config/riscv/riscv.cc (riscv_setup_incoming_varargs): Likewise. * config/rs6000/rs6000-call.cc (setup_incoming_varargs): Likewise. * config/sh/sh.cc (sh_setup_incoming_varargs): Likewise. * config/visium/visium.cc (visium_setup_incoming_varargs): Likewise. * config/vms/vms-c.cc (vms_c_common_override_options): Do not set flag_allow_parameterless_variadic_functions. * doc/invoke.texi (-fallow-parameterless-variadic-functions): Do not document option. * function.cc (assign_parms): Call assign_parms_setup_varargs for TYPE_NO_NAMED_ARGS_STDARG_P case. * ginclude/stdarg.h [__STDC_VERSION__ > 201710L] (va_start): Make variadic macro. Pass second argument of 0 to __builtin_va_start. * target.def (setup_incoming_varargs): Update documentation. * doc/tm.texi: Regenerate. * tree-core.h (struct tree_type_common): Add no_named_args_stdarg_p. * tree-streamer-in.cc (unpack_ts_type_common_value_fields): Unpack TYPE_NO_NAMED_ARGS_STDARG_P. * tree-streamer-out.cc (pack_ts_type_common_value_fields): Pack TYPE_NO_NAMED_ARGS_STDARG_P. * tree.cc (type_cache_hasher::equal): Compare TYPE_NO_NAMED_ARGS_STDARG_P. (build_function_type): Add argument no_named_args_stdarg_p. (build_function_type_list_1, build_function_type_array_1) (reconstruct_complex_type): Update calls to build_function_type. (stdarg_p, prototype_p): Return true for (...) functions. (gimple_canonical_types_compatible_p): Compare TYPE_NO_NAMED_ARGS_STDARG_P. * tree.h (TYPE_NO_NAMED_ARGS_STDARG_P): New. (build_function_type): Update prototype. gcc/c-family/ * c-common.cc (def_fn_type): Call build_function_type for zero-argument variable-argument function. (c_common_nodes_and_builtins): Build default_function_type with build_function_type. * c.opt (fallow-parameterless-variadic-functions): Mark as ignored option. gcc/c/ * c-decl.cc (grokdeclarator): Pass arg_info->no_named_args_stdarg_p to build_function_type. (grokparms): Check arg_info->no_named_args_stdarg_p before converting () to (void). (build_arg_info): Initialize no_named_args_stdarg_p. (get_parm_info): Set no_named_args_stdarg_p. (start_function): Pass TYPE_NO_NAMED_ARGS_STDARG_P to build_function_type. (store_parm_decls): Count (...) functions as prototyped. * c-parser.cc (c_parser_direct_declarator): Allow '...' after open parenthesis to start parameter list. (c_parser_parms_list_declarator): Always allow '...' with no arguments, call pedwarn_c11 and set no_named_args_stdarg_p. * c-tree.h (struct c_arg_info): Add field no_named_args_stdarg_p. * c-typeck.cc (composite_type): Handle TYPE_NO_NAMED_ARGS_STDARG_P. (function_types_compatible_p): Compare TYPE_NO_NAMED_ARGS_STDARG_P. gcc/fortran/ * trans-types.cc (gfc_get_function_type): Do not use build_varargs_function_type_vec for unprototyped function. gcc/lto/ * lto-common.cc (compare_tree_sccs_1): Compare TYPE_NO_NAMED_ARGS_STDARG_P. gcc/objc/ * objc-next-runtime-abi-01.cc (build_next_objc_exception_stuff): Use build_function_type to build type of objc_setjmp_decl. gcc/testsuite/ * gcc.dg/c11-stdarg-1.c, gcc.dg/c11-stdarg-2.c, gcc.dg/c11-stdarg-3.c, gcc.dg/c2x-stdarg-1.c, gcc.dg/c2x-stdarg-2.c, gcc.dg/c2x-stdarg-3.c, gcc.dg/c2x-stdarg-4.c, gcc.dg/gnu2x-stdarg-1.c, gcc.dg/torture/c2x-stdarg-split-1a.c, gcc.dg/torture/c2x-stdarg-split-1b.c: New tests. * gcc.dg/Wold-style-definition-2.c, gcc.dg/format/sentinel-1.c: Update expected diagnostics. * gcc.dg/c2x-nullptr-1.c (test5): Cast unused parameter to (void). * gcc.dg/diagnostic-token-ranges.c: Use -pedantic. Expect warning in place of error. --- gcc/c-family/c-common.cc | 11 +- gcc/c-family/c.opt | 4 +- gcc/c/c-decl.cc | 13 +- gcc/c/c-parser.cc | 22 +-- gcc/c/c-tree.h | 2 + gcc/c/c-typeck.cc | 20 ++- gcc/config/aarch64/aarch64.cc | 3 +- gcc/config/alpha/alpha.cc | 5 +- gcc/config/arc/arc.cc | 3 +- gcc/config/arm/arm.cc | 3 +- gcc/config/csky/csky.cc | 3 +- gcc/config/epiphany/epiphany.cc | 8 +- gcc/config/fr30/fr30.cc | 23 +-- gcc/config/frv/frv.cc | 3 +- gcc/config/ft32/ft32.cc | 6 +- gcc/config/i386/i386.cc | 3 +- gcc/config/ia64/ia64.cc | 5 +- gcc/config/loongarch/loongarch.cc | 3 +- gcc/config/m32r/m32r.cc | 12 +- gcc/config/mcore/mcore.cc | 5 +- gcc/config/mips/mips.cc | 3 +- gcc/config/mmix/mmix.cc | 3 +- gcc/config/nds32/nds32.cc | 9 +- gcc/config/nios2/nios2.cc | 3 +- gcc/config/riscv/riscv.cc | 3 +- gcc/config/rs6000/rs6000-call.cc | 7 +- gcc/config/sh/sh.cc | 9 +- gcc/config/visium/visium.cc | 3 +- gcc/config/vms/vms-c.cc | 3 - gcc/doc/invoke.texi | 10 +- gcc/doc/tm.texi | 4 +- gcc/fortran/trans-types.cc | 4 +- gcc/function.cc | 6 + gcc/ginclude/stdarg.h | 4 + gcc/lto/lto-common.cc | 1 + gcc/objc/objc-next-runtime-abi-01.cc | 2 +- gcc/target.def | 4 +- gcc/testsuite/gcc.dg/Wold-style-definition-2.c | 2 +- gcc/testsuite/gcc.dg/c11-stdarg-1.c | 7 + gcc/testsuite/gcc.dg/c11-stdarg-2.c | 7 + gcc/testsuite/gcc.dg/c11-stdarg-3.c | 8 + gcc/testsuite/gcc.dg/c2x-nullptr-1.c | 1 + gcc/testsuite/gcc.dg/c2x-stdarg-1.c | 22 +++ gcc/testsuite/gcc.dg/c2x-stdarg-2.c | 22 +++ gcc/testsuite/gcc.dg/c2x-stdarg-3.c | 16 ++ gcc/testsuite/gcc.dg/c2x-stdarg-4.c | 164 +++++++++++++++++++++ gcc/testsuite/gcc.dg/diagnostic-token-ranges.c | 4 +- gcc/testsuite/gcc.dg/format/sentinel-1.c | 2 +- gcc/testsuite/gcc.dg/gnu2x-stdarg-1.c | 8 + gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1a.c | 37 +++++ gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1b.c | 147 ++++++++++++++++++ gcc/tree-core.h | 3 +- gcc/tree-streamer-in.cc | 1 + gcc/tree-streamer-out.cc | 1 + gcc/tree.cc | 31 +++- gcc/tree.h | 8 +- 56 files changed, 621 insertions(+), 105 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/c11-stdarg-1.c create mode 100644 gcc/testsuite/gcc.dg/c11-stdarg-2.c create mode 100644 gcc/testsuite/gcc.dg/c11-stdarg-3.c create mode 100644 gcc/testsuite/gcc.dg/c2x-stdarg-1.c create mode 100644 gcc/testsuite/gcc.dg/c2x-stdarg-2.c create mode 100644 gcc/testsuite/gcc.dg/c2x-stdarg-3.c create mode 100644 gcc/testsuite/gcc.dg/c2x-stdarg-4.c create mode 100644 gcc/testsuite/gcc.dg/gnu2x-stdarg-1.c create mode 100644 gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1a.c create mode 100644 gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1b.c (limited to 'gcc') diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index cd54c51..5890c18 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -4064,7 +4064,8 @@ static tree builtin_types[(int) BT_LAST + 1]; /* A helper function for c_common_nodes_and_builtins. Build function type for DEF with return type RET and N arguments. If VAR is true, then the - function should be variadic after those N arguments. + function should be variadic after those N arguments, or, if N is zero, + unprototyped. Takes special care not to ICE if any of the types involved are error_mark_node, which indicates that said type is not in fact available @@ -4093,7 +4094,10 @@ def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...) if (t == error_mark_node) goto egress; if (var) - t = build_varargs_function_type_array (t, n, args); + if (n == 0) + t = build_function_type (t, NULL_TREE); + else + t = build_varargs_function_type_array (t, n, args); else t = build_function_type_array (t, n, args); @@ -4661,8 +4665,7 @@ c_common_nodes_and_builtins (void) uintptr_type_node = TREE_TYPE (identifier_global_value (c_get_ident (UINTPTR_TYPE))); - default_function_type - = build_varargs_function_type_list (integer_type_node, NULL_TREE); + default_function_type = build_function_type (integer_type_node, NULL_TREE); unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node); lang_hooks.decls.pushdecl diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 070f85c..63a300e 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1512,8 +1512,8 @@ fall-virtual C++ ObjC++ WarnRemoved fallow-parameterless-variadic-functions -C ObjC Var(flag_allow_parameterless_variadic_functions) -Allow variadic functions without named parameter. +C ObjC Ignore +Does nothing. Preserved for backward compatibility. falt-external-templates C++ ObjC++ WarnRemoved diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 2b83900..795c971 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -7295,7 +7295,8 @@ grokdeclarator (const struct c_declarator *declarator, } type_quals = TYPE_UNQUALIFIED; - type = build_function_type (type, arg_types); + type = build_function_type (type, arg_types, + arg_info->no_named_args_stdarg_p); declarator = declarator->declarator; /* Set the TYPE_CONTEXTs for each tagged type which is local to @@ -8060,7 +8061,8 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag) /* In C2X, convert () to (void). */ if (flag_isoc2x && !arg_types - && !arg_info->parms) + && !arg_info->parms + && !arg_info->no_named_args_stdarg_p) arg_types = arg_info->types = void_list_node; /* If there is a parameter of incomplete type in a definition, @@ -8130,6 +8132,7 @@ build_arg_info (void) ret->others = NULL_TREE; ret->pending_sizes = NULL; ret->had_vla_unspec = 0; + ret->no_named_args_stdarg_p = 0; return ret; } @@ -8321,6 +8324,7 @@ get_parm_info (bool ellipsis, tree expr) arg_info->types = types; arg_info->others = others; arg_info->pending_sizes = expr; + arg_info->no_named_args_stdarg_p = ellipsis && !types; return arg_info; } @@ -9935,7 +9939,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, /* Make it return void instead. */ TREE_TYPE (decl1) = build_function_type (void_type_node, - TYPE_ARG_TYPES (TREE_TYPE (decl1))); + TYPE_ARG_TYPES (TREE_TYPE (decl1)), + TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (decl1))); } if (warn_about_return_type) @@ -10534,7 +10539,7 @@ store_parm_decls (void) empty argument list was converted to (void) in grokparms; in older C standard versions, it does not give the function a type with a prototype for future calls. */ - proto = arg_info->types != 0; + proto = arg_info->types != 0 || arg_info->no_named_args_stdarg_p; if (proto) store_parm_decls_newstyle (fndecl, arg_info); diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 4d1dcb1..ca533c9 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -4213,7 +4213,8 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, if (kind != C_DTR_NORMAL && (c_parser_next_token_starts_declspecs (parser) || (!have_gnu_attrs - && c_parser_nth_token_starts_std_attributes (parser, 1)) + && (c_parser_nth_token_starts_std_attributes (parser, 1) + || c_parser_next_token_is (parser, CPP_ELLIPSIS))) || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) { struct c_arg_info *args @@ -4489,25 +4490,18 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr, c_parser_consume_token (parser); return ret; } - if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) + if (c_parser_next_token_is (parser, CPP_ELLIPSIS) && !have_gnu_attrs) { struct c_arg_info *ret = build_arg_info (); - if (flag_allow_parameterless_variadic_functions) - { - /* F (...) is allowed. */ - ret->types = NULL_TREE; - } - else - { - /* Suppress -Wold-style-definition for this case. */ - ret->types = error_mark_node; - error_at (c_parser_peek_token (parser)->location, - "ISO C requires a named argument before %<...%>"); - } + ret->types = NULL_TREE; + pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic, + "ISO C requires a named argument before %<...%> " + "before C2X"); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) { + ret->no_named_args_stdarg_p = true; c_parser_consume_token (parser); return ret; } diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index d787dd4..facfc12 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -475,6 +475,8 @@ struct c_arg_info { tree pending_sizes; /* True when these arguments had [*]. */ BOOL_BITFIELD had_vla_unspec : 1; + /* True when the arguments are a (...) prototype. */ + BOOL_BITFIELD no_named_args_stdarg_p : 1; }; /* A declarator. */ diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 6c16647..052ae6d 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -544,17 +544,19 @@ composite_type (tree t1, tree t2) /* Simple way if one arg fails to specify argument types. */ if (TYPE_ARG_TYPES (t1) == NULL_TREE) - { - t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2)); + { + t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2), + TYPE_NO_NAMED_ARGS_STDARG_P (t2)); t1 = build_type_attribute_variant (t1, attributes); return qualify_type (t1, t2); } if (TYPE_ARG_TYPES (t2) == NULL_TREE) - { - t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1)); - t1 = build_type_attribute_variant (t1, attributes); - return qualify_type (t1, t2); - } + { + t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1), + TYPE_NO_NAMED_ARGS_STDARG_P (t1)); + t1 = build_type_attribute_variant (t1, attributes); + return qualify_type (t1, t2); + } /* If both args specify argument types, we must merge the two lists, argument by argument. */ @@ -1702,6 +1704,8 @@ function_types_compatible_p (const_tree f1, const_tree f2, if (args1 == NULL_TREE) { + if (TYPE_NO_NAMED_ARGS_STDARG_P (f1) != TYPE_NO_NAMED_ARGS_STDARG_P (f2)) + return 0; if (!self_promoting_args_p (args2)) return 0; /* If one of these types comes from a non-prototype fn definition, @@ -1715,6 +1719,8 @@ function_types_compatible_p (const_tree f1, const_tree f2, } if (args2 == NULL_TREE) { + if (TYPE_NO_NAMED_ARGS_STDARG_P (f1) != TYPE_NO_NAMED_ARGS_STDARG_P (f2)) + return 0; if (!self_promoting_args_p (args1)) return 0; if (TYPE_ACTUAL_ARG_TYPES (f2) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 0458c65..d1f979eb 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -19891,7 +19891,8 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v, argument. Advance a local copy of CUM past the last "real" named argument, to find out how many registers are left over. */ local_cum = *cum; - aarch64_function_arg_advance (pack_cumulative_args(&local_cum), arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + aarch64_function_arg_advance (pack_cumulative_args(&local_cum), arg); /* Found out how many registers we need to save. Honor tree-stdvar analysis results. */ diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc index 66c1714..333f2c6 100644 --- a/gcc/config/alpha/alpha.cc +++ b/gcc/config/alpha/alpha.cc @@ -6084,8 +6084,9 @@ alpha_setup_incoming_varargs (cumulative_args_t pcum, { CUMULATIVE_ARGS cum = *get_cumulative_args (pcum); - /* Skip the current argument. */ - targetm.calls.function_arg_advance (pack_cumulative_args (&cum), arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + /* Skip the current argument. */ + targetm.calls.function_arg_advance (pack_cumulative_args (&cum), arg); #if TARGET_ABI_OPEN_VMS /* For VMS, we allocate space for all 6 arg registers plus a count. diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index e6f52d8..604a116 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -2450,7 +2450,8 @@ arc_setup_incoming_varargs (cumulative_args_t args_so_far, /* We must treat `__builtin_va_alist' as an anonymous arg. */ next_cum = *get_cumulative_args (args_so_far); - arc_function_arg_advance (pack_cumulative_args (&next_cum), arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + arc_function_arg_advance (pack_cumulative_args (&next_cum), arg); first_anon_arg = next_cum; if (FUNCTION_ARG_REGNO_P (first_anon_arg)) diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index ee8f1ba..2eb4d51 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -29143,7 +29143,8 @@ arm_setup_incoming_varargs (cumulative_args_t pcum_v, if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL) { nregs = pcum->aapcs_ncrn; - if (nregs & 1) + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)) + && (nregs & 1)) { int res = arm_needs_doubleword_align (arg.mode, arg.type); if (res < 0 && warn_psabi) diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc index f7b2bf8..537eee6 100644 --- a/gcc/config/csky/csky.cc +++ b/gcc/config/csky/csky.cc @@ -2086,7 +2086,8 @@ csky_setup_incoming_varargs (cumulative_args_t pcum_v, cfun->machine->uses_anonymous_args = 1; local_cum = *pcum; - csky_function_arg_advance (local_cum_v, arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + csky_function_arg_advance (local_cum_v, arg); regs_to_push = CSKY_NPARM_REGS - local_cum.reg; if (regs_to_push) *pretend_size = regs_to_push * UNITS_PER_WORD; diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc index f8c0493..c4e3cea 100644 --- a/gcc/config/epiphany/epiphany.cc +++ b/gcc/config/epiphany/epiphany.cc @@ -727,11 +727,13 @@ epiphany_setup_incoming_varargs (cumulative_args_t cum, machine_function_t *mf = MACHINE_FUNCTION (cfun); /* All BLKmode values are passed by reference. */ - gcc_assert (arg.mode != BLKmode); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + gcc_assert (arg.mode != BLKmode); next_cum = *get_cumulative_args (cum); - next_cum = (ROUND_ADVANCE_CUM (next_cum, arg.mode, arg.type) - + ROUND_ADVANCE_ARG (arg.mode, arg.type)); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + next_cum = (ROUND_ADVANCE_CUM (next_cum, arg.mode, arg.type) + + ROUND_ADVANCE_ARG (arg.mode, arg.type)); first_anon_arg = next_cum; if (first_anon_arg < MAX_EPIPHANY_PARM_REGS && !no_rtl) diff --git a/gcc/config/fr30/fr30.cc b/gcc/config/fr30/fr30.cc index c9b061d..334bb44 100644 --- a/gcc/config/fr30/fr30.cc +++ b/gcc/config/fr30/fr30.cc @@ -471,16 +471,19 @@ fr30_setup_incoming_varargs (cumulative_args_t arg_regs_used_so_far_v, = get_cumulative_args (arg_regs_used_so_far_v); int size; - /* All BLKmode values are passed by reference. */ - gcc_assert (arg.mode != BLKmode); - - /* ??? This run-time test as well as the code inside the if - statement is probably unnecessary. */ - if (targetm.calls.strict_argument_naming (arg_regs_used_so_far_v)) - /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named - arg must not be treated as an anonymous arg. */ - /* ??? This is a pointer increment, which makes no sense. */ - arg_regs_used_so_far += fr30_num_arg_regs (arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + { + /* All BLKmode values are passed by reference. */ + gcc_assert (arg.mode != BLKmode); + + /* ??? This run-time test as well as the code inside the if + statement is probably unnecessary. */ + if (targetm.calls.strict_argument_naming (arg_regs_used_so_far_v)) + /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named + arg must not be treated as an anonymous arg. */ + /* ??? This is a pointer increment, which makes no sense. */ + arg_regs_used_so_far += fr30_num_arg_regs (arg); + } size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far); diff --git a/gcc/config/frv/frv.cc b/gcc/config/frv/frv.cc index 6f1904b..5cdb0bf 100644 --- a/gcc/config/frv/frv.cc +++ b/gcc/config/frv/frv.cc @@ -2104,7 +2104,8 @@ frv_setup_incoming_varargs (cumulative_args_t cum_v, { CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - if (TARGET_DEBUG_ARG) + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)) + && TARGET_DEBUG_ARG) fprintf (stderr, "setup_vararg: words = %2d, mode = %4s, pretend_size = %d, second_time = %d\n", *cum, GET_MODE_NAME (arg.mode), *pretend_size, second_time); diff --git a/gcc/config/ft32/ft32.cc b/gcc/config/ft32/ft32.cc index ed2d122..d6b73d4 100644 --- a/gcc/config/ft32/ft32.cc +++ b/gcc/config/ft32/ft32.cc @@ -634,8 +634,10 @@ ft32_setup_incoming_varargs (cumulative_args_t cum_v, int *pretend_size, int no_rtl ATTRIBUTE_UNUSED) { CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - int named_size = - GET_MODE_SIZE (SImode) * (*cum - FT32_R0) + GET_MODE_SIZE (arg.mode); + int named_size = 0; + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + named_size = + GET_MODE_SIZE (SImode) * (*cum - FT32_R0) + GET_MODE_SIZE (arg.mode); if (named_size < 24) *pretend_size = 24 - named_size; diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index aeea26e..e775ba4 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -4559,7 +4559,8 @@ ix86_setup_incoming_varargs (cumulative_args_t cum_v, /* For varargs, we do not want to skip the dummy va_dcl argument. For stdargs, we do want to skip the last named argument. */ next_cum = *cum; - if (stdarg_p (fntype)) + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)) + && stdarg_p (fntype)) ix86_function_arg_advance (pack_cumulative_args (&next_cum), arg); if (cum->call_abi == MS_ABI) diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc index 995ff90..6df1ce7 100644 --- a/gcc/config/ia64/ia64.cc +++ b/gcc/config/ia64/ia64.cc @@ -4596,8 +4596,9 @@ ia64_setup_incoming_varargs (cumulative_args_t cum, { CUMULATIVE_ARGS next_cum = *get_cumulative_args (cum); - /* Skip the current argument. */ - ia64_function_arg_advance (pack_cumulative_args (&next_cum), arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + /* Skip the current argument. */ + ia64_function_arg_advance (pack_cumulative_args (&next_cum), arg); if (next_cum.words < MAX_ARGUMENT_SLOTS) { diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index e9ba337..f54c233 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -756,7 +756,8 @@ loongarch_setup_incoming_varargs (cumulative_args_t cum, argument. Advance a local copy of CUM past the last "real" named argument, to find out how many registers are left over. */ local_cum = *get_cumulative_args (cum); - loongarch_function_arg_advance (pack_cumulative_args (&local_cum), arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + loongarch_function_arg_advance (pack_cumulative_args (&local_cum), arg); /* Found out how many registers we need to save. */ gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; diff --git a/gcc/config/m32r/m32r.cc b/gcc/config/m32r/m32r.cc index bca7681..e3489fb 100644 --- a/gcc/config/m32r/m32r.cc +++ b/gcc/config/m32r/m32r.cc @@ -1287,11 +1287,15 @@ m32r_setup_incoming_varargs (cumulative_args_t cum, return; /* All BLKmode values are passed by reference. */ - gcc_assert (arg.mode != BLKmode); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + gcc_assert (arg.mode != BLKmode); - first_anon_arg = (ROUND_ADVANCE_CUM (*get_cumulative_args (cum), - arg.mode, arg.type) - + ROUND_ADVANCE_ARG (arg.mode, arg.type)); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + first_anon_arg = (ROUND_ADVANCE_CUM (*get_cumulative_args (cum), + arg.mode, arg.type) + + ROUND_ADVANCE_ARG (arg.mode, arg.type)); + else + first_anon_arg = *get_cumulative_args (cum); if (first_anon_arg < M32R_MAX_PARM_REGS) { diff --git a/gcc/config/mcore/mcore.cc b/gcc/config/mcore/mcore.cc index 28e7074..605d63b 100644 --- a/gcc/config/mcore/mcore.cc +++ b/gcc/config/mcore/mcore.cc @@ -1953,8 +1953,9 @@ mcore_setup_incoming_varargs (cumulative_args_t args_so_far_v, /* We need to know how many argument registers are used before the varargs start, so that we can push the remaining argument registers during the prologue. */ - number_of_regs_before_varargs - = *args_so_far + mcore_num_arg_regs (arg.mode, arg.type); + number_of_regs_before_varargs = *args_so_far; + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + number_of_regs_before_varargs += mcore_num_arg_regs (arg.mode, arg.type); /* There is a bug somewhere in the arg handling code. Until I can find it this workaround always pushes the diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index 699ea6c..0ac0248 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -6683,7 +6683,8 @@ mips_setup_incoming_varargs (cumulative_args_t cum, argument. Advance a local copy of CUM past the last "real" named argument, to find out how many registers are left over. */ local_cum = *get_cumulative_args (cum); - mips_function_arg_advance (pack_cumulative_args (&local_cum), arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + mips_function_arg_advance (pack_cumulative_args (&local_cum), arg); /* Found out how many registers we need to save. */ gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; diff --git a/gcc/config/mmix/mmix.cc b/gcc/config/mmix/mmix.cc index ffdd8c7..1ac7b88 100644 --- a/gcc/config/mmix/mmix.cc +++ b/gcc/config/mmix/mmix.cc @@ -999,7 +999,8 @@ mmix_setup_incoming_varargs (cumulative_args_t args_so_farp_v, /* We assume that one argument takes up one register here. That should be true until we start messing with multi-reg parameters. */ - if ((7 + (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type))) / 8 != 1) + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)) + && (7 + (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type))) / 8 != 1) internal_error ("MMIX Internal: Last named vararg would not fit in a register"); } diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc index 67a6121..639baef 100644 --- a/gcc/config/nds32/nds32.cc +++ b/gcc/config/nds32/nds32.cc @@ -2377,9 +2377,12 @@ nds32_setup_incoming_varargs (cumulative_args_t ca, for varargs. */ total_args_regs = NDS32_MAX_GPR_REGS_FOR_ARGS + NDS32_GPR_ARG_FIRST_REGNUM; - num_of_used_regs - = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, arg.mode, arg.type) - + NDS32_NEED_N_REGS_FOR_ARG (arg.mode, arg.type); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + num_of_used_regs + = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, arg.mode, arg.type) + + NDS32_NEED_N_REGS_FOR_ARG (arg.mode, arg.type); + else + num_of_used_regs = cum->gpr_offset + NDS32_GPR_ARG_FIRST_REGNUM; remaining_reg_count = total_args_regs - num_of_used_regs; *pretend_args_size = remaining_reg_count * UNITS_PER_WORD; diff --git a/gcc/config/nios2/nios2.cc b/gcc/config/nios2/nios2.cc index 1a33c88..6a894ec 100644 --- a/gcc/config/nios2/nios2.cc +++ b/gcc/config/nios2/nios2.cc @@ -3524,7 +3524,8 @@ nios2_setup_incoming_varargs (cumulative_args_t cum_v, cfun->machine->uses_anonymous_args = 1; local_cum = *cum; - nios2_function_arg_advance (local_cum_v, arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + nios2_function_arg_advance (local_cum_v, arg); regs_to_push = NUM_ARG_REGS - local_cum.regs_used; diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 77bc65b..32f9ef9 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -3730,7 +3730,8 @@ riscv_setup_incoming_varargs (cumulative_args_t cum, argument. Advance a local copy of CUM past the last "real" named argument, to find out how many registers are left over. */ local_cum = *get_cumulative_args (cum); - riscv_function_arg_advance (pack_cumulative_args (&local_cum), arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + riscv_function_arg_advance (pack_cumulative_args (&local_cum), arg); /* Found out how many registers we need to save. */ gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc index ac3cb7e..6da4de6 100644 --- a/gcc/config/rs6000/rs6000-call.cc +++ b/gcc/config/rs6000/rs6000-call.cc @@ -2253,7 +2253,9 @@ setup_incoming_varargs (cumulative_args_t cum, /* Skip the last named argument. */ next_cum = *get_cumulative_args (cum); - rs6000_function_arg_advance_1 (&next_cum, arg.mode, arg.type, arg.named, 0); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + rs6000_function_arg_advance_1 (&next_cum, arg.mode, arg.type, arg.named, + 0); if (DEFAULT_ABI == ABI_V4) { @@ -2327,7 +2329,8 @@ setup_incoming_varargs (cumulative_args_t cum, first_reg_offset = next_cum.words; save_area = crtl->args.internal_arg_pointer; - if (targetm.calls.must_pass_in_stack (arg)) + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)) + && targetm.calls.must_pass_in_stack (arg)) first_reg_offset += rs6000_arg_size (TYPE_MODE (arg.type), arg.type); } diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc index 9bee618..1aec70a 100644 --- a/gcc/config/sh/sh.cc +++ b/gcc/config/sh/sh.cc @@ -8183,11 +8183,12 @@ sh_setup_incoming_varargs (cumulative_args_t ca, gcc_assert (cfun->stdarg); if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl)) { - int named_parm_regs, anon_parm_regs; + int named_parm_regs = 0, anon_parm_regs; - named_parm_regs = (sh_round_reg (*get_cumulative_args (ca), arg.mode) - + CEIL (arg.promoted_size_in_bytes (), - UNITS_PER_WORD)); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + named_parm_regs = (sh_round_reg (*get_cumulative_args (ca), arg.mode) + + CEIL (arg.promoted_size_in_bytes (), + UNITS_PER_WORD)); anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs; if (anon_parm_regs > 0) *pretend_arg_size = anon_parm_regs * 4; diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc index 03c1a33..e7d1596 100644 --- a/gcc/config/visium/visium.cc +++ b/gcc/config/visium/visium.cc @@ -1481,7 +1481,8 @@ visium_setup_incoming_varargs (cumulative_args_t pcum_v, /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named argument. Advance a local copy of ARGS_SO_FAR past the last "real" named argument, to find out how many registers are left over. */ - TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far, arg); + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far, arg); /* Find how many registers we need to save. */ locargs = get_cumulative_args (local_args_so_far); diff --git a/gcc/config/vms/vms-c.cc b/gcc/config/vms/vms-c.cc index 2f74fb5..ccf6d5f 100644 --- a/gcc/config/vms/vms-c.cc +++ b/gcc/config/vms/vms-c.cc @@ -455,9 +455,6 @@ vms_c_register_includes (const char *sysroot, void vms_c_common_override_options (void) { - /* Allow variadic functions without parameters (as declared in starlet). */ - flag_allow_parameterless_variadic_functions = TRUE; - /* Initialize c_default_pointer_mode. */ switch (flag_vms_pointer_size) { diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index c0ca765..550aec8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -198,7 +198,7 @@ in the following sections. @item C Language Options @xref{C Dialect Options,,Options Controlling C Dialect}. @gccoptlist{-ansi -std=@var{standard} -aux-info @var{filename} @gol --fallow-parameterless-variadic-functions -fno-asm @gol +-fno-asm @gol -fno-builtin -fno-builtin-@var{function} -fcond-mismatch @gol -ffreestanding -fgimple -fgnu-tm -fgnu89-inline -fhosted @gol -flax-vector-conversions -fms-extensions @gol @@ -2515,14 +2515,6 @@ character). In the case of function definitions, a K&R-style list of arguments followed by their declarations is also provided, inside comments, after the declaration. -@item -fallow-parameterless-variadic-functions -@opindex fallow-parameterless-variadic-functions -Accept variadic functions without named parameters. - -Although it is possible to define such a function, this is not very -useful as it is not possible to read the arguments. This is only -supported for C as this construct is allowed by C++. - @item -fno-asm @opindex fno-asm @opindex fasm diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 110f8df..63c8a31 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5378,7 +5378,9 @@ pass all their arguments on the stack. The argument @var{args_so_far} points to the @code{CUMULATIVE_ARGS} data structure, containing the values that are obtained after processing the named arguments. The argument @var{arg} describes the last of these named -arguments. +arguments. The argument @var{arg} should not be used if the function type +satisfies @code{TYPE_NO_NAMED_ARGS_STDARG_P}, since in that case there are +no named arguments and all arguments are accessed with @code{va_arg}. The target hook should do two things: first, push onto the stack all the argument registers @emph{not} used for the named arguments, and second, diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc index fdce56d..def7552 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -3297,7 +3297,9 @@ arg_type_list_done: type = gfc_sym_type (sym); if (is_varargs) - type = build_varargs_function_type_vec (type, typelist); + /* This should be represented as an unprototyped type, not a type + with (...) prototype. */ + type = build_function_type (type, NULL_TREE); else type = build_function_type_vec (type, typelist); diff --git a/gcc/function.cc b/gcc/function.cc index 6474a66..d3da20e 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -3647,6 +3647,12 @@ assign_parms (tree fndecl) assign_parms_initialize_all (&all); fnargs = assign_parms_augmented_arg_list (&all); + if (TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (fndecl))) + { + struct assign_parm_data_one data = {}; + assign_parms_setup_varargs (&all, &data, false); + } + FOR_EACH_VEC_ELT (fnargs, i, parm) { struct assign_parm_data_one data; diff --git a/gcc/ginclude/stdarg.h b/gcc/ginclude/stdarg.h index 7545ed3..c704c9f 100644 --- a/gcc/ginclude/stdarg.h +++ b/gcc/ginclude/stdarg.h @@ -44,7 +44,11 @@ typedef __builtin_va_list __gnuc_va_list; if this invocation was from the user program. */ #ifdef _STDARG_H +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +#define va_start(v, ...) __builtin_va_start(v, 0) +#else #define va_start(v,l) __builtin_va_start(v,l) +#endif #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v,l) #if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L \ diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc index d8d0404..f643097 100644 --- a/gcc/lto/lto-common.cc +++ b/gcc/lto/lto-common.cc @@ -1270,6 +1270,7 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map) if (AGGREGATE_TYPE_P (t1)) compare_values (TYPE_TYPELESS_STORAGE); compare_values (TYPE_EMPTY_P); + compare_values (TYPE_NO_NAMED_ARGS_STDARG_P); compare_values (TYPE_PACKED); compare_values (TYPE_RESTRICT); compare_values (TYPE_USER_ALIGN); diff --git a/gcc/objc/objc-next-runtime-abi-01.cc b/gcc/objc/objc-next-runtime-abi-01.cc index 409b777..8d41886 100644 --- a/gcc/objc/objc-next-runtime-abi-01.cc +++ b/gcc/objc/objc-next-runtime-abi-01.cc @@ -2443,7 +2443,7 @@ build_next_objc_exception_stuff (void) /* int _setjmp(...); */ /* If the user includes , this shall be superseded by 'int _setjmp(jmp_buf);' */ - temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE); + temp_type = build_function_type (integer_type_node, NULL_TREE); objc_setjmp_decl = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE); diff --git a/gcc/target.def b/gcc/target.def index a3d3b04..25f94c1 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4680,7 +4680,9 @@ pass all their arguments on the stack.\n\ The argument @var{args_so_far} points to the @code{CUMULATIVE_ARGS} data\n\ structure, containing the values that are obtained after processing the\n\ named arguments. The argument @var{arg} describes the last of these named\n\ -arguments.\n\ +arguments. The argument @var{arg} should not be used if the function type\n\ +satisfies @code{TYPE_NO_NAMED_ARGS_STDARG_P}, since in that case there are\n\ +no named arguments and all arguments are accessed with @code{va_arg}.\n\ \n\ The target hook should do two things: first, push onto the stack all the\n\ argument registers @emph{not} used for the named arguments, and second,\n\ diff --git a/gcc/testsuite/gcc.dg/Wold-style-definition-2.c b/gcc/testsuite/gcc.dg/Wold-style-definition-2.c index a69aae6..8e297c9 100644 --- a/gcc/testsuite/gcc.dg/Wold-style-definition-2.c +++ b/gcc/testsuite/gcc.dg/Wold-style-definition-2.c @@ -5,6 +5,6 @@ /* { dg-do compile } */ /* { dg-options "-Wold-style-definition" } */ -void bar1 ( ... ) {} /* { dg-error "ISO C requires a named argument" } */ +void bar1 ( ... ) {} void bar2 (int a, ... ) {} diff --git a/gcc/testsuite/gcc.dg/c11-stdarg-1.c b/gcc/testsuite/gcc.dg/c11-stdarg-1.c new file mode 100644 index 0000000..984577f --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-stdarg-1.c @@ -0,0 +1,7 @@ +/* Test variadic functions with no named parameters not supported in C11. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +int f (...); /* { dg-error "ISO C requires a named argument before" } */ +int g (int (...)); /* { dg-error "ISO C requires a named argument before" } */ +int h (...) { return 0; } /* { dg-error "ISO C requires a named argument before" } */ diff --git a/gcc/testsuite/gcc.dg/c11-stdarg-2.c b/gcc/testsuite/gcc.dg/c11-stdarg-2.c new file mode 100644 index 0000000..bd115e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-stdarg-2.c @@ -0,0 +1,7 @@ +/* Test variadic functions with no named parameters not supported in C11. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic" } */ + +int f (...); /* { dg-warning "ISO C requires a named argument before" } */ +int g (int (...)); /* { dg-warning "ISO C requires a named argument before" } */ +int h (...) { return 0; } /* { dg-warning "ISO C requires a named argument before" } */ diff --git a/gcc/testsuite/gcc.dg/c11-stdarg-3.c b/gcc/testsuite/gcc.dg/c11-stdarg-3.c new file mode 100644 index 0000000..0092924 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-stdarg-3.c @@ -0,0 +1,8 @@ +/* Test variadic functions with no named parameters not supported in C11, but + diagnostic disabled with -Wno-c11-c2x-compat. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors -Wno-c11-c2x-compat" } */ + +int f (...); +int g (int (...)); +int h (...) { return 0; } diff --git a/gcc/testsuite/gcc.dg/c2x-nullptr-1.c b/gcc/testsuite/gcc.dg/c2x-nullptr-1.c index 9501b51..9f2cb6c 100644 --- a/gcc/testsuite/gcc.dg/c2x-nullptr-1.c +++ b/gcc/testsuite/gcc.dg/c2x-nullptr-1.c @@ -226,6 +226,7 @@ test4 (void) static void test5 (int i, ...) { + (void) i; va_list ap; va_start (ap, i); if (va_arg (ap, void *)) diff --git a/gcc/testsuite/gcc.dg/c2x-stdarg-1.c b/gcc/testsuite/gcc.dg/c2x-stdarg-1.c new file mode 100644 index 0000000..7def49d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-stdarg-1.c @@ -0,0 +1,22 @@ +/* Test C2x variadic functions with no named parameters. Compilation tests, + valid code. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +int f (...); +int g (int (...)); +int h (...) { return 0; } + +typedef int A[]; +typedef int A2[2]; + +A *f1 (...); +A2 *f1 (...); +A *f1 (...) { return 0; } + +A2 *f2 (...); +A *f2 (...); +A2 *f2 (...) { return 0; } +typeof (f1) f2; + +int t () { return f () + f (1) + f (1, 2) + h () + h (1.5, 2, f1) + g (f); } diff --git a/gcc/testsuite/gcc.dg/c2x-stdarg-2.c b/gcc/testsuite/gcc.dg/c2x-stdarg-2.c new file mode 100644 index 0000000..2778240 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-stdarg-2.c @@ -0,0 +1,22 @@ +/* Test C2x variadic functions with no named parameters. Compilation tests, + valid code, verify not considered unprototyped functions. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -Wstrict-prototypes -Wold-style-definition" } */ + +int f (...); +int g (int (...)); +int h (...) { return 0; } + +typedef int A[]; +typedef int A2[2]; + +A *f1 (...); +A2 *f1 (...); +A *f1 (...) { return 0; } + +A2 *f2 (...); +A *f2 (...); +A2 *f2 (...) { return 0; } +typeof (f1) f2; + +int t () { return f () + f (1) + f (1, 2) + h () + h (1.5, 2, f1) + g (f); } diff --git a/gcc/testsuite/gcc.dg/c2x-stdarg-3.c b/gcc/testsuite/gcc.dg/c2x-stdarg-3.c new file mode 100644 index 0000000..e2e1406 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-stdarg-3.c @@ -0,0 +1,16 @@ +/* Test C2x variadic functions with no named parameters. Compilation tests, + invalid code. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +int f (...); /* { dg-message "previous declaration" } */ +int f (); /* { dg-error "conflicting types" } */ + +int f2 (...); /* { dg-message "previous declaration" } */ +int f2 (int); /* { dg-error "conflicting types" } */ + +int g (); /* { dg-message "previous declaration" } */ +int g (...); /* { dg-error "conflicting types" } */ + +int g2 (int); /* { dg-message "previous declaration" } */ +int g2 (...); /* { dg-error "conflicting types" } */ diff --git a/gcc/testsuite/gcc.dg/c2x-stdarg-4.c b/gcc/testsuite/gcc.dg/c2x-stdarg-4.c new file mode 100644 index 0000000..1f8718d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-stdarg-4.c @@ -0,0 +1,164 @@ +/* Test C2x variadic functions with no named parameters, or last named + parameter with a declaration not allowed in C17. Execution tests. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include + +extern void abort (void); +extern void exit (int); + +double +f (...) +{ + va_list ap; + va_start (ap); + double ret = va_arg (ap, int); + ret += va_arg (ap, double); + ret += va_arg (ap, int); + ret += va_arg (ap, double); + va_end (ap); + return ret; +} + +void +g (...) +{ + va_list ap; + va_start (ap, random ! ignored, ignored ** text); + for (int i = 0; i < 10; i++) + if (va_arg (ap, double) != i) + abort (); + va_end (ap); +} + +void +h1 (register int x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h2 (int x(), ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h3 (int x[10], ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h4 (char x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h5 (float x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h6 (volatile long x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +struct s { char c[1000]; }; + +void +h7 (volatile struct s x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +int +main () +{ + if (f (1, 2.0, 3, 4.0) != 10.0) + abort (); + g (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); + g (0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f); + h1 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h2 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h3 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h4 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h5 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h6 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h7 ((struct s) {}, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c index 7d7ec0a..31085be 100644 --- a/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c +++ b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c @@ -1,4 +1,4 @@ -/* { dg-options "-fdiagnostics-show-caret -Wc++-compat -std=c11" } */ +/* { dg-options "-fdiagnostics-show-caret -Wc++-compat -std=c11 -pedantic" } */ /* Verify that various diagnostics show source code ranges. */ @@ -48,7 +48,7 @@ void test_identifier_conflicts_with_cplusplus (void) } extern void -bogus_varargs (...); /* { dg-error "ISO C requires a named argument before '...'" } */ +bogus_varargs (...); /* { dg-warning "ISO C requires a named argument before '...'" } */ /* { dg-begin-multiline-output "" } bogus_varargs (...); diff --git a/gcc/testsuite/gcc.dg/format/sentinel-1.c b/gcc/testsuite/gcc.dg/format/sentinel-1.c index 0c8a2ac..16c75a8 100644 --- a/gcc/testsuite/gcc.dg/format/sentinel-1.c +++ b/gcc/testsuite/gcc.dg/format/sentinel-1.c @@ -15,7 +15,7 @@ extern char *envp[]; extern int a ATTR; /* { dg-warning "applies to function types" "sentinel" } */ extern void foo1 (const char *, ...) ATTR; /* { dg-message "note: declared here" } */ -extern void foo2 (...) ATTR; /* { dg-error "ISO C requires|named arguments" "sentinel" } */ +extern void foo2 (...) ATTR; extern void foo3 () ATTR; /* { dg-warning "named arguments" "sentinel" } */ extern void foo4 (const char *, int) ATTR; /* { dg-warning "variadic functions" "sentinel" } */ extern void foo5 (const char *, ...) __attribute__ ((__sentinel__(1))); diff --git a/gcc/testsuite/gcc.dg/gnu2x-stdarg-1.c b/gcc/testsuite/gcc.dg/gnu2x-stdarg-1.c new file mode 100644 index 0000000..bb64cde --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu2x-stdarg-1.c @@ -0,0 +1,8 @@ +/* Test variadic functions with no named parameters do not accept GNU + attributes before '...'. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu2x" } */ + +int f (__attribute__(()) ...); /* { dg-error "expected" } */ +int g (int (__attribute__(()) ...)); /* { dg-error "expected" } */ +int h (__attribute__(()) ...) { return 0; } /* { dg-error "expected" } */ diff --git a/gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1a.c b/gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1a.c new file mode 100644 index 0000000..f527b8232 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1a.c @@ -0,0 +1,37 @@ +/* Test C2x variadic functions with no named parameters, or last named + parameter with a declaration not allowed in C17. Execution tests split + between source files. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ +/* { dg-additional-sources "c2x-stdarg-split-1b.c" } */ + +extern void abort (void); +extern void exit (int); + +double f (...); +void g (...); +void h1 (register int x, ...); +void h2 (int x(), ...); +void h3 (int x[10], ...); +void h4 (char x, ...); +void h5 (float x, ...); +void h6 (volatile long x, ...); +struct s { char c[1000]; }; +void h7 (volatile struct s x, ...); + +int +main () +{ + if (f (1, 2.0, 3, 4.0) != 10.0) + abort (); + g (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); + g (0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f); + h1 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h2 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h3 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h4 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h5 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h6 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + h7 ((struct s) {}, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1b.c b/gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1b.c new file mode 100644 index 0000000..55a01b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1b.c @@ -0,0 +1,147 @@ +/* Test C2x variadic functions with no named parameters, or last named + parameter with a declaration not allowed in C17. Execution tests split + between source files. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include + +extern void abort (void); + +double +f (...) +{ + va_list ap; + va_start (ap); + double ret = va_arg (ap, int); + ret += va_arg (ap, double); + ret += va_arg (ap, int); + ret += va_arg (ap, double); + va_end (ap); + return ret; +} + +void +g (...) +{ + va_list ap; + va_start (ap, random ! ignored, ignored ** text); + for (int i = 0; i < 10; i++) + if (va_arg (ap, double) != i) + abort (); + va_end (ap); +} + +void +h1 (register int x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h2 (int x(), ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h3 (int x[10], ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h4 (char x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h5 (float x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +void +h6 (volatile long x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} + +struct s { char c[1000]; }; + +void +h7 (volatile struct s x, ...) +{ + va_list ap; + va_start (ap); + for (int i = 0; i < 10; i++) + { + if (va_arg (ap, double) != i) + abort (); + i++; + if (va_arg (ap, int) != i) + abort (); + } + va_end (ap); +} diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 80b886c..af75522 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1717,7 +1717,8 @@ struct GTY(()) tree_type_common { unsigned typeless_storage : 1; unsigned empty_flag : 1; unsigned indivisible_p : 1; - unsigned spare : 16; + unsigned no_named_args_stdarg_p : 1; + unsigned spare : 15; alias_set_type alias_set; tree pointer_to; diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc index 57923da..0fa1eba 100644 --- a/gcc/tree-streamer-in.cc +++ b/gcc/tree-streamer-in.cc @@ -398,6 +398,7 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) if (AGGREGATE_TYPE_P (expr)) TYPE_TYPELESS_STORAGE (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_EMPTY_P (expr) = (unsigned) bp_unpack_value (bp, 1); + TYPE_NO_NAMED_ARGS_STDARG_P (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp); SET_TYPE_ALIGN (expr, bp_unpack_var_len_unsigned (bp)); #ifdef ACCEL_COMPILER diff --git a/gcc/tree-streamer-out.cc b/gcc/tree-streamer-out.cc index 68a2818..3bf95ff 100644 --- a/gcc/tree-streamer-out.cc +++ b/gcc/tree-streamer-out.cc @@ -365,6 +365,7 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) if (AGGREGATE_TYPE_P (expr)) bp_pack_value (bp, TYPE_TYPELESS_STORAGE (expr), 1); bp_pack_value (bp, TYPE_EMPTY_P (expr), 1); + bp_pack_value (bp, TYPE_NO_NAMED_ARGS_STDARG_P (expr), 1); bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr)); bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr)); } diff --git a/gcc/tree.cc b/gcc/tree.cc index 04603c8..1720987 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -6112,7 +6112,9 @@ type_cache_hasher::equal (type_hash *a, type_hash *b) TYPE_FIELDS (b->type)))); case FUNCTION_TYPE: - if (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type) + if ((TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type) + && (TYPE_NO_NAMED_ARGS_STDARG_P (a->type) + == TYPE_NO_NAMED_ARGS_STDARG_P (b->type))) || (TYPE_ARG_TYPES (a->type) && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST && TYPE_ARG_TYPES (b->type) @@ -7364,10 +7366,13 @@ maybe_canonicalize_argtypes (tree argtypes, given arguments of types ARG_TYPES. ARG_TYPES is a chain of TREE_LIST nodes whose TREE_VALUEs are data type nodes for the arguments of the function. + NO_NAMED_ARGS_STDARG_P is true if this is a prototyped + variable-arguments function with (...) prototype (no named arguments). If such a type has already been constructed, reuse it. */ tree -build_function_type (tree value_type, tree arg_types) +build_function_type (tree value_type, tree arg_types, + bool no_named_args_stdarg_p) { tree t; inchash::hash hstate; @@ -7386,6 +7391,11 @@ build_function_type (tree value_type, tree arg_types) t = make_node (FUNCTION_TYPE); TREE_TYPE (t) = value_type; TYPE_ARG_TYPES (t) = arg_types; + if (no_named_args_stdarg_p) + { + gcc_assert (arg_types == NULL_TREE); + TYPE_NO_NAMED_ARGS_STDARG_P (t) = 1; + } /* If we already have such a type, use the old one. */ hashval_t hash = type_hash_canon_hash (t); @@ -7436,7 +7446,7 @@ build_function_type_list_1 (bool vaargs, tree return_type, va_list argp) args = nreverse (args); TREE_CHAIN (last) = void_list_node; } - args = build_function_type (return_type, args); + args = build_function_type (return_type, args, vaargs && args == NULL_TREE); return args; } @@ -7491,7 +7501,7 @@ build_function_type_array_1 (bool vaargs, tree return_type, int n, for (i = n - 1; i >= 0; i--) t = tree_cons (NULL_TREE, arg_types[i], t); - return build_function_type (return_type, t); + return build_function_type (return_type, t, vaargs && n == 0); } /* Build a function type. RETURN_TYPE is the type returned by the @@ -9994,7 +10004,8 @@ reconstruct_complex_type (tree type, tree bottom) else if (TREE_CODE (type) == FUNCTION_TYPE) { inner = reconstruct_complex_type (TREE_TYPE (type), bottom); - outer = build_function_type (inner, TYPE_ARG_TYPES (type)); + outer = build_function_type (inner, TYPE_ARG_TYPES (type), + TYPE_NO_NAMED_ARGS_STDARG_P (type)); } else if (TREE_CODE (type) == METHOD_TYPE) { @@ -11612,6 +11623,9 @@ stdarg_p (const_tree fntype) if (!fntype) return false; + if (TYPE_NO_NAMED_ARGS_STDARG_P (fntype)) + return true; + FOREACH_FUNCTION_ARGS (fntype, t, args_iter) { n = t; @@ -11629,6 +11643,9 @@ prototype_p (const_tree fntype) gcc_assert (fntype != NULL_TREE); + if (TYPE_NO_NAMED_ARGS_STDARG_P (fntype)) + return true; + t = TYPE_ARG_TYPES (fntype); return (t != NULL_TREE); } @@ -13647,7 +13664,9 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2, trust_type_canonical)) return false; - if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)) + if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2) + && (TYPE_NO_NAMED_ARGS_STDARG_P (t1) + == TYPE_NO_NAMED_ARGS_STDARG_P (t2))) return true; else { diff --git a/gcc/tree.h b/gcc/tree.h index a50f7b2..d6a5fdf 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -772,6 +772,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, normal GNU extensions for target-specific vector types. */ #define TYPE_INDIVISIBLE_P(NODE) (TYPE_CHECK (NODE)->type_common.indivisible_p) +/* True if this is a stdarg function with no named arguments (C2x + (...) prototype, where arguments can be accessed with va_start and + va_arg), as opposed to an unprototyped function. */ +#define TYPE_NO_NAMED_ARGS_STDARG_P(NODE) \ + (TYPE_CHECK (NODE)->type_common.no_named_args_stdarg_p) + /* In an IDENTIFIER_NODE, this means that assemble_name was called with this string as an argument. */ #define TREE_SYMBOL_REFERENCED(NODE) \ @@ -4734,7 +4740,7 @@ extern tree build_array_type_1 (tree, tree, bool, bool, bool); extern tree build_array_type (tree, tree, bool = false); extern tree build_nonshared_array_type (tree, tree); extern tree build_array_type_nelts (tree, poly_uint64); -extern tree build_function_type (tree, tree); +extern tree build_function_type (tree, tree, bool = false); extern tree build_function_type_list (tree, ...); extern tree build_varargs_function_type_list (tree, ...); extern tree build_function_type_array (tree, int, tree *); -- cgit v1.1 From 38a628f52cf0ff5db6708578248484d50a50b366 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 28 Oct 2022 10:45:06 -0400 Subject: c++: apply friend attributes sooner Comparing attributes between declarations of a friend function has been complicated by pushdecl happening before decl_attributes. I assumed there was some complicated reason we weren't calling decl_attributes here, but it doesn't break anything. gcc/cp/ChangeLog: * decl.cc (grokdeclarator): Call decl_attributes before do_friend. --- gcc/cp/decl.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index bc085f8..c7f1937 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -14206,13 +14206,16 @@ grokdeclarator (const cp_declarator *declarator, else if (decl && DECL_NAME (decl)) { set_originating_module (decl, true); - + if (initialized) /* Kludge: We need funcdef_flag to be true in do_friend for in-class defaulted functions, but that breaks grokfndecl. So set it here. */ funcdef_flag = true; + cplus_decl_attributes (&decl, *attrlist, 0); + *attrlist = NULL_TREE; + decl = do_friend (ctype, unqualified_id, decl, flags, funcdef_flag); return decl; -- cgit v1.1 From e583c86f49b9ef6991b25308a0ad60de9697f24a Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 26 Oct 2022 21:15:53 -0400 Subject: c++: -Wdangling-reference and system headers I got this testcase: auto f() -> std::optional; for (char c : f().value()) { } which has a dangling reference: std::optional::value returns a reference to the contained value, but here it's the f() temporary. We warn, which is great, but only with -Wsystem-headers, because the function comes from a system header and warning_enabled_at used in do_warn_dangling_reference checks diagnostic_report_warnings_p, which in this case returned false so we didn't warn. Fixed as below. I could also override dc_warn_system_headers so that the warning is enabled in system headers always. With that, I found one issue in libstdc++: libstdc++-v3/include/bits/fs_path.h:1265:15: warning: possibly dangling reference to a temporary [-Wdangling-reference] 1265 | auto& __last = *--end(); | ^~~~~~ which looks like a true positive as well. gcc/cp/ChangeLog: * call.cc (maybe_warn_dangling_reference): Enable the warning in system headers if the decl isn't in a system header. gcc/testsuite/ChangeLog: * g++.dg/warn/Wdangling-reference4.C: New test. --- gcc/cp/call.cc | 7 +++++++ gcc/testsuite/g++.dg/warn/Wdangling-reference4.C | 14 ++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference4.C (limited to 'gcc') diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 951b9fd..c7c7a12 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -13539,6 +13539,13 @@ maybe_warn_dangling_reference (const_tree decl, tree init) return; if (!TYPE_REF_P (TREE_TYPE (decl))) return; + /* Don't suppress the diagnostic just because the call comes from + a system header. If the DECL is not in a system header, or if + -Wsystem-headers was provided, warn. */ + auto wsh + = make_temp_override (global_dc->dc_warn_system_headers, + (!in_system_header_at (DECL_SOURCE_LOCATION (decl)) + || global_dc->dc_warn_system_headers)); if (tree call = do_warn_dangling_reference (init)) { auto_diagnostic_group d; diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C new file mode 100644 index 0000000..aee7a29 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-Wdangling-reference" } +// Check that we warn here even without -Wsystem-headers. + +#include +#include + +auto f() -> std::optional; + +void +g () +{ + for (char c : f().value()) { (void) c; } // { dg-warning "dangling reference" } +} -- cgit v1.1 From 3055829a4addde1fa3542c8070c87e2dd17217fc Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 29 Oct 2022 00:17:49 +0000 Subject: Daily bump. --- gcc/ChangeLog | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/c-family/ChangeLog | 17 ++++++++ gcc/c/ChangeLog | 83 +++++++++++++++++++++++++++++++++++++++ gcc/cp/ChangeLog | 26 +++++++++++++ gcc/fortran/ChangeLog | 5 +++ gcc/lto/ChangeLog | 13 +++++++ gcc/objc/ChangeLog | 5 +++ gcc/testsuite/ChangeLog | 71 ++++++++++++++++++++++++++++++++++ 9 files changed, 322 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a318a22..27e2c49 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,104 @@ +2022-10-28 Joseph Myers + + * config/aarch64/aarch64.cc (aarch64_setup_incoming_varargs): + Check TYPE_NO_NAMED_ARGS_STDARG_P. + * config/alpha/alpha.cc (alpha_setup_incoming_varargs): Likewise. + * config/arc/arc.cc (arc_setup_incoming_varargs): Likewise. + * config/arm/arm.cc (arm_setup_incoming_varargs): Likewise. + * config/csky/csky.cc (csky_setup_incoming_varargs): Likewise. + * config/epiphany/epiphany.cc (epiphany_setup_incoming_varargs): + Likewise. + * config/fr30/fr30.cc (fr30_setup_incoming_varargs): Likewise. + * config/frv/frv.cc (frv_setup_incoming_varargs): Likewise. + * config/ft32/ft32.cc (ft32_setup_incoming_varargs): Likewise. + * config/i386/i386.cc (ix86_setup_incoming_varargs): Likewise. + * config/ia64/ia64.cc (ia64_setup_incoming_varargs): Likewise. + * config/loongarch/loongarch.cc + (loongarch_setup_incoming_varargs): Likewise. + * config/m32r/m32r.cc (m32r_setup_incoming_varargs): Likewise. + * config/mcore/mcore.cc (mcore_setup_incoming_varargs): Likewise. + * config/mips/mips.cc (mips_setup_incoming_varargs): Likewise. + * config/mmix/mmix.cc (mmix_setup_incoming_varargs): Likewise. + * config/nds32/nds32.cc (nds32_setup_incoming_varargs): Likewise. + * config/nios2/nios2.cc (nios2_setup_incoming_varargs): Likewise. + * config/riscv/riscv.cc (riscv_setup_incoming_varargs): Likewise. + * config/rs6000/rs6000-call.cc (setup_incoming_varargs): Likewise. + * config/sh/sh.cc (sh_setup_incoming_varargs): Likewise. + * config/visium/visium.cc (visium_setup_incoming_varargs): + Likewise. + * config/vms/vms-c.cc (vms_c_common_override_options): Do not set + flag_allow_parameterless_variadic_functions. + * doc/invoke.texi (-fallow-parameterless-variadic-functions): Do + not document option. + * function.cc (assign_parms): Call assign_parms_setup_varargs for + TYPE_NO_NAMED_ARGS_STDARG_P case. + * ginclude/stdarg.h [__STDC_VERSION__ > 201710L] (va_start): Make + variadic macro. Pass second argument of 0 to __builtin_va_start. + * target.def (setup_incoming_varargs): Update documentation. + * doc/tm.texi: Regenerate. + * tree-core.h (struct tree_type_common): Add + no_named_args_stdarg_p. + * tree-streamer-in.cc (unpack_ts_type_common_value_fields): Unpack + TYPE_NO_NAMED_ARGS_STDARG_P. + * tree-streamer-out.cc (pack_ts_type_common_value_fields): Pack + TYPE_NO_NAMED_ARGS_STDARG_P. + * tree.cc (type_cache_hasher::equal): Compare + TYPE_NO_NAMED_ARGS_STDARG_P. + (build_function_type): Add argument no_named_args_stdarg_p. + (build_function_type_list_1, build_function_type_array_1) + (reconstruct_complex_type): Update calls to build_function_type. + (stdarg_p, prototype_p): Return true for (...) functions. + (gimple_canonical_types_compatible_p): Compare + TYPE_NO_NAMED_ARGS_STDARG_P. + * tree.h (TYPE_NO_NAMED_ARGS_STDARG_P): New. + (build_function_type): Update prototype. + +2022-10-28 Andre Vieira + + PR tree-optimization/107346 + * tree-vect-data-refs.cc (vect_check_gather_scatter): Reject offsets + that aren't multiples of BITS_PER_UNIT. + +2022-10-28 Richard Biener + + PR tree-optimization/107407 + * tree-ssa-dse.cc (dse_classify_store): Perform backedge + varying index check when collecting PHI uses rather than + after optimizing processing of the candidate defs. + +2022-10-28 Richard Biener + + PR tree-optimization/107447 + * tree-ssa-loop-im.cc (determine_max_movement): Do not + hoist returns-twice calls. + +2022-10-28 Richard Biener + + PR tree-optimization/107435 + * tree-vect-loop.cc (vectorizable_recurr): Convert initial + value to vector component type. + +2022-10-28 Julian Brown + Thomas Schwinge + + PR middle-end/90115 + * omp-low.cc (oacc_privatization_candidate_p): Artificial vars are not + privatization candidates. + +2022-10-28 Martin Liska + + PR sanitizer/107298 + * doc/invoke.texi: Document sanitizers can trigger warnings. + +2022-10-28 Thomas Schwinge + + * doc/makefile.texi (Makefile Targets): Document + 'distclean-stage[N]'. + +2022-10-28 Aldy Hernandez + + * value-range.cc (range_tests_floats): Use HONOR_INFINITIES. + 2022-10-27 Eric Botcazou * config/aarch64/aarch64.h (DONT_USE_BUILTIN_SETJMP): Delete. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7109ae3..06511cc 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20221028 +20221029 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ee7b511..32e8fb1 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,20 @@ +2022-10-28 Joseph Myers + + * c-common.cc (def_fn_type): Call build_function_type for + zero-argument variable-argument function. + (c_common_nodes_and_builtins): Build default_function_type with + build_function_type. + * c.opt (fallow-parameterless-variadic-functions): Mark as ignored + option. + +2022-10-28 Joseph Myers + + PR c/61469 + * c-common.h (ENUM_UNDERLYING_TYPE, ENUM_FIXED_UNDERLYING_TYPE_P): + New. Moved from cp/cp-tree.h. + * c-warn.cc (warnings_for_convert_and_check): Do not consider + conversions to enum with underlying type bool to overflow. + 2022-10-26 Marek Polacek PR c++/106393 diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 2ac8eaa..4e71198 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,86 @@ +2022-10-28 Joseph Myers + + * c-decl.cc (grokdeclarator): Pass + arg_info->no_named_args_stdarg_p to build_function_type. + (grokparms): Check arg_info->no_named_args_stdarg_p before + converting () to (void). + (build_arg_info): Initialize no_named_args_stdarg_p. + (get_parm_info): Set no_named_args_stdarg_p. + (start_function): Pass TYPE_NO_NAMED_ARGS_STDARG_P to + build_function_type. + (store_parm_decls): Count (...) functions as prototyped. + * c-parser.cc (c_parser_direct_declarator): Allow '...' after open + parenthesis to start parameter list. + (c_parser_parms_list_declarator): Always allow '...' with no + arguments, call pedwarn_c11 and set no_named_args_stdarg_p. + * c-tree.h (struct c_arg_info): Add field no_named_args_stdarg_p. + * c-typeck.cc (composite_type): Handle + TYPE_NO_NAMED_ARGS_STDARG_P. + (function_types_compatible_p): Compare + TYPE_NO_NAMED_ARGS_STDARG_P. + +2022-10-28 Jakub Jelinek + + * c-parser.cc (c_parser_omp_all_clauses): Allow optional + comma before the first clause. + (c_parser_omp_allocate, c_parser_omp_atomic, c_parser_omp_depobj, + c_parser_omp_flush, c_parser_omp_scan_loop_body, + c_parser_omp_ordered, c_finish_omp_declare_variant, + c_parser_omp_declare_target, c_parser_omp_declare_reduction, + c_parser_omp_requires, c_parser_omp_error, + c_parser_omp_assumption_clauses): Likewise. + +2022-10-28 Joseph Myers + + PR c/61469 + * c-convert.cc (c_convert): Handle enums with underlying boolean + type like bool. + * c-decl.cc (shadow_tag_warned): Allow shadowing declarations for + enums with enum type specifier, but give errors for storage class + specifiers, qualifiers or alignment specifiers in non-definition + declarations of such enums. + (grokdeclarator): Give error for non-definition use of type + specifier with an enum type specifier. + (parser_xref_tag): Add argument has_enum_type_specifier. Pass it + to lookup_tag and use it to set ENUM_FIXED_UNDERLYING_TYPE_P. + (xref_tag): Update call to parser_xref_tag. + (start_enum): Add argument fixed_underlying_type. Complete enum + type with a fixed underlying type given in the definition. Give + error for defining without a fixed underlying type in the + definition if one was given in a prior declaration. Do not mark + enums with fixed underlying type as packed for -fshort-enums. + Store the enum type in the_enum. + (finish_enum): Do not adjust types of values or check their range + for an enum with a fixed underlying type. Set underlying type of + enum and variants. + (build_enumerator): Check enumeration constants for enum with + fixed underlying type against that type and convert to that type. + Increment in the underlying integer type, with handling for bool. + (c_simulate_enum_decl): Update call to start_enum. + (declspecs_add_type): Set specs->enum_type_specifier_ref_p. + * c-objc-common.cc (c_get_alias_set): Use ENUM_UNDERLYING_TYPE + rather than recomputing an underlying type based on size. + * c-parser.cc (c_parser_declspecs) + (c_parser_struct_or_union_specifier, c_parser_typeof_specifier): + Set has_enum_type_specifier for type specifiers. + (c_parser_enum_specifier): Handle enum type specifiers. + (c_parser_struct_or_union_specifier): Update call to + parser_xref_tag. + (c_parser_omp_atomic): Check for boolean increment or decrement + using C_BOOLEAN_TYPE_P. + * c-tree.h (C_BOOLEAN_TYPE_P): New. + (struct c_typespec): Add has_enum_type_specifier. + (struct c_declspecs): Add enum_type_specifier_ref_p. + (struct c_enum_contents): Add enum_type. + (start_enum, parser_xref_tag): Update prototypes. + * c-typeck.cc (composite_type): Allow for enumerated types + compatible with bool. + (common_type, comptypes_internal, perform_integral_promotions): + Use ENUM_UNDERLYING_TYPE. + (parser_build_binary_op, build_unary_op, convert_for_assignment) + (c_finish_return, c_start_switch, build_binary_op): Check for + boolean types using C_BOOLEAN_TYPE_P. + 2022-10-24 Jakub Jelinek PR c++/107358 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d065fd1..82629ef 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,29 @@ +2022-10-28 Marek Polacek + + * call.cc (maybe_warn_dangling_reference): Enable the warning in + system headers if the decl isn't in a system header. + +2022-10-28 Jason Merrill + + * decl.cc (grokdeclarator): Call decl_attributes before do_friend. + +2022-10-28 Jakub Jelinek + + * parser.cc (cp_parser_omp_all_clauses): Allow optional comma + before the first clause even in pragma syntax. + (cp_parser_omp_allocate, cp_parser_omp_atomic, cp_parser_omp_depobj, + cp_parser_omp_flush, cp_parser_omp_scan_loop_body, + cp_parser_omp_ordered, cp_parser_omp_assumption_clauses, + cp_finish_omp_declare_variant, cp_parser_omp_declare_target, + cp_parser_omp_declare_reduction_exprs, cp_parser_omp_requires, + cp_parser_omp_error): Likewise. + +2022-10-28 Joseph Myers + + PR c/61469 + * cp-tree.h (ENUM_FIXED_UNDERLYING_TYPE_P, ENUM_UNDERLYING_TYPE): + Remove. Moved to c-common.h. + 2022-10-27 Jakub Jelinek PR c++/107379 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 1ca82cd..7b2d93b 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,8 @@ +2022-10-28 Joseph Myers + + * trans-types.cc (gfc_get_function_type): Do not use + build_varargs_function_type_vec for unprototyped function. + 2022-10-26 Harald Anlauf PR fortran/103413 diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index e36fa44..b350d50 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,16 @@ +2022-10-28 Joseph Myers + + * lto-common.cc (compare_tree_sccs_1): Compare + TYPE_NO_NAMED_ARGS_STDARG_P. + +2022-10-28 Martin Liska + + * lto-dump.cc (dump_list): Remove trailing return. + (dump_symbol): Likewise. + (dump_body): Filter name based on mangled name. + (dump_tool_help): Use GIMPLE wording. + (lto_main): Update wording. + 2022-10-27 Martin Liska PR lto/107418 diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index a83c3c7..2584520 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2022-10-28 Joseph Myers + + * objc-next-runtime-abi-01.cc (build_next_objc_exception_stuff): + Use build_function_type to build type of objc_setjmp_decl. + 2022-10-07 Martin Liska * objc-gnu-runtime-abi-01.cc (generate_static_references): diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 83d372a..90c3b92 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,74 @@ +2022-10-28 Marek Polacek + + * g++.dg/warn/Wdangling-reference4.C: New test. + +2022-10-28 Joseph Myers + + * gcc.dg/c11-stdarg-1.c, gcc.dg/c11-stdarg-2.c, + gcc.dg/c11-stdarg-3.c, gcc.dg/c2x-stdarg-1.c, + gcc.dg/c2x-stdarg-2.c, gcc.dg/c2x-stdarg-3.c, + gcc.dg/c2x-stdarg-4.c, gcc.dg/gnu2x-stdarg-1.c, + gcc.dg/torture/c2x-stdarg-split-1a.c, + gcc.dg/torture/c2x-stdarg-split-1b.c: New tests. + * gcc.dg/Wold-style-definition-2.c, gcc.dg/format/sentinel-1.c: + Update expected diagnostics. + * gcc.dg/c2x-nullptr-1.c (test5): Cast unused parameter to (void). + * gcc.dg/diagnostic-token-ranges.c: Use -pedantic. Expect warning + in place of error. + +2022-10-28 Richard Biener + + PR tree-optimization/107407 + * gcc.dg/torture/pr107407.c: New testcase. + +2022-10-28 Richard Biener + + PR tree-optimization/107447 + * gcc.dg/torture/pr107447.c: New testcase. + +2022-10-28 Richard Biener + + PR tree-optimization/107435 + * gcc.dg/torture/pr107435.c: New testcase. + +2022-10-28 Jakub Jelinek + + * c-c++-common/gomp/directive-1.c: New test. + * c-c++-common/gomp/clauses-6.c: New test. + * c-c++-common/gomp/declare-variant-2.c (f75a): Declare. + (f75): Use f75a as variant instead of f1 and don't expect error. + * g++.dg/gomp/clause-4.C (foo): Don't expect error on comma + before first clause. + * gcc.dg/gomp/clause-2.c (foo): Likewise. + +2022-10-28 Richard Biener + + * gcc.dg/vect/pr100756.c: Adjust for larger vectors. + +2022-10-28 Thomas Schwinge + + * gcc.dg/vect/bb-slp-cond-1.c: Fix target selector syntax. + +2022-10-28 Kewen Lin + + PR testsuite/107240 + * gcc.dg/vect/vect-bitfield-read-1.c: Add effective target checking + vect_shift. + * gcc.dg/vect/vect-bitfield-read-3.c: Likewise. + * gcc.dg/vect/vect-bitfield-read-5.c: Likewise. + * gcc.dg/vect/vect-bitfield-read-6.c: Likewise. + * gcc.dg/vect/vect-bitfield-read-7.c: Likewise. + * gcc.dg/vect/vect-bitfield-read-2.c: Add effective target checking + vect_shift and replace vect_int with vect_long_long. + * gcc.dg/vect/vect-bitfield-read-4.c: Likewise. + +2022-10-28 Joseph Myers + + PR c/61469 + * gcc.dg/c11-enum-4.c, gcc.dg/c11-enum-5.c, gcc.dg/c11-enum-6.c, + gcc.dg/c2x-enum-6.c, gcc.dg/c2x-enum-7.c, gcc.dg/c2x-enum-8.c, + gcc.dg/gnu2x-enum-1.c: New tests. + 2022-10-27 H.J. Lu PR target/107172 -- cgit v1.1 From 724d3f926b94672de960dbe88fb699bbdd7fde97 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 28 Oct 2022 23:33:06 -0400 Subject: Fix signed vs unsigned issue in H8 port gcc/ * config/h8300/h8300.cc (pre_incdec_with_reg): Make reg argument an unsigned int * config/h8300/h8300-protos.h (pre_incdec_with_reg): Adjust prototype. --- gcc/config/h8300/h8300-protos.h | 2 +- gcc/config/h8300/h8300.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 8c98949..77adfab 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -100,7 +100,7 @@ extern int h8300_initial_elimination_offset (int, int); extern int h8300_regs_ok_for_stm (int, rtx[]); extern int h8300_hard_regno_rename_ok (unsigned int, unsigned int); extern bool h8300_move_ok (rtx, rtx); -extern bool pre_incdec_with_reg (rtx, int); +extern bool pre_incdec_with_reg (rtx, unsigned int); struct cpp_reader; extern void h8300_pr_interrupt (struct cpp_reader *); diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc index ce0702e..cd7975e 100644 --- a/gcc/config/h8300/h8300.cc +++ b/gcc/config/h8300/h8300.cc @@ -5536,7 +5536,7 @@ h8300_ok_for_sibcall_p (tree fndecl, tree) instruction using REG, FALSE otherwise. */ bool -pre_incdec_with_reg (rtx op, int reg) +pre_incdec_with_reg (rtx op, unsigned int reg) { /* OP must be a MEM. */ if (GET_CODE (op) != MEM) -- cgit v1.1 From ca652f86f79855830762e2e7680b6807798437bf Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 17 Oct 2022 19:32:52 +0200 Subject: d: Remove D-specific version definitions from target headers This splits up the targetdm sources so that each file only handles one target platform. Having all logic kept in the headers means that they could become out of sync when a new target is added (loongarch*-*-linux*) or accidentally broken if some headers in tm_file are changed about. gcc/ChangeLog: * config.gcc: Split out glibc-d.o into linux-d.o, kfreebsd-d.o, kopensolaris-d.o, and gnu-d.o. Split out cygwin-d.o from winnt-d.o. * config/arm/linux-eabi.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. * config/gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Remove. * config/i386/cygwin.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. * config/i386/linux-common.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. * config/i386/mingw32.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. * config/i386/t-cygming: Add cygwin-d.o. * config/i386/winnt-d.cc (winnt_d_os_builtins): Only add MinGW-specific version condition. * config/kfreebsd-gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Remove. * config/kopensolaris-gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Remove. * config/linux-android.h (ANDROID_TARGET_D_OS_VERSIONS): Remove. * config/linux.h (GNU_USER_TARGET_D_OS_VERSIONS): Remove. * config/mips/linux-common.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. * config/t-glibc: Remove glibc-d.o, add gnu-d.o, kfreebsd-d.o, kopensolaris-d.o. * config/t-linux: Add linux-d.o. * config/glibc-d.cc: Remove file. * config/gnu-d.cc: New file. * config/i386/cygwin-d.cc: New file. * config/kfreebsd-d.cc: New file. * config/kopensolaris-d.cc: New file. * config/linux-d.cc: New file. --- gcc/config.gcc | 24 ++++++++++-- gcc/config/arm/linux-eabi.h | 3 -- gcc/config/glibc-d.cc | 73 ------------------------------------- gcc/config/gnu-d.cc | 65 +++++++++++++++++++++++++++++++++ gcc/config/gnu.h | 6 --- gcc/config/i386/cygwin-d.cc | 83 ++++++++++++++++++++++++++++++++++++++++++ gcc/config/i386/cygwin.h | 9 ----- gcc/config/i386/linux-common.h | 3 -- gcc/config/i386/mingw32.h | 12 ------ gcc/config/i386/t-cygming | 4 ++ gcc/config/i386/winnt-d.cc | 10 +++-- gcc/config/kfreebsd-d.cc | 65 +++++++++++++++++++++++++++++++++ gcc/config/kfreebsd-gnu.h | 6 --- gcc/config/kopensolaris-d.cc | 65 +++++++++++++++++++++++++++++++++ gcc/config/kopensolaris-gnu.h | 6 --- gcc/config/linux-android.h | 6 --- gcc/config/linux-d.cc | 78 +++++++++++++++++++++++++++++++++++++++ gcc/config/linux.h | 13 ------- gcc/config/mips/linux-common.h | 3 -- gcc/config/t-glibc | 10 ++++- gcc/config/t-linux | 4 ++ 21 files changed, 399 insertions(+), 149 deletions(-) delete mode 100644 gcc/config/glibc-d.cc create mode 100644 gcc/config/gnu-d.cc create mode 100644 gcc/config/i386/cygwin-d.cc create mode 100644 gcc/config/kfreebsd-d.cc create mode 100644 gcc/config/kopensolaris-d.cc create mode 100644 gcc/config/linux-d.cc (limited to 'gcc') diff --git a/gcc/config.gcc b/gcc/config.gcc index e8fe623..ac1c08f 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -882,10 +882,8 @@ case ${target} in esac c_target_objs="${c_target_objs} glibc-c.o" cxx_target_objs="${cxx_target_objs} glibc-c.o" - d_target_objs="${d_target_objs} glibc-d.o" tmake_file="${tmake_file} t-glibc" target_has_targetcm=yes - target_has_targetdm=yes case $target in *-*-*uclibc* | *-*-uclinuxfdpiceabi) ;; @@ -894,6 +892,24 @@ case ${target} in gcc_cv_initfini_array=yes ;; esac + case $target in + *-*-*linux*) + d_target_objs="${d_target_objs} linux-d.o" + target_has_targetdm=yes + ;; + *-*-kfreebsd*-gnu) + d_target_objs="${d_target_objs} kfreebsd-d.o" + target_has_targetdm=yes + ;; + *-*-kopensolaris*-gnu) + d_target_objs="${d_target_objs} kopensolaris-d.o" + target_has_targetdm=yes + ;; + *-*-gnu*) + d_target_objs="${d_target_objs} gnu-d.o" + target_has_targetdm=yes + ;; + esac ;; *-*-netbsd*) tm_p_file="${tm_p_file} netbsd-protos.h" @@ -2054,7 +2070,7 @@ i[34567]86-*-cygwin*) extra_objs="${extra_objs} winnt.o winnt-stubs.o" c_target_objs="${c_target_objs} msformat-c.o" cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o" - d_target_objs="${d_target_objs} winnt-d.o" + d_target_objs="${d_target_objs} cygwin-d.o" target_has_targetdm="yes" if test x$enable_threads = xyes; then thread_file='posix' @@ -2072,7 +2088,7 @@ x86_64-*-cygwin*) extra_objs="${extra_objs} winnt.o winnt-stubs.o" c_target_objs="${c_target_objs} msformat-c.o" cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o" - d_target_objs="${d_target_objs} winnt-d.o" + d_target_objs="${d_target_objs} cygwin-d.o" target_has_targetdm="yes" if test x$enable_threads = xyes; then thread_file='posix' diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h index 50cc0bc..6d803ce 100644 --- a/gcc/config/arm/linux-eabi.h +++ b/gcc/config/arm/linux-eabi.h @@ -30,9 +30,6 @@ } \ while (false) -#define EXTRA_TARGET_D_OS_VERSIONS() \ - ANDROID_TARGET_D_OS_VERSIONS(); - /* We default to a soft-float ABI so that binaries can run on all target hardware. If you override this to use the hard-float ABI then change the setting of GLIBC_DYNAMIC_LINKER_DEFAULT as well. */ diff --git a/gcc/config/glibc-d.cc b/gcc/config/glibc-d.cc deleted file mode 100644 index 1411f19..0000000 --- a/gcc/config/glibc-d.cc +++ /dev/null @@ -1,73 +0,0 @@ -/* Glibc support needed only by D front-end. - Copyright (C) 2017-2022 Free Software Foundation, Inc. - -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 -. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "tm_d.h" -#include "d/d-target.h" -#include "d/d-target-def.h" - -/* Implement TARGET_D_OS_VERSIONS for Glibc targets. */ - -static void -glibc_d_os_builtins (void) -{ - d_add_builtin_version ("Posix"); - -#define builtin_version(TXT) d_add_builtin_version (TXT) - -#ifdef GNU_USER_TARGET_D_OS_VERSIONS - GNU_USER_TARGET_D_OS_VERSIONS (); -#endif - -#ifdef EXTRA_TARGET_D_OS_VERSIONS - EXTRA_TARGET_D_OS_VERSIONS (); -#endif -} - -/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ - -static tree -glibc_d_handle_target_object_format (void) -{ - const char *objfmt = "elf"; - - return build_string_literal (strlen (objfmt) + 1, objfmt); -} - -/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Glibc targets. */ - -static void -glibc_d_register_target_info (void) -{ - const struct d_target_info_spec handlers[] = { - { "objectFormat", glibc_d_handle_target_object_format }, - { NULL, NULL }, - }; - - d_add_target_info_handlers (handlers); -} - -#undef TARGET_D_OS_VERSIONS -#define TARGET_D_OS_VERSIONS glibc_d_os_builtins - -#undef TARGET_D_REGISTER_OS_TARGET_INFO -#define TARGET_D_REGISTER_OS_TARGET_INFO glibc_d_register_target_info - -struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/gnu-d.cc b/gcc/config/gnu-d.cc new file mode 100644 index 0000000..1c0dff2 --- /dev/null +++ b/gcc/config/gnu-d.cc @@ -0,0 +1,65 @@ +/* GNU system support needed only by D front-end. + Copyright (C) 2017-2022 Free Software Foundation, Inc. + +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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tm_d.h" +#include "d/d-target.h" +#include "d/d-target-def.h" + +/* Implement TARGET_D_OS_VERSIONS for GNU targets. */ + +static void +gnu_d_os_builtins (void) +{ + d_add_builtin_version ("Posix"); + d_add_builtin_version ("Hurd"); + d_add_builtin_version ("CRuntime_Glibc"); +} + +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +gnu_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for GNU targets. */ + +static void +gnu_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", gnu_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + +#undef TARGET_D_OS_VERSIONS +#define TARGET_D_OS_VERSIONS gnu_d_os_builtins + +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO gnu_d_register_target_info + +struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/gnu.h b/gcc/config/gnu.h index de2ead8..e8d7246 100644 --- a/gcc/config/gnu.h +++ b/gcc/config/gnu.h @@ -31,9 +31,3 @@ along with GCC. If not, see . builtin_assert ("system=unix"); \ builtin_assert ("system=posix"); \ } while (0) - -#define GNU_USER_TARGET_D_OS_VERSIONS() \ - do { \ - builtin_version ("Hurd"); \ - builtin_version ("CRuntime_Glibc"); \ - } while (0) diff --git a/gcc/config/i386/cygwin-d.cc b/gcc/config/i386/cygwin-d.cc new file mode 100644 index 0000000..619930b --- /dev/null +++ b/gcc/config/i386/cygwin-d.cc @@ -0,0 +1,83 @@ +/* Cygwin support needed only by D front-end. + Copyright (C) 2021-2022 Free Software Foundation, Inc. + +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 +. */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tm_d.h" +#include "d/d-target.h" +#include "d/d-target-def.h" + +/* Implement TARGET_D_OS_VERSIONS for Cygwin targets. */ + +static void +cygwin_d_os_builtins (void) +{ + d_add_builtin_version ("Windows"); + d_add_builtin_version ("Cygwin"); + d_add_builtin_version ("Posix"); + d_add_builtin_version ("CRuntime_Newlib"); +} + +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +cygwin_d_handle_target_object_format (void) +{ + const char *objfmt = "coff"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Cygwin targets. */ + +static void +cygwin_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", cygwin_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} +#undef TARGET_D_OS_VERSIONS +#define TARGET_D_OS_VERSIONS cygwin_d_os_builtins + +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO cygwin_d_register_target_info + +/* Define TARGET_D_MINFO_SECTION for Cygwin targets. */ + +#undef TARGET_D_MINFO_SECTION +#define TARGET_D_MINFO_SECTION "minfo" + +#undef TARGET_D_MINFO_START_NAME +#define TARGET_D_MINFO_START_NAME "__start_minfo" + +#undef TARGET_D_MINFO_END_NAME +#define TARGET_D_MINFO_END_NAME "__stop_minfo" + +/* Define TARGET_D_TEMPLATES_ALWAYS_COMDAT for Cygwin targets. */ + +#undef TARGET_D_TEMPLATES_ALWAYS_COMDAT +#define TARGET_D_TEMPLATES_ALWAYS_COMDAT true + +struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h index d06eda3..0a604d6 100644 --- a/gcc/config/i386/cygwin.h +++ b/gcc/config/i386/cygwin.h @@ -29,15 +29,6 @@ along with GCC; see the file COPYING3. If not see } \ while (0) -#define EXTRA_TARGET_D_OS_VERSIONS() \ - do \ - { \ - builtin_version ("Cygwin"); \ - builtin_version ("Posix"); \ - builtin_version ("CRuntime_Newlib"); \ - } \ - while (0) - #undef CPP_SPEC #define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} \ %{!ansi:-Dunix} \ diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h index efa7fb2..53cf86f 100644 --- a/gcc/config/i386/linux-common.h +++ b/gcc/config/i386/linux-common.h @@ -27,9 +27,6 @@ along with GCC; see the file COPYING3. If not see } \ while (0) -#define EXTRA_TARGET_D_OS_VERSIONS() \ - ANDROID_TARGET_D_OS_VERSIONS(); - #undef CC1_SPEC #define CC1_SPEC \ LINUX_OR_ANDROID_CC (GNU_USER_TARGET_CC1_SPEC, \ diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h index b5f31c3..19a98c3 100644 --- a/gcc/config/i386/mingw32.h +++ b/gcc/config/i386/mingw32.h @@ -59,18 +59,6 @@ along with GCC; see the file COPYING3. If not see } \ while (0) -#define EXTRA_TARGET_D_OS_VERSIONS() \ - do \ - { \ - builtin_version ("MinGW"); \ - if (TARGET_64BIT && ix86_abi == MS_ABI) \ - builtin_version ("Win64"); \ - else if (!TARGET_64BIT) \ - builtin_version ("Win32"); \ - builtin_version ("CRuntime_Microsoft"); \ - } \ - while (0) - #ifndef TARGET_USE_PTHREAD_BY_DEFAULT #define SPEC_PTHREAD1 "pthread" #define SPEC_PTHREAD2 "!no-pthread" diff --git a/gcc/config/i386/t-cygming b/gcc/config/i386/t-cygming index d4803de..f892c27 100644 --- a/gcc/config/i386/t-cygming +++ b/gcc/config/i386/t-cygming @@ -39,6 +39,10 @@ winnt-stubs.o: $(srcdir)/config/i386/winnt-stubs.cc $(CONFIG_H) $(SYSTEM_H) core $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/i386/winnt-stubs.cc +cygwin-d.o: $(srcdir)/config/i386/cygwin-d.cc + $(COMPILE) $< + $(POSTCOMPILE) + winnt-d.o: $(srcdir)/config/i386/winnt-d.cc $(COMPILE) $< $(POSTCOMPILE) diff --git a/gcc/config/i386/winnt-d.cc b/gcc/config/i386/winnt-d.cc index 00c28c3..a1fd3fa 100644 --- a/gcc/config/i386/winnt-d.cc +++ b/gcc/config/i386/winnt-d.cc @@ -31,12 +31,14 @@ static void winnt_d_os_builtins (void) { d_add_builtin_version ("Windows"); + d_add_builtin_version ("MinGW"); -#define builtin_version(TXT) d_add_builtin_version (TXT) + if (TARGET_64BIT && ix86_abi == MS_ABI) + d_add_builtin_version ("Win64"); + else if (!TARGET_64BIT) + d_add_builtin_version ("Win32"); -#ifdef EXTRA_TARGET_D_OS_VERSIONS - EXTRA_TARGET_D_OS_VERSIONS (); -#endif + d_add_builtin_version ("CRuntime_Microsoft"); } /* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ diff --git a/gcc/config/kfreebsd-d.cc b/gcc/config/kfreebsd-d.cc new file mode 100644 index 0000000..0bfa6bd --- /dev/null +++ b/gcc/config/kfreebsd-d.cc @@ -0,0 +1,65 @@ +/* kFreeBSD-based GNU systems support needed only by D front-end. + Copyright (C) 2017-2022 Free Software Foundation, Inc. + +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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tm_d.h" +#include "d/d-target.h" +#include "d/d-target-def.h" + +/* Implement TARGET_D_OS_VERSIONS for kFreeBSD targets. */ + +static void +kfreebsd_d_os_builtins (void) +{ + d_add_builtin_version ("Posix"); + d_add_builtin_version ("FreeBSD"); + d_add_builtin_version ("CRuntime_Glibc"); +} + +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +kfreebsd_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for kFreeBSD targets. */ + +static void +kfreebsd_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", kfreebsd_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + +#undef TARGET_D_OS_VERSIONS +#define TARGET_D_OS_VERSIONS kfreebsd_d_os_builtins + +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO kfreebsd_d_register_target_info + +struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/kfreebsd-gnu.h b/gcc/config/kfreebsd-gnu.h index f74a627..c28fcaf 100644 --- a/gcc/config/kfreebsd-gnu.h +++ b/gcc/config/kfreebsd-gnu.h @@ -29,12 +29,6 @@ along with GCC; see the file COPYING3. If not see } \ while (0) -#define GNU_USER_TARGET_D_OS_VERSIONS() \ - do { \ - builtin_version ("FreeBSD"); \ - builtin_version ("CRuntime_Glibc"); \ - } while (0) - #define GNU_USER_DYNAMIC_LINKER GLIBC_DYNAMIC_LINKER #define GNU_USER_DYNAMIC_LINKER32 GLIBC_DYNAMIC_LINKER32 #define GNU_USER_DYNAMIC_LINKER64 GLIBC_DYNAMIC_LINKER64 diff --git a/gcc/config/kopensolaris-d.cc b/gcc/config/kopensolaris-d.cc new file mode 100644 index 0000000..197471a --- /dev/null +++ b/gcc/config/kopensolaris-d.cc @@ -0,0 +1,65 @@ +/* kOpenSolaris-based GNU systems support needed only by D front-end. + Copyright (C) 2017-2022 Free Software Foundation, Inc. + +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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tm_d.h" +#include "d/d-target.h" +#include "d/d-target-def.h" + +/* Implement TARGET_D_OS_VERSIONS for kOpenSolaris targets. */ + +static void +kopensolaris_d_os_builtins (void) +{ + d_add_builtin_version ("Posix"); + d_add_builtin_version ("Solaris"); + d_add_builtin_version ("CRuntime_Glibc"); +} + +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +kopensolaris_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for kOpenSolaris targets. */ + +static void +kopensolaris_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", kopensolaris_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + +#undef TARGET_D_OS_VERSIONS +#define TARGET_D_OS_VERSIONS kopensolaris_d_os_builtins + +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO kopensolaris_d_register_target_info + +struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/kopensolaris-gnu.h b/gcc/config/kopensolaris-gnu.h index 8379f96..3929d4b 100644 --- a/gcc/config/kopensolaris-gnu.h +++ b/gcc/config/kopensolaris-gnu.h @@ -30,11 +30,5 @@ along with GCC; see the file COPYING3. If not see } \ while (0) -#define GNU_USER_TARGET_D_OS_VERSIONS() \ - do { \ - builtin_version ("Solaris"); \ - builtin_version ("CRuntime_Glibc"); \ - } while (0) - #undef GNU_USER_DYNAMIC_LINKER #define GNU_USER_DYNAMIC_LINKER "/lib/ld.so.1" diff --git a/gcc/config/linux-android.h b/gcc/config/linux-android.h index cf34066..f335cea 100644 --- a/gcc/config/linux-android.h +++ b/gcc/config/linux-android.h @@ -25,12 +25,6 @@ builtin_define ("__ANDROID__"); \ } while (0) -#define ANDROID_TARGET_D_OS_VERSIONS() \ - do { \ - if (TARGET_ANDROID) \ - builtin_version ("Android"); \ - } while (0) - #if ANDROID_DEFAULT # define NOANDROID "mno-android" #else diff --git a/gcc/config/linux-d.cc b/gcc/config/linux-d.cc new file mode 100644 index 0000000..f2ef2f0 --- /dev/null +++ b/gcc/config/linux-d.cc @@ -0,0 +1,78 @@ +/* Linux support needed only by D front-end. + Copyright (C) 2017-2022 Free Software Foundation, Inc. + +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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tm_d.h" +#include "d/d-target.h" +#include "d/d-target-def.h" + +/* Implement TARGET_D_OS_VERSIONS for Linux targets. */ + +static void +linux_d_os_builtins (void) +{ + d_add_builtin_version ("Posix"); + + d_add_builtin_version ("linux"); +#ifdef TARGET_ANDROID + if (TARGET_ANDROID) + d_add_builtin_version ("Android"); +#endif + + if (OPTION_GLIBC) + d_add_builtin_version ("CRuntime_Glibc"); + else if (OPTION_UCLIBC) + d_add_builtin_version ("CRuntime_UClibc"); + else if (OPTION_BIONIC) + d_add_builtin_version ("CRuntime_Bionic"); + else if (OPTION_MUSL) + d_add_builtin_version ("CRuntime_Musl"); +} + +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +linux_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Linux targets. */ + +static void +linux_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", linux_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + +#undef TARGET_D_OS_VERSIONS +#define TARGET_D_OS_VERSIONS linux_d_os_builtins + +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO linux_d_register_target_info + +struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/linux.h b/gcc/config/linux.h index 74f7079..d1d6753 100644 --- a/gcc/config/linux.h +++ b/gcc/config/linux.h @@ -58,19 +58,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see builtin_assert ("system=posix"); \ } while (0) -#define GNU_USER_TARGET_D_OS_VERSIONS() \ - do { \ - builtin_version ("linux"); \ - if (OPTION_GLIBC) \ - builtin_version ("CRuntime_Glibc"); \ - else if (OPTION_UCLIBC) \ - builtin_version ("CRuntime_UClibc"); \ - else if (OPTION_BIONIC) \ - builtin_version ("CRuntime_Bionic"); \ - else if (OPTION_MUSL) \ - builtin_version ("CRuntime_Musl"); \ - } while (0) - /* Determine which dynamic linker to use depending on whether GLIBC or uClibc or Bionic or musl is the default C library and whether -muclibc or -mglibc or -mbionic or -mmusl has been passed to change diff --git a/gcc/config/mips/linux-common.h b/gcc/config/mips/linux-common.h index cf7713b..b29f4aa 100644 --- a/gcc/config/mips/linux-common.h +++ b/gcc/config/mips/linux-common.h @@ -27,9 +27,6 @@ along with GCC; see the file COPYING3. If not see ANDROID_TARGET_OS_CPP_BUILTINS(); \ } while (0) -#define EXTRA_TARGET_D_OS_VERSIONS() \ - ANDROID_TARGET_D_OS_VERSIONS(); - #undef LINK_SPEC #define LINK_SPEC \ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_LINK_SPEC, \ diff --git a/gcc/config/t-glibc b/gcc/config/t-glibc index c8b7d4e..f26c37a 100644 --- a/gcc/config/t-glibc +++ b/gcc/config/t-glibc @@ -20,6 +20,14 @@ glibc-c.o: config/glibc-c.cc $(COMPILE) $< $(POSTCOMPILE) -glibc-d.o: config/glibc-d.cc +gnu-d.o: config/gnu-d.cc + $(COMPILE) $< + $(POSTCOMPILE) + +kfreebsd-d.o: config/kfreebsd-d.cc + $(COMPILE) $< + $(POSTCOMPILE) + +kopensolaris-d.o: config/kopensolaris-d.cc $(COMPILE) $< $(POSTCOMPILE) diff --git a/gcc/config/t-linux b/gcc/config/t-linux index d9bc9b8..830b987 100644 --- a/gcc/config/t-linux +++ b/gcc/config/t-linux @@ -19,3 +19,7 @@ linux.o: $(srcdir)/config/linux.cc $(COMPILE) $< $(POSTCOMPILE) + +linux-d.o: $(srcdir)/config/linux-d.cc + $(COMPILE) $< + $(POSTCOMPILE) -- cgit v1.1 From eaa59f085e8854a5cf082179c5f8c97e5efc9b6c Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 23 Oct 2022 14:09:17 +0200 Subject: d: Make TARGET_D_MINFO_SECTION hooks in elfos.h the language default. Removes the last of all TARGET_D_* macro definitions in common target headers. Now everything is either defined in the D language front-end, or D-specific target headers. gcc/ChangeLog: * config/darwin-d.cc (TARGET_D_MINFO_START_NAME): Rename to ... (TARGET_D_MINFO_SECTION_START): ...this. (TARGET_D_MINFO_END_NAME): Rename to ... (TARGET_D_MINFO_SECTION_END): ... this. * config/elfos.h (TARGET_D_MINFO_SECTION): Remove. (TARGET_D_MINFO_START_NAME): Remove. (TARGET_D_MINFO_END_NAME): Remove. * config/i386/cygwin-d.cc (TARGET_D_MINFO_SECTION): Remove. (TARGET_D_MINFO_START_NAME): Remove. (TARGET_D_MINFO_END_NAME): Remove. * config/i386/winnt-d.cc (TARGET_D_MINFO_SECTION): Remove. (TARGET_D_MINFO_START_NAME): Remove. (TARGET_D_MINFO_END_NAME): Remove. * doc/tm.texi: Regenerate. * doc/tm.texi.in (TARGET_D_MINFO_START_NAME): Rename to ... (TARGET_D_MINFO_SECTION_START): ...this. (TARGET_D_MINFO_END_NAME): Rename to ... (TARGET_D_MINFO_SECTION_END): ...this. gcc/d/ChangeLog: * d-target.def (d_minfo_section): Expand documentation of hook. Default initialize to "minfo". (d_minfo_start_name): Rename to ... (d_minfo_section_start): ... this. Default initialize to "__start_minfo". (d_minfo_end_name): Rename to ... (d_minfo_section_end): ... this. Default initialize to "__stop_minfo". * modules.cc (register_moduleinfo): Use new targetdm hook names. --- gcc/config/darwin-d.cc | 8 ++++---- gcc/config/elfos.h | 6 ------ gcc/config/i386/cygwin-d.cc | 11 ----------- gcc/config/i386/winnt-d.cc | 11 ----------- gcc/d/d-target.def | 23 +++++++++++++---------- gcc/d/modules.cc | 4 ++-- gcc/doc/tm.texi | 16 ++++++++++------ gcc/doc/tm.texi.in | 4 ++-- 8 files changed, 31 insertions(+), 52 deletions(-) (limited to 'gcc') diff --git a/gcc/config/darwin-d.cc b/gcc/config/darwin-d.cc index 2ceebc4..9730494 100644 --- a/gcc/config/darwin-d.cc +++ b/gcc/config/darwin-d.cc @@ -67,10 +67,10 @@ darwin_d_register_target_info (void) #undef TARGET_D_MINFO_SECTION #define TARGET_D_MINFO_SECTION "__DATA,__minfodata" -#undef TARGET_D_MINFO_START_NAME -#define TARGET_D_MINFO_START_NAME "*section$start$__DATA$__minfodata" +#undef TARGET_D_MINFO_SECTION_START +#define TARGET_D_MINFO_SECTION_START "*section$start$__DATA$__minfodata" -#undef TARGET_D_MINFO_END_NAME -#define TARGET_D_MINFO_END_NAME "*section$end$__DATA$__minfodata" +#undef TARGET_D_MINFO_SECTION_END +#define TARGET_D_MINFO_SECTION_END "*section$end$__DATA$__minfodata" struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h index acb3762..f8b3be4 100644 --- a/gcc/config/elfos.h +++ b/gcc/config/elfos.h @@ -482,9 +482,3 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #undef TARGET_LIBC_HAS_FUNCTION #define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function - -/* ELF support needed only by D front-end. */ - -#define TARGET_D_MINFO_SECTION "minfo" -#define TARGET_D_MINFO_START_NAME "__start_minfo" -#define TARGET_D_MINFO_END_NAME "__stop_minfo" diff --git a/gcc/config/i386/cygwin-d.cc b/gcc/config/i386/cygwin-d.cc index 619930b..6d70d49 100644 --- a/gcc/config/i386/cygwin-d.cc +++ b/gcc/config/i386/cygwin-d.cc @@ -64,17 +64,6 @@ cygwin_d_register_target_info (void) #undef TARGET_D_REGISTER_OS_TARGET_INFO #define TARGET_D_REGISTER_OS_TARGET_INFO cygwin_d_register_target_info -/* Define TARGET_D_MINFO_SECTION for Cygwin targets. */ - -#undef TARGET_D_MINFO_SECTION -#define TARGET_D_MINFO_SECTION "minfo" - -#undef TARGET_D_MINFO_START_NAME -#define TARGET_D_MINFO_START_NAME "__start_minfo" - -#undef TARGET_D_MINFO_END_NAME -#define TARGET_D_MINFO_END_NAME "__stop_minfo" - /* Define TARGET_D_TEMPLATES_ALWAYS_COMDAT for Cygwin targets. */ #undef TARGET_D_TEMPLATES_ALWAYS_COMDAT diff --git a/gcc/config/i386/winnt-d.cc b/gcc/config/i386/winnt-d.cc index a1fd3fa..843c713 100644 --- a/gcc/config/i386/winnt-d.cc +++ b/gcc/config/i386/winnt-d.cc @@ -69,17 +69,6 @@ winnt_d_register_target_info (void) #undef TARGET_D_REGISTER_OS_TARGET_INFO #define TARGET_D_REGISTER_OS_TARGET_INFO winnt_d_register_target_info -/* Define TARGET_D_MINFO_SECTION for Windows targets. */ - -#undef TARGET_D_MINFO_SECTION -#define TARGET_D_MINFO_SECTION "minfo" - -#undef TARGET_D_MINFO_START_NAME -#define TARGET_D_MINFO_START_NAME "__start_minfo" - -#undef TARGET_D_MINFO_END_NAME -#define TARGET_D_MINFO_END_NAME "__stop_minfo" - /* Define TARGET_D_TEMPLATES_ALWAYS_COMDAT for Windows targets. */ #undef TARGET_D_TEMPLATES_ALWAYS_COMDAT diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def index 7805942..7d999d0 100644 --- a/gcc/d/d-target.def +++ b/gcc/d/d-target.def @@ -70,26 +70,29 @@ the target operating system.", DEFHOOKPOD (d_minfo_section, "Contains the name of the section in which module info references should be\n\ -placed. This section is expected to be bracketed by two symbols to indicate\n\ -the start and end address of the section, so that the runtime library can\n\ -collect all modules for each loaded shared library and executable. The\n\ -default value of @code{NULL} disables the use of sections altogether.", - const char *, NULL) +placed. By default, the compiler puts all module info symbols in the\n\ +@code{\"minfo\"} section. Define this macro to override the string if a\n\ +different section name should be used. This section is expected to be\n\ +bracketed by two symbols @code{TARGET_D_MINFO_SECTION_START} and \n\ +@code{TARGET_D_MINFO_SECTION_END} to indicate the start and end address of\n\ +the section, so that the runtime library can collect all modules for each\n\ +loaded shared library and executable. Setting the value to @code{NULL}\n\ +disables the use of sections for storing module info altogether.", + const char *, "minfo") DEFHOOKPOD -(d_minfo_start_name, +(d_minfo_section_start, "If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined\n\ as the name of the symbol indicating the start address of the module info\n\ section", - const char *, NULL) + const char *, "__start_minfo") -/* The name of the ModuleInfo section. */ DEFHOOKPOD -(d_minfo_end_name, +(d_minfo_section_end, "If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined\n\ as the name of the symbol indicating the end address of the module info\n\ section", - const char *, NULL) + const char *, "__stop_minfo") /* The "stdcall" convention is really supported on 32-bit x86/Windows only. The following hook is a helper to determine whether to apply the attribute diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc index 0aac8fe..4f91853 100644 --- a/gcc/d/modules.cc +++ b/gcc/d/modules.cc @@ -438,11 +438,11 @@ register_moduleinfo (Module *decl, tree minfo) if (!first_module) return; - start_minfo_node = build_dso_registry_var (targetdm.d_minfo_start_name, + start_minfo_node = build_dso_registry_var (targetdm.d_minfo_section_start, ptr_type_node); rest_of_decl_compilation (start_minfo_node, 1, 0); - stop_minfo_node = build_dso_registry_var (targetdm.d_minfo_end_name, + stop_minfo_node = build_dso_registry_var (targetdm.d_minfo_section_end, ptr_type_node); rest_of_decl_compilation (stop_minfo_node, 1, 0); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 63c8a31..8572313 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10850,19 +10850,23 @@ the target operating system. @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION Contains the name of the section in which module info references should be -placed. This section is expected to be bracketed by two symbols to indicate -the start and end address of the section, so that the runtime library can -collect all modules for each loaded shared library and executable. The -default value of @code{NULL} disables the use of sections altogether. +placed. By default, the compiler puts all module info symbols in the +@code{"minfo"} section. Define this macro to override the string if a +different section name should be used. This section is expected to be +bracketed by two symbols @code{TARGET_D_MINFO_SECTION_START} and +@code{TARGET_D_MINFO_SECTION_END} to indicate the start and end address of +the section, so that the runtime library can collect all modules for each +loaded shared library and executable. Setting the value to @code{NULL} +disables the use of sections for storing module info altogether. @end deftypevr -@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_START_NAME +@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION_START If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined as the name of the symbol indicating the start address of the module info section @end deftypevr -@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_END_NAME +@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION_END If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined as the name of the symbol indicating the end address of the module info section diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 501ddf1..986e8f0 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7117,9 +7117,9 @@ floating-point support; they are not included in this mechanism. @hook TARGET_D_MINFO_SECTION -@hook TARGET_D_MINFO_START_NAME +@hook TARGET_D_MINFO_SECTION_START -@hook TARGET_D_MINFO_END_NAME +@hook TARGET_D_MINFO_SECTION_END @hook TARGET_D_HAS_STDCALL_CONVENTION -- cgit v1.1 From cfd85418051e8413e84ae7011cb5cb99cd8e337c Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 1 Apr 2022 19:52:54 +0200 Subject: Better separate 'LTO' vs. 'LTODump' in 'gcc/lto/lang.opt' Minor clean-up after Subversion r270897 (Git commit 66d62d9f2e6b059be6a018397fba555147133a9a) "Add lto-dump tool". No change in generated files. gcc/lto/ * lang.opt: Better separate 'LTO' vs. 'LTODump'. --- gcc/lto/lang.opt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/lto/lang.opt b/gcc/lto/lang.opt index 550a50f..1ad2967 100644 --- a/gcc/lto/lang.opt +++ b/gcc/lto/lang.opt @@ -24,9 +24,6 @@ Language LTO -Language -LTODump - Enum Name(lto_linker_output) Type(enum lto_linker_output) UnknownError(unknown linker output %qs) @@ -52,7 +49,6 @@ flinker-output= LTO Driver Joined RejectNegative Enum(lto_linker_output) Var(flag_lto_linker_output) Init(LTO_LINKER_OUTPUT_UNKNOWN) Set linker output type (used internally during LTO optimization). - fltrans LTO Var(flag_ltrans) Run the link-time optimizer in local transformation (LTRANS) mode. @@ -61,6 +57,10 @@ fltrans-output-list= LTO Joined Var(ltrans_output_list) Specify a file to which a list of files output by LTRANS is written. +fresolution= +LTO Joined +The resolution file. + fwpa LTO Driver Run the link-time optimizer in whole program analysis (WPA) mode. @@ -70,6 +70,9 @@ LTO Driver RejectNegative Joined Var(flag_wpa) Whole program analysis (WPA) mode with number of parallel jobs specified. +Language +LTODump + list LTODump Var(flag_lto_dump_list) Call the dump function for variables and function in IL. @@ -131,8 +134,4 @@ callgraph LTODump Var(flag_dump_callgraph) Dump the symtab callgraph. -fresolution= -LTO Joined -The resolution file. - ; This comment is to ensure we retain the blank line above. -- cgit v1.1 From 7e7ebe3e350fde90fe49ab41ce3b92a811bb6370 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 29 Oct 2022 09:05:54 +0200 Subject: d: Merge upstream dmd, druntime e4f8919591, phobos 3ad507b51. D front-end changes: - Import dmd v2.101.0-beta.1. - Add predefined version `D_Optimized' when compiling with `-O'. - Shortened method syntax (DIP1043) is now enabled by default. - Array literals assigned to `scope' array variables are now allocated on the stack. - Implement `@system' variables (DIP1035), available behind the preview feature flag `-fpreview=systemvariables'. D runtime changes: - Import druntime v2.101.0-beta.1. Phobos changes: - Import phobos v2.101.0-beta.1. - Added `std.typecons.SafeRefCounted', that can be used in `@safe' code with `-fpreview=dip1000'. gcc/d/ChangeLog: * d-attribs.cc (apply_user_attributes): Update for new front-end interface. * d-builtins.cc (d_init_versions): Predefine `D_Optimized' with compiling with optimizations enabled. * d-lang.cc (d_handle_option): Update for new front-end interface. Handle new option `-fpreview=systemvariables'. * dmd/MERGE: Merge upstream dmd e4f8919591. * dmd/VERSION: Bump version to v2.101.0-beta.1. * expr.cc (ExprVisitor::visit (AssignExp *)): Treat construction of static arrays from a call expression as a simple assignment. (ExprVisitor::visit (ArrayLiteralExp *)): Handle array literals with `scope' storage. * gdc.texi: Update documentation of `-fpreview=' options. * lang.opt (fpreview=shortenedmethods): Remove. (fpreview=systemvariables): New option. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime e4f8919591. * src/MERGE: Merge upstream phobos 3ad507b51. gcc/testsuite/ChangeLog: * gdc.dg/simd19630.d: Move tests with errors to ... * gdc.dg/simd19630b.d: ... here. New test. * gdc.dg/simd19630c.d: New test. * gdc.dg/simd_ctfe.d: Removed. * gdc.dg/simd18867.d: New test. * gdc.dg/simd19788.d: New test. * gdc.dg/simd21469.d: New test. * gdc.dg/simd21672.d: New test. * gdc.dg/simd23077.d: New test. * gdc.dg/simd23084.d: New test. * gdc.dg/simd23085.d: New test. * gdc.dg/torture/simd19632.d: New test. * gdc.dg/torture/simd20041.d: New test. * gdc.dg/torture/simd21673.d: New test. * gdc.dg/torture/simd21676.d: New test. * gdc.dg/torture/simd22438.d: New test. * gdc.dg/torture/simd23009.d: New test. * gdc.dg/torture/simd23077.d: New test. * gdc.dg/torture/simd8.d: New test. * gdc.dg/torture/simd9.d: New test. * gdc.dg/torture/simd_prefetch.d: New test. --- gcc/d/d-attribs.cc | 5 +- gcc/d/d-builtins.cc | 3 + gcc/d/d-lang.cc | 10 +- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/VERSION | 2 +- gcc/d/dmd/aggregate.d | 2 +- gcc/d/dmd/aggregate.h | 4 +- gcc/d/dmd/attrib.d | 41 -- gcc/d/dmd/attrib.h | 1 - gcc/d/dmd/clone.d | 22 +- gcc/d/dmd/common/bitfields.d | 9 +- gcc/d/dmd/common/file.d | 11 +- gcc/d/dmd/cparse.d | 39 +- gcc/d/dmd/cppmangle.d | 10 +- gcc/d/dmd/dcast.d | 114 +++--- gcc/d/dmd/declaration.d | 59 ++- gcc/d/dmd/declaration.h | 66 +++- gcc/d/dmd/dinterpret.d | 6 + gcc/d/dmd/dmodule.d | 435 ++++++++++----------- gcc/d/dmd/dscope.d | 6 +- gcc/d/dmd/dstruct.d | 33 +- gcc/d/dmd/dsymbol.d | 54 ++- gcc/d/dmd/dsymbol.h | 16 +- gcc/d/dmd/dsymbolsem.d | 204 ++++++---- gcc/d/dmd/dtemplate.d | 4 +- gcc/d/dmd/entity.d | 236 +++++------ gcc/d/dmd/escape.d | 369 ++++++++--------- gcc/d/dmd/expression.d | 2 +- gcc/d/dmd/expression.h | 1 + gcc/d/dmd/expressionsem.d | 173 +++++--- gcc/d/dmd/func.d | 276 ++++++------- gcc/d/dmd/globals.d | 5 +- gcc/d/dmd/globals.h | 6 +- gcc/d/dmd/hdrgen.d | 27 +- gcc/d/dmd/lexer.d | 48 ++- gcc/d/dmd/module.h | 2 +- gcc/d/dmd/mtype.d | 69 ++-- gcc/d/dmd/mtype.h | 5 + gcc/d/dmd/nogc.d | 4 +- gcc/d/dmd/parse.d | 6 +- gcc/d/dmd/printast.d | 7 + gcc/d/dmd/root/utf.d | 2 +- gcc/d/dmd/safe.d | 10 +- gcc/d/dmd/semantic3.d | 44 +-- gcc/d/dmd/statementsem.d | 188 +++++---- gcc/d/dmd/templateparamsem.d | 9 + gcc/d/dmd/transitivevisitor.d | 9 + gcc/d/expr.cc | 9 + gcc/d/gdc.texi | 8 +- gcc/d/lang.opt | 4 +- gcc/testsuite/gdc.dg/simd18867.d | 11 + gcc/testsuite/gdc.dg/simd19630.d | 10 - gcc/testsuite/gdc.dg/simd19630b.d | 17 + gcc/testsuite/gdc.dg/simd19630c.d | 15 + gcc/testsuite/gdc.dg/simd19788.d | 11 + gcc/testsuite/gdc.dg/simd21469.d | 9 + gcc/testsuite/gdc.dg/simd21672.d | 17 + gcc/testsuite/gdc.dg/simd23077.d | 11 + gcc/testsuite/gdc.dg/simd23084.d | 17 + gcc/testsuite/gdc.dg/simd23085.d | 11 + gcc/testsuite/gdc.dg/simd_ctfe.d | 88 ----- gcc/testsuite/gdc.dg/torture/simd19632.d | 15 + gcc/testsuite/gdc.dg/torture/simd20041.d | 22 ++ gcc/testsuite/gdc.dg/torture/simd21673.d | 20 + gcc/testsuite/gdc.dg/torture/simd21676.d | 36 ++ gcc/testsuite/gdc.dg/torture/simd22438.d | 18 + gcc/testsuite/gdc.dg/torture/simd23009.d | 22 ++ gcc/testsuite/gdc.dg/torture/simd23077.d | 11 + gcc/testsuite/gdc.dg/torture/simd8.d | 26 ++ gcc/testsuite/gdc.dg/torture/simd9.d | 46 +++ gcc/testsuite/gdc.dg/torture/simd_prefetch.d | 21 + gcc/testsuite/gdc.test/compilable/cdcmp.d | 14 - .../gdc.test/compilable/extra-files/header2.d | 19 + .../gdc.test/compilable/imports/cimports2a.i | 7 + .../gdc.test/compilable/imports/cimports2b.i | 8 + .../gdc.test/compilable/imports/pkg22952/package.d | 1 + gcc/testsuite/gdc.test/compilable/noreturn3.d | 257 ++++++++++++ .../gdc.test/compilable/scope_tuple_expansion.d | 21 + .../gdc.test/compilable/shortened_methods.d | 2 +- gcc/testsuite/gdc.test/compilable/test11980.d | 5 +- gcc/testsuite/gdc.test/compilable/test22674.d | 7 + gcc/testsuite/gdc.test/compilable/test22784.d | 10 + gcc/testsuite/gdc.test/compilable/test22952.d | 10 + gcc/testsuite/gdc.test/compilable/test23380.d | 9 + gcc/testsuite/gdc.test/compilable/test23386.d | 12 + .../gdc.test/fail_compilation/diag23384.d | 29 ++ .../gdc.test/fail_compilation/fail10905.d | 22 -- .../gdc.test/fail_compilation/fail19898a.d | 2 +- .../gdc.test/fail_compilation/fail19898b.d | 2 +- .../gdc.test/fail_compilation/fail22366.d | 2 +- .../gdc.test/fail_compilation/fail23406.d | 40 ++ .../gdc.test/fail_compilation/issue21378.d | 2 +- gcc/testsuite/gdc.test/fail_compilation/lexer1.d | 3 +- .../gdc.test/fail_compilation/pragmainline.d | 2 +- gcc/testsuite/gdc.test/fail_compilation/pragmas.d | 4 +- .../gdc.test/fail_compilation/previewin.d | 6 +- .../gdc.test/fail_compilation/reserved_version.d | 3 + .../fail_compilation/reserved_version_switch.d | 3 + gcc/testsuite/gdc.test/fail_compilation/retscope.d | 6 +- .../gdc.test/fail_compilation/retscope2.d | 2 +- .../gdc.test/fail_compilation/retscope6.d | 2 +- .../gdc.test/fail_compilation/systemvariables.d | 48 +++ .../fail_compilation/systemvariables_deprecation.d | 28 ++ .../fail_compilation/systemvariables_struct.d | 60 +++ .../fail_compilation/systemvariables_void_init.d | 32 ++ .../gdc.test/fail_compilation/templatethis.d | 37 ++ .../gdc.test/fail_compilation/test14496.d | 3 +- .../gdc.test/fail_compilation/test17764.d | 2 +- .../gdc.test/fail_compilation/test19097.d | 2 +- .../gdc.test/fail_compilation/test22145.d | 2 +- .../gdc.test/fail_compilation/test22680.d | 2 +- .../gdc.test/fail_compilation/warn14905.d | 23 ++ gcc/testsuite/gdc.test/fail_compilation/xmmslice.d | 22 ++ gcc/testsuite/gdc.test/runnable/cdcmp.d | 146 +++++++ gcc/testsuite/gdc.test/runnable/lexer.d | 4 + gcc/testsuite/gdc.test/runnable/test20734.d | 8 + gcc/testsuite/gdc.test/runnable/test23337.d | 182 +++++++++ 117 files changed, 2851 insertions(+), 1393 deletions(-) create mode 100644 gcc/testsuite/gdc.dg/simd18867.d create mode 100644 gcc/testsuite/gdc.dg/simd19630b.d create mode 100644 gcc/testsuite/gdc.dg/simd19630c.d create mode 100644 gcc/testsuite/gdc.dg/simd19788.d create mode 100644 gcc/testsuite/gdc.dg/simd21469.d create mode 100644 gcc/testsuite/gdc.dg/simd21672.d create mode 100644 gcc/testsuite/gdc.dg/simd23077.d create mode 100644 gcc/testsuite/gdc.dg/simd23084.d create mode 100644 gcc/testsuite/gdc.dg/simd23085.d delete mode 100644 gcc/testsuite/gdc.dg/simd_ctfe.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd19632.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd20041.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd21673.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd21676.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd22438.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd23009.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd23077.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd8.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd9.d create mode 100644 gcc/testsuite/gdc.dg/torture/simd_prefetch.d create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg22952/package.d create mode 100644 gcc/testsuite/gdc.test/compilable/noreturn3.d create mode 100644 gcc/testsuite/gdc.test/compilable/scope_tuple_expansion.d create mode 100644 gcc/testsuite/gdc.test/compilable/test22784.d create mode 100644 gcc/testsuite/gdc.test/compilable/test22952.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23380.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23386.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/diag23384.d delete mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail10905.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail23406.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/systemvariables.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/systemvariables_deprecation.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/systemvariables_struct.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/systemvariables_void_init.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/templatethis.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/warn14905.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/xmmslice.d create mode 100644 gcc/testsuite/gdc.test/runnable/cdcmp.d create mode 100644 gcc/testsuite/gdc.test/runnable/test23337.d (limited to 'gcc') diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc index 04f7f16..90e72e3 100644 --- a/gcc/d/d-attribs.cc +++ b/gcc/d/d-attribs.cc @@ -426,7 +426,8 @@ build_attributes (Expressions *eattrs) void apply_user_attributes (Dsymbol *sym, tree node) { - if (!sym->userAttribDecl) + UserAttributeDeclaration *uda = sym->userAttribDecl (); + if (uda == NULL) return; location_t saved_location = input_location; @@ -436,7 +437,7 @@ apply_user_attributes (Dsymbol *sym, tree node) if (TYPE_P (node) && !COMPLETE_TYPE_P (node)) attr_flags |= ATTR_FLAG_TYPE_IN_PLACE; - Expressions *attrs = sym->userAttribDecl->getAttributes (); + Expressions *attrs = uda->getAttributes (); decl_attributes (&node, build_attributes (attrs), attr_flags); input_location = saved_location; diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc index 5997e5d..51e562a 100644 --- a/gcc/d/d-builtins.cc +++ b/gcc/d/d-builtins.cc @@ -505,6 +505,9 @@ d_init_versions (void) VersionCondition::addPredefinedGlobalIdent ("D_TypeInfo"); } + if (optimize) + VersionCondition::addPredefinedGlobalIdent ("D_Optimized"); + VersionCondition::addPredefinedGlobalIdent ("all"); /* Emit all target-specific version identifiers. */ diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index dcc465f..3b61301 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -567,10 +567,10 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, global.params.fixAliasThis = value; global.params.previewIn = value; global.params.fix16997 = value; - global.params.noSharedAccess = value; + global.params.noSharedAccess = FeatureState::enabled; global.params.rvalueRefParam = FeatureState::enabled; global.params.inclusiveInContracts = value; - global.params.shortenedMethods = value; + global.params.systemVariables = FeatureState::enabled; global.params.fixImmutableConv = value; break; @@ -619,15 +619,15 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, break; case OPT_fpreview_nosharedaccess: - global.params.noSharedAccess = value; + global.params.noSharedAccess = FeatureState::enabled; break; case OPT_fpreview_rvaluerefparam: global.params.rvalueRefParam = FeatureState::enabled; break; - case OPT_fpreview_shortenedmethods: - global.params.shortenedMethods = value; + case OPT_fpreview_systemvariables: + global.params.systemVariables = FeatureState::enabled; break; case OPT_frelease: diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index a4c46f3..2398875 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -4219ba670ce9ff92f3e874f0f048f2c28134c008 +e4f89195913be1dc638707b1abb24c4f3ae7e0bf The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION index 83a14f5..50adf9c 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.100.1 +v2.101.0-beta.1 diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d index edca17f..e9e8bbe 100644 --- a/gcc/d/dmd/aggregate.d +++ b/gcc/d/dmd/aggregate.d @@ -109,7 +109,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol CPPMANGLE cppmangle; /// overridden symbol with pragma(mangle, "...") if not null - MangleOverride* mangleOverride; + MangleOverride* pMangleOverride; /** * !=null if is nested diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index f0909e3..d4432b5 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -82,7 +82,7 @@ public: CPPMANGLE cppmangle; // overridden symbol with pragma(mangle, "...") - MangleOverride *mangleOverride; + MangleOverride *pMangleOverride; /* !=NULL if is nested * pointing to the dsymbol that directly enclosing it. * 1. The function that enclosing it (nested struct and class) @@ -174,7 +174,7 @@ public: structalign_t alignment; // alignment applied outside of the struct ThreeState ispod; // if struct is POD private: - uint8_t bitFields; + uint16_t bitFields; public: static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject); StructDeclaration *syntaxCopy(Dsymbol *s) override; diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index 3472d1c..3f27cb9 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -894,50 +894,9 @@ extern (C++) final class PragmaDeclaration : AttribDeclaration // then it's evaluated on demand in function semantic return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.visibility, sc.explicitVisibility, sc.aligndecl, this); } - if (ident == Id.printf || ident == Id.scanf) - { - auto sc2 = sc.push(); - - if (ident == Id.printf) - // Override previous setting, never let both be set - sc2.flags = (sc2.flags & ~SCOPE.scanf) | SCOPE.printf; - else - sc2.flags = (sc2.flags & ~SCOPE.printf) | SCOPE.scanf; - - return sc2; - } return sc; } - PINLINE evalPragmaInline(Scope* sc) - { - if (!args || args.dim == 0) - return PINLINE.default_; - - Expression e = (*args)[0]; - if (!e.type) - { - - sc = sc.startCTFE(); - e = e.expressionSemantic(sc); - e = resolveProperties(sc, e); - sc = sc.endCTFE(); - e = e.ctfeInterpret(); - e = e.toBoolean(sc); - if (e.isErrorExp()) - error("pragma(`inline`, `true` or `false`) expected, not `%s`", (*args)[0].toChars()); - (*args)[0] = e; - } - - const opt = e.toBool(); - if (opt.isEmpty()) - return PINLINE.default_; - else if (opt.get()) - return PINLINE.always; - else - return PINLINE.never; - } - override const(char)* kind() const { return "pragma"; diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h index 1fe33a6..b153229 100644 --- a/gcc/d/dmd/attrib.h +++ b/gcc/d/dmd/attrib.h @@ -154,7 +154,6 @@ public: PragmaDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - PINLINE evalPragmaInline(Scope* sc); const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d index ba7d590..c999048 100644 --- a/gcc/d/dmd/clone.d +++ b/gcc/d/dmd/clone.d @@ -300,7 +300,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc) auto tf = new TypeFunction(ParameterList(fparams), sd.handleType(), LINK.d, stc | STC.ref_); auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.assign, stc, tf); fop.storage_class |= STC.inference; - fop.flags |= FUNCFLAG.generated; + fop.isGenerated = true; Expression e; if (stc & STC.disable) { @@ -581,7 +581,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc) tf = tf.addSTC(STC.const_).toTypeFunction(); Identifier id = Id.xopEquals; auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf); - fop.flags |= FUNCFLAG.generated; + fop.isGenerated = true; fop.parent = sd; Expression e1 = new IdentifierExp(loc, Id.This); Expression e2 = new IdentifierExp(loc, Id.p); @@ -705,7 +705,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc) tf = tf.addSTC(STC.const_).toTypeFunction(); Identifier id = Id.xopCmp; auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf); - fop.flags |= FUNCFLAG.generated; + fop.isGenerated = true; fop.parent = sd; Expression e1 = new IdentifierExp(loc, Id.This); Expression e2 = new IdentifierExp(loc, Id.p); @@ -823,7 +823,7 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc) auto tf = new TypeFunction(ParameterList(parameters), Type.thash_t, LINK.d, STC.nothrow_ | STC.trusted); Identifier id = Id.xtoHash; auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf); - fop.flags |= FUNCFLAG.generated; + fop.isGenerated = true; /* Do memberwise hashing. * @@ -961,7 +961,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc) { //printf("Building __fieldDtor(), %s\n", e.toChars()); auto dd = new DtorDeclaration(declLoc, Loc.initial, stc, Id.__fieldDtor); - dd.flags |= FUNCFLAG.generated; + dd.isGenerated = true; dd.storage_class |= STC.inference; dd.fbody = new ExpStatement(loc, e); ad.members.push(dd); @@ -1017,7 +1017,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc) e = Expression.combine(e, ce); } auto dd = new DtorDeclaration(declLoc, Loc.initial, stc, Id.__aggrDtor); - dd.flags |= FUNCFLAG.generated; + dd.isGenerated = true; dd.storage_class |= STC.inference; dd.fbody = new ExpStatement(loc, e); ad.members.push(dd); @@ -1088,7 +1088,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara stmts.push(new ExpStatement(loc, call)); stmts.push(new ReturnStatement(loc, new CastExp(loc, new ThisExp(loc), Type.tvoidptr))); func.fbody = new CompoundStatement(loc, stmts); - func.flags |= FUNCFLAG.generated; + func.isGenerated = true; auto sc2 = sc.push(); sc2.stc &= ~STC.static_; // not a static destructor @@ -1140,7 +1140,7 @@ private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc) auto call = new CallExp(dtor.loc, dtor, null); call.directcall = true; // non-virtual call Class.__dtor(); func.fbody = new ExpStatement(dtor.loc, call); - func.flags |= FUNCFLAG.generated; + func.isGenerated = true; func.storage_class |= STC.inference; auto sc2 = sc.push(); @@ -1416,7 +1416,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc) //printf("Building __fieldPostBlit()\n"); checkShared(); auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__fieldPostblit); - dd.flags |= FUNCFLAG.generated; + dd.isGenerated = true; dd.storage_class |= STC.inference | STC.scope_; dd.fbody = (stc & STC.disable) ? null : new CompoundStatement(loc, postblitCalls); sd.postblits.shift(dd); @@ -1454,7 +1454,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc) checkShared(); auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__aggrPostblit); - dd.flags |= FUNCFLAG.generated; + dd.isGenerated = true; dd.storage_class |= STC.inference; dd.fbody = new ExpStatement(loc, e); sd.members.push(dd); @@ -1517,7 +1517,7 @@ private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true); ccd.storage_class |= funcStc; ccd.storage_class |= STC.inference; - ccd.flags |= FUNCFLAG.generated; + ccd.isGenerated = true; return ccd; } diff --git a/gcc/d/dmd/common/bitfields.d b/gcc/d/dmd/common/bitfields.d index cccaabd..bba61ad 100644 --- a/gcc/d/dmd/common/bitfields.d +++ b/gcc/d/dmd/common/bitfields.d @@ -23,6 +23,7 @@ if (__traits(isUnsigned, T)) string result = "extern (C++) pure nothrow @nogc @safe final {"; enum structName = __traits(identifier, S); + string initialValue = ""; foreach (size_t i, mem; __traits(allMembers, S)) { static assert(is(typeof(__traits(getMember, S, mem)) == bool)); @@ -37,8 +38,10 @@ if (__traits(isUnsigned, T)) v ? (bitFields |= "~mask~") : (bitFields &= ~"~mask~"); return v; }"; + + initialValue = (__traits(getMember, S.init, mem) ? "1" : "0") ~ initialValue; } - return result ~ "}\n private "~T.stringof~" bitFields;\n"; + return result ~ "}\n private "~T.stringof~" bitFields = 0b" ~ initialValue ~ ";\n"; } /// @@ -48,7 +51,7 @@ unittest { bool x; bool y; - bool z; + bool z = 1; } static struct S @@ -66,5 +69,5 @@ unittest s.y = true; assert(s.y); assert(!s.x); - assert(!s.z); + assert(s.z); } diff --git a/gcc/d/dmd/common/file.d b/gcc/d/dmd/common/file.d index 8f34b53..89e7027 100644 --- a/gcc/d/dmd/common/file.d +++ b/gcc/d/dmd/common/file.d @@ -144,9 +144,14 @@ struct FileMapping(Datum) import core.stdc.string : strlen; import core.stdc.stdlib : malloc; import core.stdc.string : memcpy; - auto totalNameLength = filename.strlen() + 1; - name = cast(char*) memcpy(malloc(totalNameLength), filename, totalNameLength); - name || assert(0, "FileMapping: Out of memory."); + const totalNameLength = filename.strlen() + 1; + auto namex = cast(char*) malloc(totalNameLength); + if (!namex) + { + fprintf(stderr, "FileMapping: Out of memory."); + exit(1); + } + name = cast(char*) memcpy(namex, filename, totalNameLength); } /** diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index 2c5a4f0..ad1ad67 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -1906,6 +1906,8 @@ final class CParser(AST) : Parser!AST { auto str = asmName.peekString(); p.mangleOverride = str; +// p.adFlags |= AST.VarDeclaration.nounderscore; + p.adFlags |= 4; // cannot get above line to compile on Ubuntu } } s = applySpecifier(s, specifier); @@ -5164,18 +5166,40 @@ final class CParser(AST) : Parser!AST if (n.value == TOK.identifier && n.ident == Id.pop) { scan(&n); - while (n.value == TOK.comma) + size_t len = this.records.length; + if (n.value == TOK.rightParenthesis) // #pragma pack ( pop ) + { + if (len == 0) // nothing to pop + return closingParen(); + + this.records.setDim(len - 1); + this.packs.setDim(len - 1); + if (len == 1) // stack is now empty + packalign.setDefault(); + else + packalign = (*this.packs)[len - 1]; + return closingParen(); + } + while (n.value == TOK.comma) // #pragma pack ( pop , { scan(&n); if (n.value == TOK.identifier) { - for (size_t len = this.records.length; len; --len) + /* pragma pack(pop, identifier + * Pop until identifier is found, pop that one too, and set + * alignment to the new top of the stack. + * If identifier is not found, do nothing. + */ + for ( ; len; --len) { if ((*this.records)[len - 1] == n.ident) { - packalign = (*this.packs)[len - 1]; this.records.setDim(len - 1); this.packs.setDim(len - 1); + if (len > 1) + packalign = (*this.packs)[len - 2]; + else + packalign.setDefault(); // stack empty, use default break; } } @@ -5184,14 +5208,18 @@ final class CParser(AST) : Parser!AST else if (n.value == TOK.int32Literal) { setPackAlign(n); - this.records.push(null); - this.packs.push(packalign); + scan(&n); + } + else + { + error(loc, "identifier or alignment value expected following `#pragma pack(pop,` not `%s`", n.toChars()); scan(&n); } } return closingParen(); } /* # pragma pack ( integer ) + * Sets alignment to integer */ if (n.value == TOK.int32Literal) { @@ -5200,6 +5228,7 @@ final class CParser(AST) : Parser!AST return closingParen(); } /* # pragma pack ( ) + * Sets alignment to default */ if (n.value == TOK.rightParenthesis) { diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d index fed83b8..7c130e9 100644 --- a/gcc/d/dmd/cppmangle.d +++ b/gcc/d/dmd/cppmangle.d @@ -615,7 +615,7 @@ private final class CppMangleVisitor : Visitor if (!ti) { auto ag = s.isAggregateDeclaration(); - const ident = (ag && ag.mangleOverride) ? ag.mangleOverride.id : s.ident; + const ident = (ag && ag.pMangleOverride) ? ag.pMangleOverride.id : s.ident; this.writeNamespace(s.cppnamespace, () { this.writeIdentifier(ident); this.abiTags.writeSymbol(s, this); @@ -654,14 +654,14 @@ private final class CppMangleVisitor : Visitor } auto ag = ti.aliasdecl ? ti.aliasdecl.isAggregateDeclaration() : null; - if (ag && ag.mangleOverride) + if (ag && ag.pMangleOverride) { this.writeNamespace( ti.toAlias().cppnamespace, () { - this.writeIdentifier(ag.mangleOverride.id); - if (ag.mangleOverride.agg && ag.mangleOverride.agg.isInstantiated()) + this.writeIdentifier(ag.pMangleOverride.id); + if (ag.pMangleOverride.agg && ag.pMangleOverride.agg.isInstantiated()) { - auto to = ag.mangleOverride.agg.isInstantiated(); + auto to = ag.pMangleOverride.agg.isInstantiated(); append(to); this.abiTags.writeSymbol(to.tempdecl, this); template_args(to); diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 8ab3873..ba3afb7 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -327,6 +327,45 @@ MATCH implicitConvTo(Expression e, Type t) return MATCH.nomatch; } + // Apply mod bits to each function parameter, + // and see if we can convert the function argument to the modded type + static bool parametersModMatch(Expressions* args, TypeFunction tf, MOD mod) + { + const size_t nparams = tf.parameterList.length; + const size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended + foreach (const i; j .. args.dim) + { + Expression earg = (*args)[i]; + Type targ = earg.type.toBasetype(); + static if (LOG) + { + printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars()); + } + if (i - j < nparams) + { + Parameter fparam = tf.parameterList[i - j]; + if (fparam.isLazy()) + return false; // not sure what to do with this + Type tparam = fparam.type; + if (!tparam) + continue; + if (fparam.isReference()) + { + if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch) + return false; + continue; + } + } + static if (LOG) + { + printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars()); + } + if (implicitMod(earg, targ, mod) == MATCH.nomatch) + return false; + } + return true; + } + MATCH visitAdd(AddExp e) { version (none) @@ -894,9 +933,6 @@ MATCH implicitConvTo(Expression e, Type t) /* Apply mod bits to each function parameter, * and see if we can convert the function argument to the modded type */ - - size_t nparams = tf.parameterList.length; - size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended if (auto dve = e.e1.isDotVarExp()) { /* Treat 'this' as just another function argument @@ -905,36 +941,9 @@ MATCH implicitConvTo(Expression e, Type t) if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch) return result; } - foreach (const i; j .. e.arguments.dim) - { - Expression earg = (*e.arguments)[i]; - Type targ = earg.type.toBasetype(); - static if (LOG) - { - printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars()); - } - if (i - j < nparams) - { - Parameter fparam = tf.parameterList[i - j]; - if (fparam.isLazy()) - return result; // not sure what to do with this - Type tparam = fparam.type; - if (!tparam) - continue; - if (fparam.isReference()) - { - if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch) - return result; - continue; - } - } - static if (LOG) - { - printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars()); - } - if (implicitMod(earg, targ, mod) == MATCH.nomatch) - return result; - } + + if (!parametersModMatch(e.arguments, tf, mod)) + return result; /* Success */ @@ -1206,47 +1215,16 @@ MATCH implicitConvTo(Expression e, Type t) if (tf.purity == PURE.impure) return MATCH.nomatch; // impure + // Allow a conversion to immutable type, or + // conversions of mutable types between thread-local and shared. if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant) { return MATCH.nomatch; } - // Allow a conversion to immutable type, or - // conversions of mutable types between thread-local and shared. - - Expressions* args = e.arguments; - size_t nparams = tf.parameterList.length; - // if TypeInfoArray was prepended - size_t j = tf.isDstyleVariadic(); - for (size_t i = j; i < e.arguments.dim; ++i) + if (!parametersModMatch(e.arguments, tf, mod)) { - Expression earg = (*args)[i]; - Type targ = earg.type.toBasetype(); - static if (LOG) - { - printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars()); - } - if (i - j < nparams) - { - Parameter fparam = tf.parameterList[i - j]; - if (fparam.isLazy()) - return MATCH.nomatch; // not sure what to do with this - Type tparam = fparam.type; - if (!tparam) - continue; - if (fparam.isReference()) - { - if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch) - return MATCH.nomatch; - continue; - } - } - static if (LOG) - { - printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars()); - } - if (implicitMod(earg, targ, mod) == MATCH.nomatch) - return MATCH.nomatch; + return MATCH.nomatch; } } diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d index ff27e37..07d58f0 100644 --- a/gcc/d/dmd/declaration.d +++ b/gcc/d/dmd/declaration.d @@ -227,6 +227,7 @@ extern (C++) abstract class Declaration : Dsymbol ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons) enum wasRead = 1; // set if AliasDeclaration was read enum ignoreRead = 2; // ignore any reads of AliasDeclaration + enum nounderscore = 4; // don't prepend _ to mangled name Symbol* isym; // import version of csym @@ -481,6 +482,11 @@ extern (C++) abstract class Declaration : Dsymbol return (storage_class & STC.scope_) != 0; } + final bool isReturn() const pure nothrow @nogc @safe + { + return (storage_class & STC.return_) != 0; + } + final bool isSynchronized() const pure nothrow @nogc @safe { return (storage_class & STC.synchronized_) != 0; @@ -542,6 +548,11 @@ extern (C++) abstract class Declaration : Dsymbol return (storage_class & STC.future) != 0; } + final extern(D) bool isSystem() const pure nothrow @nogc @safe + { + return (storage_class & STC.system) != 0; + } + override final Visibility visible() pure nothrow @nogc @safe { return visibility; @@ -780,7 +791,17 @@ extern (C++) final class AliasDeclaration : Declaration * is not overloadable. */ if (type) - return false; + { + /* + If type has been resolved already we could + still be inserting an alias from an import. + + If we are handling an alias then pretend + it was inserting and return true, if not then + false since we didn't even pretend to insert something. + */ + return this._import && this.equals(s); + } /* When s is added in member scope by static if, mixin("code") or others, * aliassym is determined already. See the case in: test/compilable/test61.d @@ -1634,7 +1655,7 @@ extern (C++) class VarDeclaration : Declaration // Add this VarDeclaration to fdv.closureVars[] if not already there if (!sc.intypeof && !(sc.flags & SCOPE.compile) && // https://issues.dlang.org/show_bug.cgi?id=17605 - (fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly)) + (fdv.isCompileTimeOnly || !fdthis.isCompileTimeOnly) ) { if (!fdv.closureVars.contains(this)) @@ -1754,16 +1775,21 @@ extern (C++) class BitFieldDeclaration : VarDeclaration override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) { - //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars()); - static void print(const ref FieldState fieldState) + enum log = false; + static if (log) { - printf("FieldState.offset = %d bytes\n", fieldState.offset); - printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset); - printf(" .bitOffset = %d bits\n", fieldState.bitOffset); - printf(" .fieldSize = %d bytes\n", fieldState.fieldSize); - printf(" .inFlight = %d\n\n", fieldState.inFlight); + printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars()); + void print(const ref FieldState fieldState) + { + printf("FieldState.offset = %d bytes\n", fieldState.offset); + printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset); + printf(" .bitOffset = %d bits\n", fieldState.bitOffset); + printf(" .fieldSize = %d bytes\n", fieldState.fieldSize); + printf(" .inFlight = %d\n", fieldState.inFlight); + printf(" fieldWidth = %d bits\n", fieldWidth); + } + print(fieldState); } - //print(fieldState); Type t = type.toBasetype(); const bool anon = isAnonymous(); @@ -1780,6 +1806,7 @@ extern (C++) class BitFieldDeclaration : VarDeclaration assert(sz != SIZE_INVALID && sz < uint.max); uint memsize = cast(uint)sz; // size of member uint memalignsize = target.fieldalign(t); // size of member for alignment purposes + if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize); if (fieldWidth == 0 && !anon) error(loc, "named bit fields cannot have 0 width"); @@ -1790,6 +1817,7 @@ extern (C++) class BitFieldDeclaration : VarDeclaration void startNewField() { + if (log) printf("startNewField()\n"); uint alignsize; if (style == TargetC.BitFieldStyle.Gcc_Clang) { @@ -1881,15 +1909,15 @@ extern (C++) class BitFieldDeclaration : VarDeclaration if (!fieldState.inFlight) { + //printf("not in flight\n"); startNewField(); } else if (style == TargetC.BitFieldStyle.Gcc_Clang) { - if (fieldState.bitOffset + fieldWidth > memsize * 8) - { - //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize); - startNewField(); - } + // If the bit-field spans more units of alignment than its type, + // start a new field at the next alignment boundary. + if (fieldState.bitOffset == fieldState.fieldSize * 8) + startNewField(); // the bit field is full else { // if alignment boundary is crossed @@ -1909,6 +1937,7 @@ extern (C++) class BitFieldDeclaration : VarDeclaration if (memsize != fieldState.fieldSize || fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8) { + //printf("new field\n"); startNewField(); } } diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index 5bce6b0..2668b6e 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -139,6 +139,7 @@ public: bool isWild() const { return (storage_class & STCwild) != 0; } bool isAuto() const { return (storage_class & STCauto) != 0; } bool isScope() const { return (storage_class & STCscope) != 0; } + bool isReturn() const { return (storage_class & STCreturn) != 0; } bool isSynchronized() const { return (storage_class & STCsynchronized) != 0; } bool isParameter() const { return (storage_class & STCparameter) != 0; } bool isDeprecated() const override final { return (storage_class & STCdeprecated) != 0; } @@ -615,7 +616,54 @@ public: AttributeViolation* safetyViolation; - unsigned flags; // FUNCFLAGxxxxx + // Formerly FUNCFLAGS + uint32_t flags; + bool purityInprocess() const; + bool purityInprocess(bool v); + bool safetyInprocess() const; + bool safetyInprocess(bool v); + bool nothrowInprocess() const; + bool nothrowInprocess(bool v); + bool nogcInprocess() const; + bool nogcInprocess(bool v); + bool returnInprocess() const; + bool returnInprocess(bool v); + bool inlineScanned() const; + bool inlineScanned(bool v); + bool inferScope() const; + bool inferScope(bool v); + bool hasCatches() const; + bool hasCatches(bool v); + bool isCompileTimeOnly() const; + bool isCompileTimeOnly(bool v); + bool printf() const; + bool printf(bool v); + bool scanf() const; + bool scanf(bool v); + bool noreturn() const; + bool noreturn(bool v); + bool isNRVO() const; + bool isNRVO(bool v); + bool isNaked() const; + bool isNaked(bool v); + bool isGenerated() const; + bool isGenerated(bool v); + bool isIntroducing() const; + bool isIntroducing(bool v); + bool hasSemantic3Errors() const; + bool hasSemantic3Errors(bool v); + bool hasNoEH() const; + bool hasNoEH(bool v); + bool inferRetType() const; + bool inferRetType(bool v); + bool hasDualContext() const; + bool hasDualContext(bool v); + bool hasAlwaysInlines() const; + bool hasAlwaysInlines(bool v); + bool isCrtCtor() const; + bool isCrtCtor(bool v); + bool isCrtDtor() const; + bool isCrtDtor(bool v); // Data for a function declaration that is needed for the Objective-C // integration. @@ -655,22 +703,6 @@ public: bool isNogc(); bool isNogcBypassingInference(); - bool isNRVO() const; - void isNRVO(bool v); - bool isNaked() const; - void isNaked(bool v); - bool isGenerated() const; - void isGenerated(bool v); - bool isIntroducing() const; - bool hasSemantic3Errors() const; - bool hasNoEH() const; - bool inferRetType() const; - bool hasDualContext() const; - bool hasAlwaysInlines() const; - bool isCrtCtor() const; - void isCrtCtor(bool v); - bool isCrtDtor() const; - void isCrtDtor(bool v); virtual bool isNested() const; AggregateDeclaration *isThis() override; diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index a95d9de..63b70009 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -2872,6 +2872,12 @@ public: else m = v.getConstInitializer(true); } + else if (v.type.isTypeNoreturn()) + { + // Noreturn field with default initializer + (*elems)[fieldsSoFar + i] = null; + continue; + } else m = v.type.defaultInitLiteral(e.loc); if (exceptionOrCant(m)) diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index 2cb1cc7..b2908ce 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -98,13 +98,13 @@ private const(char)[] getFilename(Identifier[] packages, Identifier ident) nothr { const(char)[] filename = ident.toString(); - if (packages.length == 0) - return filename; - OutBuffer buf; OutBuffer dotmods; auto modAliases = &global.params.modFileAliasStrings; + if (packages.length == 0 && modAliases.length == 0) + return filename; + void checkModFileAlias(const(char)[] p) { /* Check and replace the contents of buf[] with @@ -308,7 +308,7 @@ extern (C++) class Package : ScopeDsymbol packages ~= s.ident; reverse(packages); - if (FileManager.lookForSourceFile(getFilename(packages, ident), global.path ? (*global.path)[] : null)) + if (Module.find(getFilename(packages, ident))) Module.load(Loc.initial, packages, this.ident); else isPkgMod = PKG.package_; @@ -492,6 +492,16 @@ extern (C++) final class Module : Package return new Module(Loc.initial, filename, ident, doDocComment, doHdrGen); } + static const(char)* find(const(char)* filename) + { + return find(filename.toDString).ptr; + } + + extern (D) static const(char)[] find(const(char)[] filename) + { + return FileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null); + } + extern (C++) static Module load(const ref Loc loc, Identifiers* packages, Identifier ident) { return load(loc, packages ? (*packages)[] : null, ident); @@ -506,7 +516,7 @@ extern (C++) final class Module : Package // foo\bar\baz const(char)[] filename = getFilename(packages, ident); // Look for the source file - if (const result = FileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null)) + if (const result = find(filename)) filename = result; // leaks auto m = new Module(loc, filename, ident, 0, 0); @@ -703,232 +713,12 @@ extern (C++) final class Module : Package /// ditto extern (D) Module parseModule(AST)() { - enum Endian { little, big} - enum SourceEncoding { utf16, utf32} - - /* - * Convert a buffer from UTF32 to UTF8 - * Params: - * Endian = is the buffer big/little endian - * buf = buffer of UTF32 data - * Returns: - * input buffer reencoded as UTF8 - */ - - char[] UTF32ToUTF8(Endian endian)(const(char)[] buf) - { - static if (endian == Endian.little) - alias readNext = Port.readlongLE; - else - alias readNext = Port.readlongBE; - - if (buf.length & 3) - { - error("odd length of UTF-32 char source %llu", cast(ulong) buf.length); - return null; - } - - const (uint)[] eBuf = cast(const(uint)[])buf; - - OutBuffer dbuf; - dbuf.reserve(eBuf.length); - - foreach (i; 0 .. eBuf.length) - { - const u = readNext(&eBuf[i]); - if (u & ~0x7F) - { - if (u > 0x10FFFF) - { - error("UTF-32 value %08x greater than 0x10FFFF", u); - return null; - } - dbuf.writeUTF8(u); - } - else - dbuf.writeByte(u); - } - dbuf.writeByte(0); //add null terminator - return dbuf.extractSlice(); - } - - /* - * Convert a buffer from UTF16 to UTF8 - * Params: - * Endian = is the buffer big/little endian - * buf = buffer of UTF16 data - * Returns: - * input buffer reencoded as UTF8 - */ - - char[] UTF16ToUTF8(Endian endian)(const(char)[] buf) - { - static if (endian == Endian.little) - alias readNext = Port.readwordLE; - else - alias readNext = Port.readwordBE; - - if (buf.length & 1) - { - error("odd length of UTF-16 char source %llu", cast(ulong) buf.length); - return null; - } - - const (ushort)[] eBuf = cast(const(ushort)[])buf; - - OutBuffer dbuf; - dbuf.reserve(eBuf.length); - - //i will be incremented in the loop for high codepoints - foreach (ref i; 0 .. eBuf.length) - { - uint u = readNext(&eBuf[i]); - if (u & ~0x7F) - { - if (0xD800 <= u && u < 0xDC00) - { - i++; - if (i >= eBuf.length) - { - error("surrogate UTF-16 high value %04x at end of file", u); - return null; - } - const u2 = readNext(&eBuf[i]); - if (u2 < 0xDC00 || 0xE000 <= u2) - { - error("surrogate UTF-16 low value %04x out of range", u2); - return null; - } - u = (u - 0xD7C0) << 10; - u |= (u2 - 0xDC00); - } - else if (u >= 0xDC00 && u <= 0xDFFF) - { - error("unpaired surrogate UTF-16 value %04x", u); - return null; - } - else if (u == 0xFFFE || u == 0xFFFF) - { - error("illegal UTF-16 value %04x", u); - return null; - } - dbuf.writeUTF8(u); - } - else - dbuf.writeByte(u); - } - dbuf.writeByte(0); //add a terminating null byte - return dbuf.extractSlice(); - } - const(char)* srcname = srcfile.toChars(); //printf("Module::parse(srcname = '%s')\n", srcname); isPackageFile = isPackageFileName(srcfile); - const(char)[] buf = cast(const(char)[]) this.src; - - bool needsReencoding = true; - bool hasBOM = true; //assume there's a BOM - Endian endian; - SourceEncoding sourceEncoding; - - if (buf.length >= 2) - { - /* Convert all non-UTF-8 formats to UTF-8. - * BOM : https://www.unicode.org/faq/utf_bom.html - * 00 00 FE FF UTF-32BE, big-endian - * FF FE 00 00 UTF-32LE, little-endian - * FE FF UTF-16BE, big-endian - * FF FE UTF-16LE, little-endian - * EF BB BF UTF-8 - */ - if (buf[0] == 0xFF && buf[1] == 0xFE) - { - endian = Endian.little; - - sourceEncoding = buf.length >= 4 && buf[2] == 0 && buf[3] == 0 - ? SourceEncoding.utf32 - : SourceEncoding.utf16; - } - else if (buf[0] == 0xFE && buf[1] == 0xFF) - { - endian = Endian.big; - sourceEncoding = SourceEncoding.utf16; - } - else if (buf.length >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF) - { - endian = Endian.big; - sourceEncoding = SourceEncoding.utf32; - } - else if (buf.length >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) - { - needsReencoding = false;//utf8 with BOM - } - else - { - /* There is no BOM. Make use of Arcane Jill's insight that - * the first char of D source must be ASCII to - * figure out the encoding. - */ - hasBOM = false; - if (buf.length >= 4 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) - { - endian = Endian.little; - sourceEncoding = SourceEncoding.utf32; - } - else if (buf.length >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0) - { - endian = Endian.big; - sourceEncoding = SourceEncoding.utf32; - } - else if (buf.length >= 2 && buf[1] == 0) //try to check for UTF-16 - { - endian = Endian.little; - sourceEncoding = SourceEncoding.utf16; - } - else if (buf[0] == 0) - { - endian = Endian.big; - sourceEncoding = SourceEncoding.utf16; - } - else { - // It's UTF-8 - needsReencoding = false; - if (buf[0] >= 0x80) - { - error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]); - return null; - } - } - } - //throw away BOM - if (hasBOM) - { - if (!needsReencoding) buf = buf[3..$];// utf-8 already - else if (sourceEncoding == SourceEncoding.utf32) buf = buf[4..$]; - else buf = buf[2..$]; //utf 16 - } - } - // Assume the buffer is from memory and has not be read from disk. Assume UTF-8. - else if (buf.length >= 1 && (buf[0] == '\0' || buf[0] == 0x1A)) - needsReencoding = false; - //printf("%s, %d, %d, %d\n", srcfile.name.toChars(), needsReencoding, endian == Endian.little, sourceEncoding == SourceEncoding.utf16); - if (needsReencoding) - { - if (sourceEncoding == SourceEncoding.utf16) - { - buf = endian == Endian.little - ? UTF16ToUTF8!(Endian.little)(buf) - : UTF16ToUTF8!(Endian.big)(buf); - } - else - { - buf = endian == Endian.little - ? UTF32ToUTF8!(Endian.little)(buf) - : UTF32ToUTF8!(Endian.big)(buf); - } - // an error happened on UTF conversion - if (buf is null) return null; - } + const(char)[] buf = processSource(src, this); + // an error happened on UTF conversion + if (buf is null) return null; /* If it starts with the string "Ddoc", then it's a documentation * source file. @@ -1533,3 +1323,192 @@ extern (C++) struct ModuleDeclaration return this.toChars().toDString; } } + +/** + * Process the content of a source file + * + * Attempts to find which encoding it is using, if it has BOM, + * and then normalize the source to UTF-8. If no encoding is required, + * a slice of `src` will be returned without extra allocation. + * + * Params: + * src = Content of the source file to process + * mod = Module matching `src`, used for error handling + * + * Returns: + * UTF-8 encoded variant of `src`, stripped of any BOM, + * or `null` if an error happened. + */ +private const(char)[] processSource (const(ubyte)[] src, Module mod) +{ + enum SourceEncoding { utf16, utf32} + enum Endian { little, big} + + /* + * Convert a buffer from UTF32 to UTF8 + * Params: + * Endian = is the buffer big/little endian + * buf = buffer of UTF32 data + * Returns: + * input buffer reencoded as UTF8 + */ + + char[] UTF32ToUTF8(Endian endian)(const(char)[] buf) + { + static if (endian == Endian.little) + alias readNext = Port.readlongLE; + else + alias readNext = Port.readlongBE; + + if (buf.length & 3) + { + mod.error("odd length of UTF-32 char source %llu", cast(ulong) buf.length); + return null; + } + + const (uint)[] eBuf = cast(const(uint)[])buf; + + OutBuffer dbuf; + dbuf.reserve(eBuf.length); + + foreach (i; 0 .. eBuf.length) + { + const u = readNext(&eBuf[i]); + if (u & ~0x7F) + { + if (u > 0x10FFFF) + { + mod.error("UTF-32 value %08x greater than 0x10FFFF", u); + return null; + } + dbuf.writeUTF8(u); + } + else + dbuf.writeByte(u); + } + dbuf.writeByte(0); //add null terminator + return dbuf.extractSlice(); + } + + /* + * Convert a buffer from UTF16 to UTF8 + * Params: + * Endian = is the buffer big/little endian + * buf = buffer of UTF16 data + * Returns: + * input buffer reencoded as UTF8 + */ + + char[] UTF16ToUTF8(Endian endian)(const(char)[] buf) + { + static if (endian == Endian.little) + alias readNext = Port.readwordLE; + else + alias readNext = Port.readwordBE; + + if (buf.length & 1) + { + mod.error("odd length of UTF-16 char source %llu", cast(ulong) buf.length); + return null; + } + + const (ushort)[] eBuf = cast(const(ushort)[])buf; + + OutBuffer dbuf; + dbuf.reserve(eBuf.length); + + //i will be incremented in the loop for high codepoints + foreach (ref i; 0 .. eBuf.length) + { + uint u = readNext(&eBuf[i]); + if (u & ~0x7F) + { + if (0xD800 <= u && u < 0xDC00) + { + i++; + if (i >= eBuf.length) + { + mod.error("surrogate UTF-16 high value %04x at end of file", u); + return null; + } + const u2 = readNext(&eBuf[i]); + if (u2 < 0xDC00 || 0xE000 <= u2) + { + mod.error("surrogate UTF-16 low value %04x out of range", u2); + return null; + } + u = (u - 0xD7C0) << 10; + u |= (u2 - 0xDC00); + } + else if (u >= 0xDC00 && u <= 0xDFFF) + { + mod.error("unpaired surrogate UTF-16 value %04x", u); + return null; + } + else if (u == 0xFFFE || u == 0xFFFF) + { + mod.error("illegal UTF-16 value %04x", u); + return null; + } + dbuf.writeUTF8(u); + } + else + dbuf.writeByte(u); + } + dbuf.writeByte(0); //add a terminating null byte + return dbuf.extractSlice(); + } + + const(char)[] buf = cast(const(char)[]) src; + + // Assume the buffer is from memory and has not be read from disk. Assume UTF-8. + if (buf.length < 2) + return buf; + + /* Convert all non-UTF-8 formats to UTF-8. + * BOM : https://www.unicode.org/faq/utf_bom.html + * 00 00 FE FF UTF-32BE, big-endian + * FF FE 00 00 UTF-32LE, little-endian + * FE FF UTF-16BE, big-endian + * FF FE UTF-16LE, little-endian + * EF BB BF UTF-8 + */ + if (buf[0] == 0xFF && buf[1] == 0xFE) + { + if (buf.length >= 4 && buf[2] == 0 && buf[3] == 0) + return UTF32ToUTF8!(Endian.little)(buf[4 .. $]); + return UTF16ToUTF8!(Endian.little)(buf[2 .. $]); + } + + if (buf[0] == 0xFE && buf[1] == 0xFF) + return UTF16ToUTF8!(Endian.big)(buf[2 .. $]); + + if (buf.length >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF) + return UTF32ToUTF8!(Endian.big)(buf[4 .. $]); + + if (buf.length >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) + return buf[3 .. $]; + + /* There is no BOM. Make use of Arcane Jill's insight that + * the first char of D source must be ASCII to + * figure out the encoding. + */ + if (buf.length >= 4 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) + return UTF32ToUTF8!(Endian.little)(buf); + if (buf.length >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0) + return UTF32ToUTF8!(Endian.big)(buf); + // try to check for UTF-16 + if (buf.length >= 2 && buf[1] == 0) + return UTF16ToUTF8!(Endian.little)(buf); + if (buf[0] == 0) + return UTF16ToUTF8!(Endian.big)(buf); + + // It's UTF-8 + if (buf[0] >= 0x80) + { + mod.error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]); + return null; + } + + return buf; +} diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d index 9c30978..c816759 100644 --- a/gcc/d/dmd/dscope.d +++ b/gcc/d/dmd/dscope.d @@ -63,17 +63,13 @@ enum SCOPE free = 0x8000, /// is on free list fullinst = 0x10000, /// fully instantiate templates - - // The following are mutually exclusive - printf = 0x4_0000, /// printf-style function - scanf = 0x8_0000, /// scanf-style function } /// Flags that are carried along with a scope push() private enum PersistentFlags = SCOPE.contract | SCOPE.debug_ | SCOPE.ctfe | SCOPE.compile | SCOPE.constraint | SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility | - SCOPE.printf | SCOPE.scanf | SCOPE.Cfile; + SCOPE.Cfile; struct Scope { diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d index 4126a8a..1c2f226 100644 --- a/gcc/d/dmd/dstruct.d +++ b/gcc/d/dmd/dstruct.d @@ -216,6 +216,11 @@ extern (C++) class StructDeclaration : AggregateDeclaration bool hasIdentityEquals; // true if has identity opEquals bool hasNoFields; // has no fields bool hasCopyCtor; // copy constructor + bool hasPointerField; // members with indirections + bool hasVoidInitPointers; // void-initialized unsafe fields + bool hasSystemFields; // @system members + bool hasFieldWithInvariant; // invariants + bool computedTypeProperties;// the above 3 fields are computed // Even if struct is defined as non-root symbol, some built-in operations // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. // For those, today TypeInfo_Struct is generated in COMDAT. @@ -223,7 +228,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration } import dmd.common.bitfields : generateBitFields; - mixin(generateBitFields!(BitFields, ubyte)); + mixin(generateBitFields!(BitFields, ushort)); extern (D) this(const ref Loc loc, Identifier id, bool inObject) { @@ -391,9 +396,35 @@ extern (C++) class StructDeclaration : AggregateDeclaration } } + argTypes = target.toArgTypes(type); } + /// Compute cached type properties for `TypeStruct` + extern(D) final void determineTypeProperties() + { + if (computedTypeProperties) + return; + foreach (vd; fields) + { + if (vd.storage_class & STC.ref_ || vd.hasPointers()) + hasPointerField = true; + + if (vd._init && vd._init.isVoidInitializer() && vd.type.hasPointers()) + hasVoidInitPointers = true; + + if (vd.storage_class & STC.system || vd.type.hasSystemFields()) + hasSystemFields = true; + + if (!vd._init && vd.type.hasVoidInitPointers()) + hasVoidInitPointers = true; + + if (vd.type.hasInvariant()) + hasFieldWithInvariant = true; + } + computedTypeProperties = true; + } + /*************************************** * Determine if struct is POD (Plain Old Data). * diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index 7e2d02f..2f10e83 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -236,25 +236,33 @@ struct FieldState bool inFlight; /// bit field is in flight } +// 99.9% of Dsymbols don't have attributes (at least in druntime and Phobos), +// so save memory by grouping them into a separate struct +private struct DsymbolAttributes +{ + /// C++ namespace this symbol belongs to + CPPNamespaceDeclaration cppnamespace; + /// customized deprecation message + DeprecatedDeclaration depdecl_; + /// user defined attributes + UserAttributeDeclaration userAttribDecl; +} + /*********************************************************** */ extern (C++) class Dsymbol : ASTNode { Identifier ident; Dsymbol parent; - /// C++ namespace this symbol belongs to - CPPNamespaceDeclaration cppnamespace; Symbol* csym; // symbol for code generator const Loc loc; // where defined Scope* _scope; // !=null means context to use for semantic() const(char)* prettystring; // cached value of toPrettyChars() + private DsymbolAttributes* atts; /// attached attribute declarations bool errors; // this symbol failed to pass semantic() PASS semanticRun = PASS.initial; ushort localNum; /// perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab - DeprecatedDeclaration depdecl; // customized deprecation message - UserAttributeDeclaration userAttribDecl; // user defined attributes - final extern (D) this() nothrow { //printf("Dsymbol::Dsymbol(%p)\n", this); @@ -285,6 +293,42 @@ extern (C++) class Dsymbol : ASTNode return ident ? ident.toChars() : "__anonymous"; } + // Getters / setters for fields stored in `DsymbolAttributes` + final nothrow pure @safe + { + private ref DsymbolAttributes getAtts() + { + if (!atts) + atts = new DsymbolAttributes(); + return *atts; + } + + inout(DeprecatedDeclaration) depdecl() inout { return atts ? atts.depdecl_ : null; } + inout(CPPNamespaceDeclaration) cppnamespace() inout { return atts ? atts.cppnamespace : null; } + inout(UserAttributeDeclaration) userAttribDecl() inout { return atts ? atts.userAttribDecl : null; } + + DeprecatedDeclaration depdecl(DeprecatedDeclaration dd) + { + if (!dd && !atts) + return null; + return getAtts().depdecl_ = dd; + } + + CPPNamespaceDeclaration cppnamespace(CPPNamespaceDeclaration ns) + { + if (!ns && !atts) + return null; + return getAtts().cppnamespace = ns; + } + + UserAttributeDeclaration userAttribDecl(UserAttributeDeclaration uad) + { + if (!uad && !atts) + return null; + return getAtts().userAttribDecl = uad; + } + } + // helper to print fully qualified (template) arguments const(char)* toPrettyCharsHelper() { diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index acf0004..3e9b634 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -167,25 +167,31 @@ struct FieldState bool inFlight; }; +struct DsymbolAttributes; + class Dsymbol : public ASTNode { public: Identifier *ident; Dsymbol *parent; - /// C++ namespace this symbol belongs to - CPPNamespaceDeclaration *namespace_; Symbol *csym; // symbol for code generator Loc loc; // where defined Scope *_scope; // !=NULL means context to use for semantic() const utf8_t *prettystring; +private: + DsymbolAttributes* atts; +public: bool errors; // this symbol failed to pass semantic() PASS semanticRun; unsigned short localNum; // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab - DeprecatedDeclaration *depdecl; // customized deprecation message - UserAttributeDeclaration *userAttribDecl; // user defined attributes - static Dsymbol *create(Identifier *); const char *toChars() const override; + DeprecatedDeclaration* depdecl(); + CPPNamespaceDeclaration* cppnamespace(); + UserAttributeDeclaration* userAttribDecl(); + DeprecatedDeclaration* depdecl(DeprecatedDeclaration* dd); + CPPNamespaceDeclaration* cppnamespace(CPPNamespaceDeclaration* ns); + UserAttributeDeclaration* userAttribDecl(UserAttributeDeclaration* uad); virtual const char *toPrettyCharsHelper(); // helper to print fully qualified (template) arguments Loc getLoc(); const char *locToChars(); diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 701f06a..b877828 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -98,6 +98,29 @@ private uint setMangleOverride(Dsymbol s, const(char)[] sym) return 0; } +/** + * Apply pragma printf/scanf to FuncDeclarations under `s`, + * poking through attribute declarations such as `extern(C)` + * but not through aggregates or function bodies. + * + * Params: + * s = symbol to apply + * printf = `true` for printf, `false` for scanf + */ +private void setPragmaPrintf(Dsymbol s, bool printf) +{ + if (auto fd = s.isFuncDeclaration()) + { + fd.printf = printf; + fd.scanf = !printf; + } + + if (auto ad = s.isAttribDeclaration()) + { + ad.include(null).foreachDsymbol( (s) { setPragmaPrintf(s, printf); } ); + } +} + /************************************* * Does semantic analysis on the public face of declarations. */ @@ -855,17 +878,20 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } // Calculate type size + safety checks - if (1) + if (sc && sc.func) { - if (dsym._init && dsym._init.isVoidInitializer() && - (dsym.type.hasPointers() || dsym.type.hasInvariant())) // also computes type size + if (dsym._init && dsym._init.isVoidInitializer()) { - if (dsym.type.hasPointers()) + + if (dsym.type.hasPointers()) // also computes type size sc.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions"); - else + else if (dsym.type.hasInvariant()) sc.setUnsafe(false, dsym.loc, "`void` initializers for structs with invariants are not allowed in safe functions"); + else if (dsym.type.hasSystemFields()) + sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc, + "`void` initializers for `@system` variables not allowed in safe functions"); } else if (!dsym._init && !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) && @@ -1036,6 +1062,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (f.tookAddressOf) f.tookAddressOf--; } + else if (auto ale = ex.isArrayLiteralExp()) + { + // or an array literal assigned to a `scope` variable + if (!dsym.type.nextOf().needsDestruction()) + ale.onstack = true; + } } Expression exp = ei.exp; @@ -1200,7 +1232,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor override void visit(BitFieldDeclaration dsym) { - //printf("BitField::semantic('%s') %s\n", toPrettyChars(), id.toChars()); + //printf("BitField::semantic('%s')\n", dsym.toChars()); if (dsym.semanticRun >= PASS.semanticdone) return; @@ -1558,6 +1590,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor foreach (s; (*pd.decl)[]) { + if (pd.ident == Id.printf || pd.ident == Id.scanf) + { + s.setPragmaPrintf(pd.ident == Id.printf); + continue; + } + s.dsymbolSemantic(sc2); if (pd.ident != Id.mangle) continue; @@ -1574,13 +1612,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor agg = tc.sym; else if (auto ts = e.type.isTypeStruct()) agg = ts.sym; - ad.mangleOverride = new MangleOverride; + ad.pMangleOverride = new MangleOverride; void setString(ref Expression e) { if (auto se = verifyMangleString(e)) { const name = (cast(const(char)[])se.peekData()).xarraydup; - ad.mangleOverride.id = Identifier.idPool(name); + ad.pMangleOverride.id = Identifier.idPool(name); e = se; } else @@ -1588,13 +1626,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } if (agg) { - ad.mangleOverride.agg = agg; + ad.pMangleOverride.agg = agg; if (pd.args.dim == 2) { setString((*pd.args)[1]); } else - ad.mangleOverride.id = agg.ident; + ad.pMangleOverride.id = agg.ident; } else setString((*pd.args)[0]); @@ -1649,29 +1687,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!pd.args) return noDeclarations(); - for (size_t i = 0; i < pd.args.dim; i++) - { - Expression e = (*pd.args)[i]; - sc = sc.startCTFE(); - e = e.expressionSemantic(sc); - e = resolveProperties(sc, e); - sc = sc.endCTFE(); - e = ctfeInterpretForPragmaMsg(e); - if (e.op == EXP.error) - { - errorSupplemental(pd.loc, "while evaluating `pragma(msg, %s)`", (*pd.args)[i].toChars()); - return; - } - StringExp se = e.toStringExp(); - if (se) - { - se = se.toUTF8(sc); - fprintf(stderr, "%.*s", cast(int)se.len, se.peekString().ptr); - } - else - fprintf(stderr, "%s", e.toChars()); - } - fprintf(stderr, "\n"); + if (!pragmaMsgSemantic(pd.loc, sc, pd.args)) + return; return noDeclarations(); } @@ -1707,33 +1724,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } else if (pd.ident == Id.startaddress) { - if (!pd.args || pd.args.dim != 1) - pd.error("function name expected for start address"); - else - { - /* https://issues.dlang.org/show_bug.cgi?id=11980 - * resolveProperties and ctfeInterpret call are not necessary. - */ - Expression e = (*pd.args)[0]; - sc = sc.startCTFE(); - e = e.expressionSemantic(sc); - sc = sc.endCTFE(); - (*pd.args)[0] = e; - Dsymbol sa = getDsymbol(e); - if (!sa || !sa.isFuncDeclaration()) - pd.error("function name expected for start address, not `%s`", e.toChars()); - } + pragmaStartAddressSemantic(pd.loc, sc, pd.args); return noDeclarations(); } else if (pd.ident == Id.Pinline) { - if (pd.args && pd.args.dim > 1) - { - pd.error("one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) pd.args.dim); - pd.args.setDim(1); - (*pd.args)[0] = ErrorExp.get(); - } - // this pragma now gets evaluated on demand in function semantic return declarations(); @@ -1774,7 +1769,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } else if (auto f = s.isFuncDeclaration()) { - f.flags |= isCtor ? FUNCFLAG.CRTCtor : FUNCFLAG.CRTDtor; + if (isCtor) + f.isCrtCtor = true; + else + f.isCrtDtor = true; + return 1; } else @@ -3048,7 +3047,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor //printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal()); if (sc.flags & SCOPE.compile) - funcdecl.flags |= FUNCFLAG.compileTimeOnly; // don't emit code for this function + funcdecl.isCompileTimeOnly = true; // don't emit code for this function funcdecl._linkage = sc.linkage; if (auto fld = funcdecl.isFuncLiteralDeclaration()) @@ -3069,7 +3068,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // evaluate pragma(inline) if (auto pragmadecl = sc.inlining) - funcdecl.inlining = pragmadecl.evalPragmaInline(sc); + funcdecl.inlining = evalPragmaInline(pragmadecl.loc, sc, pragmadecl.args); funcdecl.visibility = sc.visibility; funcdecl.userAttribDecl = sc.userAttribDecl; @@ -3269,9 +3268,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } // check pragma(crt_constructor) signature - if (funcdecl.flags & (FUNCFLAG.CRTCtor | FUNCFLAG.CRTDtor)) + if (funcdecl.isCrtCtor || funcdecl.isCrtDtor) { - const idStr = (funcdecl.flags & FUNCFLAG.CRTCtor) ? "crt_constructor" : "crt_destructor"; + const idStr = funcdecl.isCrtCtor ? "crt_constructor" : "crt_destructor"; if (f.nextOf().ty != Tvoid) funcdecl.error("must return `void` for `pragma(%s)`", idStr.ptr); if (funcdecl._linkage != LINK.c && f.parameterList.length != 0) @@ -3351,7 +3350,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } } - if (const pors = sc.flags & (SCOPE.printf | SCOPE.scanf)) + if (funcdecl.printf || funcdecl.scanf) { /* printf/scanf-like functions must be of the form: * extern (C/C++) T printf([parameters...], const(char)* format, ...); @@ -3387,11 +3386,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor ) ) { - funcdecl.flags |= (pors == SCOPE.printf) ? FUNCFLAG.printf : FUNCFLAG.scanf; + // the signature is valid for printf/scanf, no error } else { - const p = (pors == SCOPE.printf ? Id.printf : Id.scanf).toChars(); + const p = (funcdecl.printf ? Id.printf : Id.scanf).toChars(); if (f.parameterList.varargs == VarArg.variadic) { funcdecl.error("`pragma(%s)` functions must be `extern(C) %s %s([parameters...], const(char)*, ...)`" @@ -3538,7 +3537,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor else { //printf("\tintroducing function %s\n", funcdecl.toChars()); - funcdecl.flags |= FUNCFLAG.introducing; + funcdecl.isIntroducing = true; if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads) { /* Overloaded functions with same name are grouped and in reverse order. @@ -4555,13 +4554,16 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (sd.semanticRun == PASS.initial) sd.type = sd.type.addSTC(sc.stc | sd.storage_class); sd.type = sd.type.typeSemantic(sd.loc, sc); - if (auto ts = sd.type.isTypeStruct()) + auto ts = sd.type.isTypeStruct(); + if (ts) + { if (ts.sym != sd) { auto ti = ts.sym.isInstantiated(); if (ti && isError(ti)) ts.sym = sd; } + } // Ungag errors when not speculative Ungag ungag = sd.ungagSpeculative(); @@ -4699,16 +4701,26 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } } - if (sd.type.ty == Tstruct && (cast(TypeStruct)sd.type).sym != sd) + if (ts && ts.sym != sd) { - // https://issues.dlang.org/show_bug.cgi?id=19024 - StructDeclaration sym = (cast(TypeStruct)sd.type).sym; - version (none) + StructDeclaration sym = ts.sym; + if (sd.isCsymbol() && sym.isCsymbol()) + { + /* This is two structs imported from different C files. + * Just ignore sd, the second one. The first one will always + * be found when going through the type. + */ + } + else { - printf("this = %p %s\n", sd, sd.toChars()); - printf("type = %d sym = %p, %s\n", sd.type.ty, sym, sym.toPrettyChars()); + version (none) + { + printf("this = %p %s\n", sd, sd.toChars()); + printf("type = %d sym = %p, %s\n", sd.type.ty, sym, sym.toPrettyChars()); + } + // https://issues.dlang.org/show_bug.cgi?id=19024 + sd.error("already exists at %s. Perhaps in another function with the same name?", sym.loc.toChars()); } - sd.error("already exists at %s. Perhaps in another function with the same name?", sym.loc.toChars()); } if (global.errors != errors) @@ -5291,7 +5303,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf); ctor.storage_class |= STC.inference; - ctor.flags |= FUNCFLAG.generated; + ctor.isGenerated = true; ctor.fbody = new CompoundStatement(Loc.initial, new Statements()); cldec.members.push(ctor); @@ -7099,3 +7111,47 @@ private CallExp doAtomicOp (string op, Identifier var, Expression arg) return CallExp.create(loc, dti, args); } + +/*************************************** + * Interpret a `pragma(inline, x)` + * + * Params: + * loc = location for error messages + * sc = scope for evaluation of argument + * args = pragma arguments + * Returns: corresponding `PINLINE` state + */ +PINLINE evalPragmaInline(Loc loc, Scope* sc, Expressions* args) +{ + if (!args || args.dim == 0) + return PINLINE.default_; + + if (args && args.dim > 1) + { + .error(loc, "one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) args.dim); + args.setDim(1); + (*args)[0] = ErrorExp.get(); + } + + Expression e = (*args)[0]; + if (!e.type) + { + sc = sc.startCTFE(); + e = e.expressionSemantic(sc); + e = resolveProperties(sc, e); + sc = sc.endCTFE(); + e = e.ctfeInterpret(); + e = e.toBoolean(sc); + if (e.isErrorExp()) + .error(loc, "pragma(`inline`, `true` or `false`) expected, not `%s`", (*args)[0].toChars()); + (*args)[0] = e; + } + + const opt = e.toBool(); + if (opt.isEmpty()) + return PINLINE.default_; + else if (opt.get()) + return PINLINE.always; + else + return PINLINE.never; +} diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 13efc1c..1f99c58 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -1173,7 +1173,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf); fd.parent = ti; - fd.flags |= FUNCFLAG.inferRetType; + fd.inferRetType = true; // Shouldn't run semantic on default arguments and return type. foreach (ref param; *tf.parameterList.parameters) @@ -3901,7 +3901,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param // https://issues.dlang.org/show_bug.cgi?id=2579 // Apply function parameter storage classes to parameter types fparam.type = fparam.type.addStorageClass(fparam.storageClass); - fparam.storageClass &= ~(STC.TYPECTOR | STC.in_); + fparam.storageClass &= ~STC.TYPECTOR; // https://issues.dlang.org/show_bug.cgi?id=15243 // Resolve parameter type if it's not related with template parameters diff --git a/gcc/d/dmd/entity.d b/gcc/d/dmd/entity.d index c29d499..2b499c1 100644 --- a/gcc/d/dmd/entity.d +++ b/gcc/d/dmd/entity.d @@ -25,7 +25,7 @@ nothrow: * code point corresponding to the named entity * ~0 for not recognized as a named entity */ -public uint HtmlNamedEntity(scope const char[] name) pure @nogc @safe +public uint[2] HtmlNamedEntity(scope const char[] name) pure @nogc @safe { const firstC = tolower(name[0]); if (firstC >= 'a' && firstC <= 'z') @@ -34,10 +34,10 @@ public uint HtmlNamedEntity(scope const char[] name) pure @nogc @safe foreach (entity; namesTable[firstC - 'a']) { if (entity.name == name) - return entity.value; + return [entity.value, entity.value2]; } } - return ~0; + return [0, 0]; } private: @@ -52,6 +52,7 @@ struct NameId { string name; uint value; + uint value2; } // @todo@ order namesTable and names? by frequency @@ -72,7 +73,7 @@ immutable NameId[] namesA = {"abreve", 0x00103}, // LATIN SMALL LETTER A WITH BREVE {"ac", 0x0223E}, // INVERTED LAZY S {"acd", 0x0223F}, // SINE WAVE -// {"acE", 0x0223E;0x00333}, // INVERTED LAZY S with double underline + {"acE", 0x0223E, 0x00333}, // INVERTED LAZY S with double underline {"Acirc", 0x000C2}, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX {"acirc", 0x000E2}, // LATIN SMALL LETTER A WITH CIRCUMFLEX {"acute", 0x000B4}, // ACUTE ACCENT @@ -157,42 +158,30 @@ immutable NameId[] namesB = {"backsim", 0x0223D}, // REVERSED TILDE {"backsimeq", 0x022CD}, // REVERSED TILDE EQUALS {"Backslash", 0x02216}, // SET MINUS -// "b.alpha", 0x1D6C2}, // MATHEMATICAL BOLD SMALL ALPHA {"Barv", 0x02AE7}, // SHORT DOWN TACK WITH OVERBAR {"barvee", 0x022BD}, // NOR {"barwed", 0x02305}, // PROJECTIVE {"Barwed", 0x02306}, // PERSPECTIVE {"barwedge", 0x02305}, // PROJECTIVE -// "b.beta", 0x1D6C3}, // MATHEMATICAL BOLD SMALL BETA {"bbrk", 0x023B5}, // BOTTOM SQUARE BRACKET {"bbrktbrk", 0x023B6}, // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET -// "b.chi", 0x1D6D8}, // MATHEMATICAL BOLD SMALL CHI {"bcong", 0x0224C}, // ALL EQUAL TO {"Bcy", 0x00411}, // CYRILLIC CAPITAL LETTER BE {"bcy", 0x00431}, // CYRILLIC SMALL LETTER BE -// "b.Delta", 0x1D6AB}, // MATHEMATICAL BOLD CAPITAL DELTA -// "b.delta", 0x1D6C5}, // MATHEMATICAL BOLD SMALL DELTA {"bdquo", 0x0201E}, // DOUBLE LOW-9 QUOTATION MARK {"becaus", 0x02235}, // BECAUSE {"because", 0x02235}, // BECAUSE {"Because", 0x02235}, // BECAUSE {"bemptyv", 0x029B0}, // REVERSED EMPTY SET {"bepsi", 0x003F6}, // GREEK REVERSED LUNATE EPSILON SYMBOL -// "b.epsi", 0x1D6C6}, // MATHEMATICAL BOLD SMALL EPSILON -// "b.epsiv", 0x1D6DC}, // MATHEMATICAL BOLD EPSILON SYMBOL {"bernou", 0x0212C}, // SCRIPT CAPITAL B {"Bernoullis", 0x0212C}, // SCRIPT CAPITAL B {"Beta", 0x00392}, // GREEK CAPITAL LETTER BETA {"beta", 0x003B2}, // GREEK SMALL LETTER BETA -// "b.eta", 0x1D6C8}, // MATHEMATICAL BOLD SMALL ETA {"beth", 0x02136}, // BET SYMBOL {"between", 0x0226C}, // BETWEEN {"Bfr", 0x1D505}, // MATHEMATICAL FRAKTUR CAPITAL B {"bfr", 0x1D51F}, // MATHEMATICAL FRAKTUR SMALL B -// "b.Gamma", 0x1D6AA}, // MATHEMATICAL BOLD CAPITAL GAMMA -// "b.gamma", 0x1D6C4}, // MATHEMATICAL BOLD SMALL GAMMA -// "b.Gammad", 0x1D7CA}, // MATHEMATICAL BOLD CAPITAL DIGAMMA -// "b.gammad", 0x1D7CB}, // MATHEMATICAL BOLD SMALL DIGAMMA {"Bgr", 0x00392}, // GREEK CAPITAL LETTER BETA {"bgr", 0x003B2}, // GREEK SMALL LETTER BETA {"bigcap", 0x022C2}, // N-ARY INTERSECTION @@ -208,9 +197,6 @@ immutable NameId[] namesB = {"biguplus", 0x02A04}, // N-ARY UNION OPERATOR WITH PLUS {"bigvee", 0x022C1}, // N-ARY LOGICAL OR {"bigwedge", 0x022C0}, // N-ARY LOGICAL AND -// "b.iota", 0x1D6CA}, // MATHEMATICAL BOLD SMALL IOTA -// "b.kappa", 0x1D6CB}, // MATHEMATICAL BOLD SMALL KAPPA -// "b.kappav", 0x1D6DE}, // MATHEMATICAL BOLD KAPPA SYMBOL {"bkarow", 0x0290D}, // RIGHTWARDS DOUBLE DASH ARROW {"blacklozenge", 0x029EB}, // BLACK LOZENGE {"blacksquare", 0x025AA}, // BLACK SMALL SQUARE @@ -218,21 +204,15 @@ immutable NameId[] namesB = {"blacktriangledown", 0x025BE}, // BLACK DOWN-POINTING SMALL TRIANGLE {"blacktriangleleft", 0x025C2}, // BLACK LEFT-POINTING SMALL TRIANGLE {"blacktriangleright", 0x025B8}, // BLACK RIGHT-POINTING SMALL TRIANGLE -// "b.Lambda", 0x1D6B2}, // MATHEMATICAL BOLD CAPITAL LAMDA -// "b.lambda", 0x1D6CC}, // MATHEMATICAL BOLD SMALL LAMDA {"blank", 0x02423}, // OPEN BOX {"blk12", 0x02592}, // MEDIUM SHADE {"blk14", 0x02591}, // LIGHT SHADE {"blk34", 0x02593}, // DARK SHADE {"block", 0x02588}, // FULL BLOCK -// "b.mu", 0x1D6CD}, // MATHEMATICAL BOLD SMALL MU -// "bne", 0x0003D;0x020E5}, // EQUALS SIGN with reverse slash -// "bnequiv", 0x02261;0x020E5}, // IDENTICAL TO with reverse slash + {"bne", 0x0003D, 0x020E5}, // EQUALS SIGN with reverse slash + {"bnequiv", 0x02261, 0x020E5}, // IDENTICAL TO with reverse slash {"bnot", 0x02310}, // REVERSED NOT SIGN {"bNot", 0x02AED}, // REVERSED DOUBLE STROKE NOT SIGN -// "b.nu", 0x1D6CE}, // MATHEMATICAL BOLD SMALL NU -// "b.Omega", 0x1D6C0}, // MATHEMATICAL BOLD CAPITAL OMEGA -// "b.omega", 0x1D6DA}, // MATHEMATICAL BOLD SMALL OMEGA {"Bopf", 0x1D539}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL B {"bopf", 0x1D553}, // MATHEMATICAL DOUBLE-STRUCK SMALL B {"bot", 0x022A5}, // UP TACK @@ -282,35 +262,18 @@ immutable NameId[] namesB = {"boxvR", 0x0255E}, // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE {"boxVr", 0x0255F}, // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE {"boxVR", 0x02560}, // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT -// "b.Phi", 0x1D6BD}, // MATHEMATICAL BOLD CAPITAL PHI -// "b.phi", 0x1D6D7}, // MATHEMATICAL BOLD SMALL PHI -// "b.phiv", 0x1D6DF}, // MATHEMATICAL BOLD PHI SYMBOL -// "b.Pi", 0x1D6B7}, // MATHEMATICAL BOLD CAPITAL PI -// "b.pi", 0x1D6D1}, // MATHEMATICAL BOLD SMALL PI -// "b.piv", 0x1D6E1}, // MATHEMATICAL BOLD PI SYMBOL {"bprime", 0x02035}, // REVERSED PRIME -// "b.Psi", 0x1D6BF}, // MATHEMATICAL BOLD CAPITAL PSI -// "b.psi", 0x1D6D9}, // MATHEMATICAL BOLD SMALL PSI {"breve", 0x002D8}, // BREVE {"Breve", 0x002D8}, // BREVE -// "b.rho", 0x1D6D2}, // MATHEMATICAL BOLD SMALL RHO -// "b.rhov", 0x1D6E0}, // MATHEMATICAL BOLD RHO SYMBOL {"brvbar", 0x000A6}, // BROKEN BAR {"Bscr", 0x0212C}, // SCRIPT CAPITAL B {"bscr", 0x1D4B7}, // MATHEMATICAL SCRIPT SMALL B {"bsemi", 0x0204F}, // REVERSED SEMICOLON -// "b.Sigma", 0x1D6BA}, // MATHEMATICAL BOLD CAPITAL SIGMA -// "b.sigma", 0x1D6D4}, // MATHEMATICAL BOLD SMALL SIGMA -// "b.sigmav", 0x1D6D3}, // MATHEMATICAL BOLD SMALL FINAL SIGMA {"bsim", 0x0223D}, // REVERSED TILDE {"bsime", 0x022CD}, // REVERSED TILDE EQUALS {"bsol", 0x0005C}, // REVERSE SOLIDUS {"bsolb", 0x029C5}, // SQUARED FALLING DIAGONAL SLASH {"bsolhsub", 0x027C8}, // REVERSE SOLIDUS PRECEDING SUBSET -// "b.tau", 0x1D6D5}, // MATHEMATICAL BOLD SMALL TAU -// "b.Theta", 0x1D6AF}, // MATHEMATICAL BOLD CAPITAL THETA -// "b.thetas", 0x1D6C9}, // MATHEMATICAL BOLD SMALL THETA -// "b.thetav", 0x1D6DD}, // MATHEMATICAL BOLD THETA SYMBOL {"bull", 0x02022}, // BULLET {"bullet", 0x02022}, // BULLET {"bump", 0x0224E}, // GEOMETRICALLY EQUIVALENT TO @@ -318,11 +281,6 @@ immutable NameId[] namesB = {"bumpE", 0x02AAE}, // EQUALS SIGN WITH BUMPY ABOVE {"Bumpeq", 0x0224E}, // GEOMETRICALLY EQUIVALENT TO {"bumpeq", 0x0224F}, // DIFFERENCE BETWEEN -// "b.Upsi", 0x1D6BC}, // MATHEMATICAL BOLD CAPITAL UPSILON -// "b.upsi", 0x1D6D6}, // MATHEMATICAL BOLD SMALL UPSILON -// "b.Xi", 0x1D6B5}, // MATHEMATICAL BOLD CAPITAL XI -// "b.xi", 0x1D6CF}, // MATHEMATICAL BOLD SMALL XI -// "b.zeta", 0x1D6C7}, // MATHEMATICAL BOLD SMALL ZETA ]; immutable NameId[] namesC = @@ -337,7 +295,7 @@ immutable NameId[] namesC = {"capcup", 0x02A47}, // INTERSECTION ABOVE UNION {"capdot", 0x02A40}, // INTERSECTION WITH DOT {"CapitalDifferentialD", 0x02145}, // DOUBLE-STRUCK ITALIC CAPITAL D -// "caps", 0x02229;0x0FE00}, // INTERSECTION with serifs + {"caps", 0x02229, 0x0FE00}, // INTERSECTION with serifs {"caret", 0x02041}, // CARET INSERTION POINT {"caron", 0x002C7}, // CARON {"Cayleys", 0x0212D}, // BLACK-LETTER CAPITAL C @@ -440,7 +398,7 @@ immutable NameId[] namesC = {"cupcup", 0x02A4A}, // UNION BESIDE AND JOINED WITH UNION {"cupdot", 0x0228D}, // MULTISET MULTIPLICATION {"cupor", 0x02A45}, // UNION WITH LOGICAL OR -// "cups", 0x0222A;0x0FE00}, // UNION with serifs + {"cups", 0x0222A, 0x0FE00}, // UNION with serifs {"curarr", 0x021B7}, // CLOCKWISE TOP SEMICIRCLE ARROW {"curarrm", 0x0293C}, // TOP ARC CLOCKWISE ARROW WITH MINUS {"curlyeqprec", 0x022DE}, // EQUAL TO OR PRECEDES @@ -694,7 +652,7 @@ immutable NameId[] namesF = {"filig", 0x0FB01}, // LATIN SMALL LIGATURE FI {"FilledSmallSquare", 0x025FC}, // BLACK MEDIUM SQUARE {"FilledVerySmallSquare", 0x025AA}, // BLACK SMALL SQUARE -// "fjlig", 0x00066;0x0006A}, // fj ligature + {"fjlig", 0x00066, 0x0006A}, // fj ligature {"flat", 0x0266D}, // MUSIC FLAT SIGN {"fllig", 0x0FB02}, // LATIN SMALL LIGATURE FL {"fltns", 0x025B1}, // WHITE PARALLELOGRAM @@ -757,7 +715,7 @@ immutable NameId[] namesG = {"gesdot", 0x02A80}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE {"gesdoto", 0x02A82}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE {"gesdotol", 0x02A84}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT -// "gesl", 0x022DB;0x0FE00}, // GREATER-THAN slanted EQUAL TO OR LESS-THAN + {"gesl", 0x022DB, 0x0FE00}, // GREATER-THAN slanted EQUAL TO OR LESS-THAN {"gesles", 0x02A94}, // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL {"Gfr", 0x1D50A}, // MATHEMATICAL FRAKTUR CAPITAL G {"gfr", 0x1D524}, // MATHEMATICAL FRAKTUR SMALL G @@ -810,8 +768,8 @@ immutable NameId[] namesG = {"gtreqqless", 0x02A8C}, // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN {"gtrless", 0x02277}, // GREATER-THAN OR LESS-THAN {"gtrsim", 0x02273}, // GREATER-THAN OR EQUIVALENT TO -// "gvertneqq", 0x02269;0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke -// "gvnE", 0x02269;0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke + {"gvertneqq", 0x02269, 0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke + {"gvnE", 0x02269, 0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke ]; immutable NameId[] namesH = @@ -1020,7 +978,7 @@ immutable NameId[] namesL = {"latail", 0x02919}, // LEFTWARDS ARROW-TAIL {"lAtail", 0x0291B}, // LEFTWARDS DOUBLE ARROW-TAIL {"late", 0x02AAD}, // LARGER THAN OR EQUAL TO -// "lates", 0x02AAD;0x0FE00}, // LARGER THAN OR slanted EQUAL + {"lates", 0x02AAD, 0x0FE00}, // LARGER THAN OR slanted EQUAL {"lbarr", 0x0290C}, // LEFTWARDS DOUBLE DASH ARROW {"lBarr", 0x0290E}, // LEFTWARDS TRIPLE DASH ARROW {"lbbrk", 0x02772}, // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT @@ -1091,7 +1049,7 @@ immutable NameId[] namesL = {"lesdot", 0x02A7F}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE {"lesdoto", 0x02A81}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE {"lesdotor", 0x02A83}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT -// "lesg", 0x022DA;0x0FE00}, // LESS-THAN slanted EQUAL TO OR GREATER-THAN + {"lesg", 0x022DA, 0x0FE00}, // LESS-THAN slanted EQUAL TO OR GREATER-THAN {"lesges", 0x02A93}, // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL {"lessapprox", 0x02A85}, // LESS-THAN OR APPROXIMATE {"lessdot", 0x022D6}, // LESS-THAN WITH DOT @@ -1202,8 +1160,8 @@ immutable NameId[] namesL = {"ltrPar", 0x02996}, // DOUBLE RIGHT ARC LESS-THAN BRACKET {"lurdshar", 0x0294A}, // LEFT BARB UP RIGHT BARB DOWN HARPOON {"luruhar", 0x02966}, // LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP -// "lvertneqq", 0x02268;0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke -// "lvnE", 0x02268;0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke + {"lvertneqq", 0x02268, 0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke + {"lvnE", 0x02268, 0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke ]; immutable NameId[] namesM = @@ -1263,25 +1221,25 @@ immutable NameId[] namesN = {"nabla", 0x02207}, // NABLA {"Nacute", 0x00143}, // LATIN CAPITAL LETTER N WITH ACUTE {"nacute", 0x00144}, // LATIN SMALL LETTER N WITH ACUTE -// "nang", 0x02220;0x020D2}, // ANGLE with vertical line + {"nang", 0x02220, 0x020D2}, // ANGLE with vertical line {"nap", 0x02249}, // NOT ALMOST EQUAL TO -// "napE", 0x02A70;0x00338}, // APPROXIMATELY EQUAL OR EQUAL TO with slash -// "napid", 0x0224B;0x00338}, // TRIPLE TILDE with slash + {"napE", 0x02A70, 0x00338}, // APPROXIMATELY EQUAL OR EQUAL TO with slash + {"napid", 0x0224B, 0x00338}, // TRIPLE TILDE with slash {"napos", 0x00149}, // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE {"napprox", 0x02249}, // NOT ALMOST EQUAL TO {"natur", 0x0266E}, // MUSIC NATURAL SIGN {"natural", 0x0266E}, // MUSIC NATURAL SIGN {"naturals", 0x02115}, // DOUBLE-STRUCK CAPITAL N {"nbsp", 0x000A0}, // NO-BREAK SPACE -// "nbump", 0x0224E;0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash -// "nbumpe", 0x0224F;0x00338}, // DIFFERENCE BETWEEN with slash + {"nbump", 0x0224E, 0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash + {"nbumpe", 0x0224F, 0x00338}, // DIFFERENCE BETWEEN with slash {"ncap", 0x02A43}, // INTERSECTION WITH OVERBAR {"Ncaron", 0x00147}, // LATIN CAPITAL LETTER N WITH CARON {"ncaron", 0x00148}, // LATIN SMALL LETTER N WITH CARON {"Ncedil", 0x00145}, // LATIN CAPITAL LETTER N WITH CEDILLA {"ncedil", 0x00146}, // LATIN SMALL LETTER N WITH CEDILLA {"ncong", 0x02247}, // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO -// "ncongdot", 0x02A6D;0x00338}, // CONGRUENT WITH DOT ABOVE with slash + {"ncongdot", 0x02A6D, 0x00338}, // CONGRUENT WITH DOT ABOVE with slash {"ncup", 0x02A42}, // UNION WITH OVERBAR {"Ncy", 0x0041D}, // CYRILLIC CAPITAL LETTER EN {"ncy", 0x0043D}, // CYRILLIC SMALL LETTER EN @@ -1291,14 +1249,14 @@ immutable NameId[] namesN = {"nearr", 0x02197}, // NORTH EAST ARROW {"neArr", 0x021D7}, // NORTH EAST DOUBLE ARROW {"nearrow", 0x02197}, // NORTH EAST ARROW -// "nedot", 0x02250;0x00338}, // APPROACHES THE LIMIT with slash + {"nedot", 0x02250, 0x00338}, // APPROACHES THE LIMIT with slash {"NegativeMediumSpace", 0x0200B}, // ZERO WIDTH SPACE {"NegativeThickSpace", 0x0200B}, // ZERO WIDTH SPACE {"NegativeThinSpace", 0x0200B}, // ZERO WIDTH SPACE {"NegativeVeryThinSpace", 0x0200B}, // ZERO WIDTH SPACE {"nequiv", 0x02262}, // NOT IDENTICAL TO {"nesear", 0x02928}, // NORTH EAST ARROW AND SOUTH EAST ARROW -// "nesim", 0x02242;0x00338}, // MINUS TILDE with slash + {"nesim", 0x02242, 0x00338}, // MINUS TILDE with slash {"NestedGreaterGreater", 0x0226B}, // MUCH GREATER-THAN {"NestedLessLess", 0x0226A}, // MUCH LESS-THAN {"NewLine", 0x0000A}, // LINE FEED (LF) @@ -1306,20 +1264,20 @@ immutable NameId[] namesN = {"nexists", 0x02204}, // THERE DOES NOT EXIST {"Nfr", 0x1D511}, // MATHEMATICAL FRAKTUR CAPITAL N {"nfr", 0x1D52B}, // MATHEMATICAL FRAKTUR SMALL N -// "ngE", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash + {"ngE", 0x02267, 0x00338}, // GREATER-THAN OVER EQUAL TO with slash {"nge", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO {"ngeq", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO -// "ngeqq", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash -// "ngeqslant", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash -// "nges", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash -// "nGg", 0x022D9;0x00338}, // VERY MUCH GREATER-THAN with slash + {"ngeqq", 0x02267, 0x00338}, // GREATER-THAN OVER EQUAL TO with slash + {"ngeqslant", 0x02A7E, 0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash + {"nges", 0x02A7E, 0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash + {"nGg", 0x022D9, 0x00338}, // VERY MUCH GREATER-THAN with slash {"Ngr", 0x0039D}, // GREEK CAPITAL LETTER NU {"ngr", 0x003BD}, // GREEK SMALL LETTER NU {"ngsim", 0x02275}, // NEITHER GREATER-THAN NOR EQUIVALENT TO -// "nGt", 0x0226B;0x020D2}, // MUCH GREATER THAN with vertical line + {"nGt", 0x0226B, 0x020D2}, // MUCH GREATER THAN with vertical line {"ngt", 0x0226F}, // NOT GREATER-THAN {"ngtr", 0x0226F}, // NOT GREATER-THAN -// "nGtv", 0x0226B;0x00338}, // MUCH GREATER THAN with slash + {"nGtv", 0x0226B, 0x00338}, // MUCH GREATER THAN with slash {"nharr", 0x021AE}, // LEFT RIGHT ARROW WITH STROKE {"nhArr", 0x021CE}, // LEFT RIGHT DOUBLE ARROW WITH STROKE {"nhpar", 0x02AF2}, // PARALLEL WITH HORIZONTAL STROKE @@ -1332,24 +1290,24 @@ immutable NameId[] namesN = {"nlarr", 0x0219A}, // LEFTWARDS ARROW WITH STROKE {"nlArr", 0x021CD}, // LEFTWARDS DOUBLE ARROW WITH STROKE {"nldr", 0x02025}, // TWO DOT LEADER -// "nlE", 0x02266;0x00338}, // LESS-THAN OVER EQUAL TO with slash + {"nlE", 0x02266, 0x00338}, // LESS-THAN OVER EQUAL TO with slash {"nle", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO {"nleftarrow", 0x0219A}, // LEFTWARDS ARROW WITH STROKE {"nLeftarrow", 0x021CD}, // LEFTWARDS DOUBLE ARROW WITH STROKE {"nleftrightarrow", 0x021AE}, // LEFT RIGHT ARROW WITH STROKE {"nLeftrightarrow", 0x021CE}, // LEFT RIGHT DOUBLE ARROW WITH STROKE {"nleq", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO -// "nleqq", 0x02266;0x00338}, // LESS-THAN OVER EQUAL TO with slash -// "nleqslant", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash -// "nles", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash + {"nleqq", 0x02266, 0x00338}, // LESS-THAN OVER EQUAL TO with slash + {"nleqslant", 0x02A7D, 0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash + {"nles", 0x02A7D, 0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash {"nless", 0x0226E}, // NOT LESS-THAN -// "nLl", 0x022D8;0x00338}, // VERY MUCH LESS-THAN with slash + {"nLl", 0x022D8, 0x00338}, // VERY MUCH LESS-THAN with slash {"nlsim", 0x02274}, // NEITHER LESS-THAN NOR EQUIVALENT TO -// "nLt", 0x0226A;0x020D2}, // MUCH LESS THAN with vertical line + {"nLt", 0x0226A, 0x020D2}, // MUCH LESS THAN with vertical line {"nlt", 0x0226E}, // NOT LESS-THAN {"nltri", 0x022EA}, // NOT NORMAL SUBGROUP OF {"nltrie", 0x022EC}, // NOT NORMAL SUBGROUP OF OR EQUAL TO -// "nLtv", 0x0226A;0x00338}, // MUCH LESS THAN with slash + {"nLtv", 0x0226A, 0x00338}, // MUCH LESS THAN with slash {"nmid", 0x02224}, // DOES NOT DIVIDE {"NoBreak", 0x02060}, // WORD JOINER {"NonBreakingSpace", 0x000A0}, // NO-BREAK SPACE @@ -1362,56 +1320,56 @@ immutable NameId[] namesN = {"NotDoubleVerticalBar", 0x02226}, // NOT PARALLEL TO {"NotElement", 0x02209}, // NOT AN ELEMENT OF {"NotEqual", 0x02260}, // NOT EQUAL TO -// "NotEqualTilde", 0x02242;0x00338}, // MINUS TILDE with slash + {"NotEqualTilde", 0x02242, 0x00338}, // MINUS TILDE with slash {"NotExists", 0x02204}, // THERE DOES NOT EXIST {"NotGreater", 0x0226F}, // NOT GREATER-THAN {"NotGreaterEqual", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO -// "NotGreaterFullEqual", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash -// "NotGreaterGreater", 0x0226B;0x00338}, // MUCH GREATER THAN with slash + {"NotGreaterFullEqual", 0x02267, 0x00338}, // GREATER-THAN OVER EQUAL TO with slash + {"NotGreaterGreater", 0x0226B, 0x00338}, // MUCH GREATER THAN with slash {"NotGreaterLess", 0x02279}, // NEITHER GREATER-THAN NOR LESS-THAN -// "NotGreaterSlantEqual", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash + {"NotGreaterSlantEqual", 0x02A7E, 0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash {"NotGreaterTilde", 0x02275}, // NEITHER GREATER-THAN NOR EQUIVALENT TO -// "NotHumpDownHump", 0x0224E;0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash -// "NotHumpEqual", 0x0224F;0x00338}, // DIFFERENCE BETWEEN with slash + {"NotHumpDownHump", 0x0224E, 0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash + {"NotHumpEqual", 0x0224F, 0x00338}, // DIFFERENCE BETWEEN with slash {"notin", 0x02209}, // NOT AN ELEMENT OF -// "notindot", 0x022F5;0x00338}, // ELEMENT OF WITH DOT ABOVE with slash -// "notinE", 0x022F9;0x00338}, // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash + {"notindot", 0x022F5, 0x00338}, // ELEMENT OF WITH DOT ABOVE with slash + {"notinE", 0x022F9, 0x00338}, // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash {"notinva", 0x02209}, // NOT AN ELEMENT OF {"notinvb", 0x022F7}, // SMALL ELEMENT OF WITH OVERBAR {"notinvc", 0x022F6}, // ELEMENT OF WITH OVERBAR {"NotLeftTriangle", 0x022EA}, // NOT NORMAL SUBGROUP OF -// "NotLeftTriangleBar", 0x029CF;0x00338}, // LEFT TRIANGLE BESIDE VERTICAL BAR with slash + {"NotLeftTriangleBar", 0x029CF, 0x00338}, // LEFT TRIANGLE BESIDE VERTICAL BAR with slash {"NotLeftTriangleEqual", 0x022EC}, // NOT NORMAL SUBGROUP OF OR EQUAL TO {"NotLess", 0x0226E}, // NOT LESS-THAN {"NotLessEqual", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO {"NotLessGreater", 0x02278}, // NEITHER LESS-THAN NOR GREATER-THAN -// "NotLessLess", 0x0226A;0x00338}, // MUCH LESS THAN with slash -// "NotLessSlantEqual", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash + {"NotLessLess", 0x0226A, 0x00338}, // MUCH LESS THAN with slash + {"NotLessSlantEqual", 0x02A7D, 0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash {"NotLessTilde", 0x02274}, // NEITHER LESS-THAN NOR EQUIVALENT TO -// "NotNestedGreaterGreater", 0x02AA2;0x00338}, // DOUBLE NESTED GREATER-THAN with slash -// "NotNestedLessLess", 0x02AA1;0x00338}, // DOUBLE NESTED LESS-THAN with slash + {"NotNestedGreaterGreater", 0x02AA2, 0x00338}, // DOUBLE NESTED GREATER-THAN with slash + {"NotNestedLessLess", 0x02AA1, 0x00338}, // DOUBLE NESTED LESS-THAN with slash {"notni", 0x0220C}, // DOES NOT CONTAIN AS MEMBER {"notniva", 0x0220C}, // DOES NOT CONTAIN AS MEMBER {"notnivb", 0x022FE}, // SMALL CONTAINS WITH OVERBAR {"notnivc", 0x022FD}, // CONTAINS WITH OVERBAR {"NotPrecedes", 0x02280}, // DOES NOT PRECEDE -// "NotPrecedesEqual", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + {"NotPrecedesEqual", 0x02AAF, 0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash {"NotPrecedesSlantEqual", 0x022E0}, // DOES NOT PRECEDE OR EQUAL {"NotReverseElement", 0x0220C}, // DOES NOT CONTAIN AS MEMBER {"NotRightTriangle", 0x022EB}, // DOES NOT CONTAIN AS NORMAL SUBGROUP -// "NotRightTriangleBar", 0x029D0;0x00338}, // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash + {"NotRightTriangleBar", 0x029D0, 0x00338}, // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash {"NotRightTriangleEqual", 0x022ED}, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL -// "NotSquareSubset", 0x0228F;0x00338}, // SQUARE IMAGE OF with slash + {"NotSquareSubset", 0x0228F, 0x00338}, // SQUARE IMAGE OF with slash {"NotSquareSubsetEqual", 0x022E2}, // NOT SQUARE IMAGE OF OR EQUAL TO -// "NotSquareSuperset", 0x02290;0x00338}, // SQUARE ORIGINAL OF with slash + {"NotSquareSuperset", 0x02290, 0x00338}, // SQUARE ORIGINAL OF with slash {"NotSquareSupersetEqual", 0x022E3}, // NOT SQUARE ORIGINAL OF OR EQUAL TO -// "NotSubset", 0x02282;0x020D2}, // SUBSET OF with vertical line + {"NotSubset", 0x02282, 0x020D2}, // SUBSET OF with vertical line {"NotSubsetEqual", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO {"NotSucceeds", 0x02281}, // DOES NOT SUCCEED -// "NotSucceedsEqual", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + {"NotSucceedsEqual", 0x02AB0, 0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash {"NotSucceedsSlantEqual", 0x022E1}, // DOES NOT SUCCEED OR EQUAL -// "NotSucceedsTilde", 0x0227F;0x00338}, // SUCCEEDS OR EQUIVALENT TO with slash -// "NotSuperset", 0x02283;0x020D2}, // SUPERSET OF with vertical line + {"NotSucceedsTilde", 0x0227F, 0x00338}, // SUCCEEDS OR EQUIVALENT TO with slash + {"NotSuperset", 0x02283, 0x020D2}, // SUPERSET OF with vertical line {"NotSupersetEqual", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO {"NotTilde", 0x02241}, // NOT TILDE {"NotTildeEqual", 0x02244}, // NOT ASYMPTOTICALLY EQUAL TO @@ -1420,25 +1378,25 @@ immutable NameId[] namesN = {"NotVerticalBar", 0x02224}, // DOES NOT DIVIDE {"npar", 0x02226}, // NOT PARALLEL TO {"nparallel", 0x02226}, // NOT PARALLEL TO -// "nparsl", 0x02AFD;0x020E5}, // DOUBLE SOLIDUS OPERATOR with reverse slash -// "npart", 0x02202;0x00338}, // PARTIAL DIFFERENTIAL with slash + {"nparsl", 0x02AFD, 0x020E5}, // DOUBLE SOLIDUS OPERATOR with reverse slash + {"npart", 0x02202, 0x00338}, // PARTIAL DIFFERENTIAL with slash {"npolint", 0x02A14}, // LINE INTEGRATION NOT INCLUDING THE POLE {"npr", 0x02280}, // DOES NOT PRECEDE {"nprcue", 0x022E0}, // DOES NOT PRECEDE OR EQUAL -// "npre", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + {"npre", 0x02AAF, 0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash {"nprec", 0x02280}, // DOES NOT PRECEDE -// "npreceq", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + {"npreceq", 0x02AAF, 0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash {"nrarr", 0x0219B}, // RIGHTWARDS ARROW WITH STROKE {"nrArr", 0x021CF}, // RIGHTWARDS DOUBLE ARROW WITH STROKE -// "nrarrc", 0x02933;0x00338}, // WAVE ARROW POINTING DIRECTLY RIGHT with slash -// "nrarrw", 0x0219D;0x00338}, // RIGHTWARDS WAVE ARROW with slash + {"nrarrc", 0x02933, 0x00338}, // WAVE ARROW POINTING DIRECTLY RIGHT with slash + {"nrarrw", 0x0219D, 0x00338}, // RIGHTWARDS WAVE ARROW with slash {"nrightarrow", 0x0219B}, // RIGHTWARDS ARROW WITH STROKE {"nRightarrow", 0x021CF}, // RIGHTWARDS DOUBLE ARROW WITH STROKE {"nrtri", 0x022EB}, // DOES NOT CONTAIN AS NORMAL SUBGROUP {"nrtrie", 0x022ED}, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL {"nsc", 0x02281}, // DOES NOT SUCCEED {"nsccue", 0x022E1}, // DOES NOT SUCCEED OR EQUAL -// "nsce", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + {"nsce", 0x02AB0, 0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash {"Nscr", 0x1D4A9}, // MATHEMATICAL SCRIPT CAPITAL N {"nscr", 0x1D4C3}, // MATHEMATICAL SCRIPT SMALL N {"nshortmid", 0x02224}, // DOES NOT DIVIDE @@ -1452,18 +1410,18 @@ immutable NameId[] namesN = {"nsqsupe", 0x022E3}, // NOT SQUARE ORIGINAL OF OR EQUAL TO {"nsub", 0x02284}, // NOT A SUBSET OF {"nsube", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO -// "nsubE", 0x02AC5;0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash -// "nsubset", 0x02282;0x020D2}, // SUBSET OF with vertical line + {"nsubE", 0x02AC5, 0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash + {"nsubset", 0x02282, 0x020D2}, // SUBSET OF with vertical line {"nsubseteq", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO -// "nsubseteqq", 0x02AC5;0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash + {"nsubseteqq", 0x02AC5, 0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash {"nsucc", 0x02281}, // DOES NOT SUCCEED -// "nsucceq", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + {"nsucceq", 0x02AB0, 0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash {"nsup", 0x02285}, // NOT A SUPERSET OF {"nsupe", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO -// "nsupE", 0x02AC6;0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash -// "nsupset", 0x02283;0x020D2}, // SUPERSET OF with vertical line + {"nsupE", 0x02AC6, 0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash + {"nsupset", 0x02283, 0x020D2}, // SUPERSET OF with vertical line {"nsupseteq", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO -// "nsupseteqq", 0x02AC6;0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash + {"nsupseteqq", 0x02AC6, 0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash {"ntgl", 0x02279}, // NEITHER GREATER-THAN NOR LESS-THAN {"Ntilde", 0x000D1}, // LATIN CAPITAL LETTER N WITH TILDE {"ntilde", 0x000F1}, // LATIN SMALL LETTER N WITH TILDE @@ -1477,22 +1435,22 @@ immutable NameId[] namesN = {"num", 0x00023}, // NUMBER SIGN {"numero", 0x02116}, // NUMERO SIGN {"numsp", 0x02007}, // FIGURE SPACE -// "nvap", 0x0224D;0x020D2}, // EQUIVALENT TO with vertical line + {"nvap", 0x0224D, 0x020D2}, // EQUIVALENT TO with vertical line {"nvdash", 0x022AC}, // DOES NOT PROVE {"nvDash", 0x022AD}, // NOT TRUE {"nVdash", 0x022AE}, // DOES NOT FORCE {"nVDash", 0x022AF}, // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE -// "nvge", 0x02265;0x020D2}, // GREATER-THAN OR EQUAL TO with vertical line -// "nvgt", 0x0003E;0x020D2}, // GREATER-THAN SIGN with vertical line + {"nvge", 0x02265, 0x020D2}, // GREATER-THAN OR EQUAL TO with vertical line + {"nvgt", 0x0003E, 0x020D2}, // GREATER-THAN SIGN with vertical line {"nvHarr", 0x02904}, // LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE {"nvinfin", 0x029DE}, // INFINITY NEGATED WITH VERTICAL BAR {"nvlArr", 0x02902}, // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE -// "nvle", 0x02264;0x020D2}, // LESS-THAN OR EQUAL TO with vertical line -// "nvlt", 0x0003C;0x020D2}, // LESS-THAN SIGN with vertical line -// "nvltrie", 0x022B4;0x020D2}, // NORMAL SUBGROUP OF OR EQUAL TO with vertical line + {"nvle", 0x02264, 0x020D2}, // LESS-THAN OR EQUAL TO with vertical line + {"nvlt", 0x0003C, 0x020D2}, // LESS-THAN SIGN with vertical line + {"nvltrie", 0x022B4, 0x020D2}, // NORMAL SUBGROUP OF OR EQUAL TO with vertical line {"nvrArr", 0x02903}, // RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE -// "nvrtrie", 0x022B5;0x020D2}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line -// "nvsim", 0x0223C;0x020D2}, // TILDE OPERATOR with vertical line + {"nvrtrie", 0x022B5, 0x020D2}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line + {"nvsim", 0x0223C, 0x020D2}, // TILDE OPERATOR with vertical line {"nwarhk", 0x02923}, // NORTH WEST ARROW WITH HOOK {"nwarr", 0x02196}, // NORTH WEST ARROW {"nwArr", 0x021D6}, // NORTH WEST DOUBLE ARROW @@ -1704,7 +1662,7 @@ immutable NameId[] namesQ = immutable NameId[] namesR = [ {"rAarr", 0x021DB}, // RIGHTWARDS TRIPLE ARROW -// "race", 0x0223D;0x00331}, // REVERSED TILDE with underline + {"race", 0x0223D, 0x00331}, // REVERSED TILDE with underline {"Racute", 0x00154}, // LATIN CAPITAL LETTER R WITH ACUTE {"racute", 0x00155}, // LATIN SMALL LETTER R WITH ACUTE {"radic", 0x0221A}, // SQUARE ROOT @@ -1932,7 +1890,7 @@ immutable NameId[] namesS = {"smile", 0x02323}, // SMILE {"smt", 0x02AAA}, // SMALLER THAN {"smte", 0x02AAC}, // SMALLER THAN OR EQUAL TO -// "smtes", 0x02AAC;0x0FE00}, // SMALLER THAN OR slanted EQUAL + {"smtes", 0x02AAC, 0x0FE00}, // SMALLER THAN OR slanted EQUAL {"SOFTcy", 0x0042C}, // CYRILLIC CAPITAL LETTER SOFT SIGN {"softcy", 0x0044C}, // CYRILLIC SMALL LETTER SOFT SIGN {"sol", 0x0002F}, // SOLIDUS @@ -1944,9 +1902,9 @@ immutable NameId[] namesS = {"spadesuit", 0x02660}, // BLACK SPADE SUIT {"spar", 0x02225}, // PARALLEL TO {"sqcap", 0x02293}, // SQUARE CAP -// "sqcaps", 0x02293;0x0FE00}, // SQUARE CAP with serifs + {"sqcaps", 0x02293, 0x0FE00}, // SQUARE CAP with serifs {"sqcup", 0x02294}, // SQUARE CUP -// "sqcups", 0x02294;0x0FE00}, // SQUARE CUP with serifs + {"sqcups", 0x02294, 0x0FE00}, // SQUARE CUP with serifs {"Sqrt", 0x0221A}, // SQUARE ROOT {"sqsub", 0x0228F}, // SQUARE IMAGE OF {"sqsube", 0x02291}, // SQUARE IMAGE OF OR EQUAL TO @@ -2082,7 +2040,7 @@ immutable NameId[] namesT = {"thgr", 0x003B8}, // GREEK SMALL LETTER THETA {"thickapprox", 0x02248}, // ALMOST EQUAL TO {"thicksim", 0x0223C}, // TILDE OPERATOR -// "ThickSpace", 0x0205F;0x0200A}, // space of width 5/18 em + {"ThickSpace", 0x0205F, 0x0200A}, // space of width 5/18 em {"thinsp", 0x02009}, // THIN SPACE {"ThinSpace", 0x02009}, // THIN SPACE {"thkap", 0x02248}, // ALMOST EQUAL TO @@ -2245,10 +2203,10 @@ immutable NameId[] namesV = {"vArr", 0x021D5}, // UP DOWN DOUBLE ARROW {"varrho", 0x003F1}, // GREEK RHO SYMBOL {"varsigma", 0x003C2}, // GREEK SMALL LETTER FINAL SIGMA -// "varsubsetneq", 0x0228A;0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -// "varsubsetneqq", 0x02ACB;0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members -// "varsupsetneq", 0x0228B;0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -// "varsupsetneqq", 0x02ACC;0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + {"varsubsetneq", 0x0228A, 0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members + {"varsubsetneqq", 0x02ACB, 0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + {"varsupsetneq", 0x0228B, 0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members + {"varsupsetneqq", 0x02ACC, 0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members {"vartheta", 0x003D1}, // GREEK THETA SYMBOL {"vartriangleleft", 0x022B2}, // NORMAL SUBGROUP OF {"vartriangleright", 0x022B3}, // CONTAINS AS NORMAL SUBGROUP @@ -2279,18 +2237,18 @@ immutable NameId[] namesV = {"Vfr", 0x1D519}, // MATHEMATICAL FRAKTUR CAPITAL V {"vfr", 0x1D533}, // MATHEMATICAL FRAKTUR SMALL V {"vltri", 0x022B2}, // NORMAL SUBGROUP OF -// "vnsub", 0x02282;0x020D2}, // SUBSET OF with vertical line -// "vnsup", 0x02283;0x020D2}, // SUPERSET OF with vertical line + {"vnsub", 0x02282, 0x020D2}, // SUBSET OF with vertical line + {"vnsup", 0x02283, 0x020D2}, // SUPERSET OF with vertical line {"Vopf", 0x1D54D}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL V {"vopf", 0x1D567}, // MATHEMATICAL DOUBLE-STRUCK SMALL V {"vprop", 0x0221D}, // PROPORTIONAL TO {"vrtri", 0x022B3}, // CONTAINS AS NORMAL SUBGROUP {"Vscr", 0x1D4B1}, // MATHEMATICAL SCRIPT CAPITAL V {"vscr", 0x1D4CB}, // MATHEMATICAL SCRIPT SMALL V -// "vsubne", 0x0228A;0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -// "vsubnE", 0x02ACB;0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members -// "vsupne", 0x0228B;0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -// "vsupnE", 0x02ACC;0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + {"vsubne", 0x0228A, 0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members + {"vsubnE", 0x02ACB, 0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + {"vsupne", 0x0228B, 0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members + {"vsupnE", 0x02ACC, 0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members {"Vvdash", 0x022AA}, // TRIPLE VERTICAL BAR RIGHT TURNSTILE {"vzigzag", 0x0299A}, // VERTICAL ZIGZAG LINE ]; diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index 7ba0a96..e7626b0 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -409,23 +409,9 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Var { unsafeAssign!"scope variable"(v); } - else if (v.isTypesafeVariadicParameter && p == sc.func) + else if (v.isTypesafeVariadicArray && p == sc.func) { - Type tb = v.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - unsafeAssign!"variadic variable"(v); - } - } - else - { - /* v is not 'scope', and is assigned to a parameter that may escape. - * Therefore, v can never be 'scope'. - */ - if (log) printf("no infer for %s in %s loc %s, fdc %s, %d\n", - v.toChars(), sc.func.ident.toChars(), sc.func.loc.toChars(), fdc.ident.toChars(), __LINE__); - - doNotInferScope(v, vPar); + unsafeAssign!"variadic variable"(v); } } @@ -673,9 +659,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) FuncDeclaration fd = sc.func; - // Determine if va is a parameter that is an indirect reference - const bool vaIsRef = va && va.storage_class & STC.parameter && - (va.isReference() || va.type.toBasetype().isTypeClass()); // ref, out, or class + // Determine if va is a `ref` parameter, so it has a lifetime exceding the function scope + const bool vaIsRef = va && va.isParameter() && va.isReference(); if (log && vaIsRef) printf("va is ref `%s`\n", va.toChars()); /* Determine if va is the first parameter, through which other 'return' parameters @@ -717,7 +702,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) Dsymbol p = v.toParent2(); if (va && !vaIsRef && !va.isScope() && !v.isScope() && - !v.isTypesafeVariadicParameter && !va.isTypesafeVariadicParameter && + !v.isTypesafeVariadicArray && !va.isTypesafeVariadicArray && (va.isParameter() && va.maybeScope && v.isParameter() && v.maybeScope) && p == fd) { @@ -727,16 +712,9 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) continue; } - if (vaIsFirstRef && - (v.isScope() || v.maybeScope) && - !(v.storage_class & STC.return_) && - v.isParameter() && - fd.flags & FUNCFLAG.returnInprocess && - p == fd && - !v.isTypesafeVariadicParameter) + if (vaIsFirstRef && p == fd) { - if (log) printf("inferring 'return' for parameter %s in function %s\n", v.toChars(), fd.toChars()); - inferReturn(fd, v, /*returnScope:*/ true); // infer addition of 'return' to make `return scope` + inferReturn(fd, v, /*returnScope:*/ true); } if (!(va && va.isScope()) || vaIsRef) @@ -744,82 +722,66 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) if (v.isScope()) { - if (vaIsFirstRef && v.isParameter() && v.storage_class & STC.return_) + if (vaIsFirstRef && v.isParameter() && v.isReturn()) { // va=v, where v is `return scope` - if (va.isScope()) + if (inferScope(va)) continue; - - if (va.maybeScope) - { - if (log) printf("inferring scope for lvalue %s\n", va.toChars()); - va.storage_class |= STC.scope_ | STC.scopeinferred; - continue; - } } - if (va && va.isScope() && va.storage_class & STC.return_ && !(v.storage_class & STC.return_)) + // If va's lifetime encloses v's, then error + if (EnclosedBy eb = va.enclosesLifetimeOf(v)) { - // va may return its value, but v does not allow that, so this is an error - if (sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to return scope `%s`", v, va)) + const(char)* msg; + final switch (eb) { - result = true; - continue; + case EnclosedBy.none: assert(0); + case EnclosedBy.returnScope: + msg = "scope variable `%s` assigned to return scope `%s`"; + break; + case EnclosedBy.longerScope: + if (v.storage_class & STC.temp) + continue; + msg = "scope variable `%s` assigned to `%s` with longer lifetime"; + break; + case EnclosedBy.refVar: + msg = "scope variable `%s` assigned to `ref` variable `%s` with longer lifetime"; + break; + case EnclosedBy.global: + msg = "scope variable `%s` assigned to global variable `%s`"; + break; } - } - // If va's lifetime encloses v's, then error - if (va && !va.isDataseg() && - ((va.enclosesLifetimeOf(v) && !(v.storage_class & STC.temp)) || vaIsRef)) - { - if (sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to `%s` with longer lifetime", v, va)) + if (sc.setUnsafeDIP1000(gag, ae.loc, msg, v, va)) { result = true; continue; } } - if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) + // v = scope, va should be scope as well + const vaWasScope = va && va.isScope(); + if (inferScope(va)) { - if (!va.isScope()) - { /* v is scope, and va is not scope, so va needs to - * infer scope - */ - if (log) printf("inferring scope for %s\n", va.toChars()); - va.storage_class |= STC.scope_ | STC.scopeinferred; - /* v returns, and va does not return, so va needs - * to infer return - */ - if (v.storage_class & STC.return_ && - !(va.storage_class & STC.return_)) - { - if (log) printf("infer return for %s\n", va.toChars()); - va.storage_class |= STC.return_ | STC.returninferred; + // In case of `scope local = returnScopeParam`, do not infer return scope for `x` + if (!vaWasScope && v.isReturn() && !va.isReturn()) + { + if (log) printf("infer return for %s\n", va.toChars()); + va.storage_class |= STC.return_ | STC.returninferred; - // Added "return scope" so don't confuse it with "return ref" - if (isRefReturnScope(va.storage_class)) - va.storage_class |= STC.returnScope; - } + // Added "return scope" so don't confuse it with "return ref" + if (isRefReturnScope(va.storage_class)) + va.storage_class |= STC.returnScope; } continue; } result |= sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to non-scope `%s`", v, e1); } - else if (v.isTypesafeVariadicParameter && p == fd) + else if (v.isTypesafeVariadicArray && p == fd) { - Type tb = v.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) - { - if (!va.isScope()) - { //printf("inferring scope for %s\n", va.toChars()); - va.storage_class |= STC.scope_ | STC.scopeinferred; - } - continue; - } - result |= sc.setUnsafeDIP1000(gag, ae.loc, "variadic variable `%s` assigned to non-scope `%s`", v, e1); - } + if (inferScope(va)) + continue; + result |= sc.setUnsafeDIP1000(gag, ae.loc, "variadic variable `%s` assigned to non-scope `%s`", v, e1); } else { @@ -845,7 +807,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) if (va && va.isScope() && !v.isReference()) { - if (!(va.storage_class & STC.return_)) + if (!va.isReturn()) { va.doNotInferReturn = true; } @@ -858,19 +820,14 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) Dsymbol p = v.toParent2(); - if (vaIsFirstRef && v.isParameter() && - !(v.storage_class & STC.return_) && - fd.flags & FUNCFLAG.returnInprocess && - p == fd) + if (vaIsFirstRef && p == fd) { //if (log) printf("inferring 'return' for parameter %s in function %s\n", v.toChars(), fd.toChars()); inferReturn(fd, v, /*returnScope:*/ false); } // If va's lifetime encloses v's, then error - if (va && - !(vaIsFirstRef && (v.storage_class & STC.return_)) && - (va.enclosesLifetimeOf(v) || (va.isReference() && !(va.storage_class & STC.temp)) || va.isDataseg())) + if (va && !(vaIsFirstRef && v.isReturn()) && va.enclosesLifetimeOf(v)) { if (sc.setUnsafeDIP1000(gag, ae.loc, "address of variable `%s` assigned to `%s` with longer lifetime", v, va)) { @@ -885,13 +842,9 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) if (p != sc.func) continue; - if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) + if (inferScope(va)) { - if (!va.isScope()) - { //printf("inferring scope for %s\n", va.toChars()); - va.storage_class |= STC.scope_ | STC.scopeinferred; - } - if (v.storage_class & STC.return_ && !(va.storage_class & STC.return_)) + if (v.isReturn() && !va.isReturn()) va.storage_class |= STC.return_ | STC.returninferred; continue; } @@ -912,7 +865,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) * then uncount that address of. This is so it won't cause a * closure to be allocated. */ - if (va && va.isScope() && !(va.storage_class & STC.return_) && func.tookAddressOf) + if (va && va.isScope() && !va.isReturn() && func.tookAddressOf) --func.tookAddressOf; foreach (v; vars) @@ -978,14 +931,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) } } - if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) - { - if (!va.isScope()) - { //printf("inferring scope for %s\n", va.toChars()); - va.storage_class |= STC.scope_ | STC.scopeinferred; - } + if (inferScope(va)) continue; - } result |= sc.setUnsafeDIP1000(gag, ee.loc, "reference to stack allocated value returned by `%s` assigned to non-scope `%s`", ee, e1); @@ -1091,14 +1038,10 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) continue; } } - else if (v.isTypesafeVariadicParameter && p == sc.func) + else if (v.isTypesafeVariadicArray && p == sc.func) { - Type tb = v.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - result |= sc.setUnsafeDIP1000(gag, e.loc, - "copying `%s` into allocated memory escapes a reference to variadic parameter `%s`", e, v); - } + result |= sc.setUnsafeDIP1000(gag, e.loc, + "copying `%s` into allocated memory escapes a reference to variadic parameter `%s`", e, v); } else { @@ -1258,15 +1201,8 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) Dsymbol p = v.toParent2(); - if ((v.isScope() || v.maybeScope) && - !(v.storage_class & STC.return_) && - v.isParameter() && - !v.doNotInferReturn && - sc.func.flags & FUNCFLAG.returnInprocess && - p == sc.func && - !v.isTypesafeVariadicParameter) + if (p == sc.func && inferReturn(sc.func, v, /*returnScope:*/ true)) { - inferReturn(sc.func, v, /*returnScope:*/ true); // infer addition of 'return' continue; } @@ -1300,7 +1236,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) !(!refs && sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0) ) { - if (v.isParameter() && !(v.storage_class & STC.return_)) + if (v.isParameter() && !v.isReturn()) { // https://issues.dlang.org/show_bug.cgi?id=23191 if (!gag) @@ -1320,15 +1256,11 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) } } } - else if (v.isTypesafeVariadicParameter && p == sc.func) + else if (v.isTypesafeVariadicArray && p == sc.func) { - Type tb = v.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - if (!gag) - error(e.loc, "returning `%s` escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars()); - result = false; - } + if (!gag) + error(e.loc, "returning `%s` escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars()); + result = false; } else { @@ -1414,7 +1346,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) continue; } FuncDeclaration fd = p.isFuncDeclaration(); - if (fd && sc.func.flags & FUNCFLAG.returnInprocess) + if (fd && sc.func.returnInprocess) { /* Code like: * int x; @@ -1435,10 +1367,10 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) vsr == ScopeRef.Ref_ReturnScope) && !(v.storage_class & STC.foreach_)) { - if (sc.func.flags & FUNCFLAG.returnInprocess && p == sc.func && - (vsr == ScopeRef.Ref || vsr == ScopeRef.RefScope)) + if (p == sc.func && (vsr == ScopeRef.Ref || vsr == ScopeRef.RefScope) && + inferReturn(sc.func, v, /*returnScope:*/ false)) { - inferReturn(sc.func, v, /*returnScope:*/ false); // infer addition of 'return' + continue; } else { @@ -1488,6 +1420,26 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) return result; } +/*********************************** + * Infer `scope` for a variable + * + * Params: + * va = variable to infer scope for + * Returns: `true` if succesful or already `scope` + */ +bool inferScope(VarDeclaration va) +{ + if (!va) + return false; + if (!va.isDataseg() && va.maybeScope && !va.isScope()) + { + //printf("inferring scope for %s\n", va.toChars()); + va.maybeScope = false; + va.storage_class |= STC.scope_ | STC.scopeinferred; + return true; + } + return va.isScope(); +} /************************************* * Variable v needs to have 'return' inferred for it. @@ -1495,10 +1447,22 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) * fd = function that v is a parameter to * v = parameter that needs to be STC.return_ * returnScope = infer `return scope` instead of `return ref` + * + * Returns: whether the inference on `v` was successful or `v` already was `return` */ -private void inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope) +private bool inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope) { - // v is a local in the current function + if (v.isReturn()) + return !!(v.storage_class & STC.returnScope) == returnScope; + + if (!v.isParameter() || v.isTypesafeVariadicArray || (returnScope && v.doNotInferReturn)) + return false; + + if (!fd.returnInprocess) + return false; + + if (returnScope && !(v.isScope() || v.maybeScope)) + return false; //printf("for function '%s' inferring 'return' for variable '%s', returnScope: %d\n", fd.toChars(), v.toChars(), returnScope); auto newStcs = STC.return_ | STC.returninferred | (returnScope ? STC.returnScope : 0); @@ -1532,6 +1496,7 @@ private void inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope) } } } + return true; } @@ -1694,7 +1659,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re { if (tb.ty == Tsarray) return; - if (v.isTypesafeVariadicParameter) + if (v.isTypesafeVariadicArray) { er.byvalue.push(v); return; @@ -2008,13 +1973,10 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR if (auto ve = e.e1.isVarExp()) { VarDeclaration v = ve.var.isVarDeclaration(); - if (tb.ty == Tarray || tb.ty == Tsarray) + if (v && v.isTypesafeVariadicArray) { - if (v && v.isTypesafeVariadicParameter) - { - er.pushRef(v, retRefTransition); - return; - } + er.pushRef(v, retRefTransition); + return; } } if (tb.ty == Tsarray) @@ -2339,9 +2301,9 @@ private void doNotInferScope(VarDeclaration v, RootObject o) void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) { - if (funcdecl.flags & FUNCFLAG.returnInprocess) + if (funcdecl.returnInprocess) { - funcdecl.flags &= ~FUNCFLAG.returnInprocess; + funcdecl.returnInprocess = false; if (funcdecl.storage_class & STC.return_) { if (funcdecl.type == f) @@ -2353,9 +2315,9 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) } } - if (!(funcdecl.flags & FUNCFLAG.inferScope)) + if (!funcdecl.inferScope) return; - funcdecl.flags &= ~FUNCFLAG.inferScope; + funcdecl.inferScope = false; // Eliminate maybescope's { @@ -2387,22 +2349,19 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) foreach (u, p; f.parameterList) { auto v = (*funcdecl.parameters)[u]; - if (v.maybeScope) + if (!v.isScope() && inferScope(v)) { //printf("Inferring scope for %s\n", v.toChars()); - notMaybeScope(v, null); - v.storage_class |= STC.scope_ | STC.scopeinferred; p.storageClass |= STC.scope_ | STC.scopeinferred; } } } - if (funcdecl.vthis && funcdecl.vthis.maybeScope) + if (funcdecl.vthis) { - notMaybeScope(funcdecl.vthis, null); - funcdecl.vthis.storage_class |= STC.scope_ | STC.scopeinferred; - f.isScopeQual = true; - f.isscopeinferred = true; + inferScope(funcdecl.vthis); + f.isScopeQual = funcdecl.vthis.isScope(); + f.isscopeinferred = !!(funcdecl.vthis.storage_class & STC.scopeinferred); } } @@ -2542,20 +2501,45 @@ bool isReferenceToMutable(Parameter p, Type t) return isReferenceToMutable(p.type); } +/// When checking lifetime for assignment `va=v`, the way `va` encloses `v` +private enum EnclosedBy +{ + none = 0, + refVar, // `va` is a `ref` variable, which may link to a global variable + global, // `va` is a global variable + returnScope, // `va` is a scope variable that may be returned + longerScope, // `va` is another scope variable declared earlier than `v` +} + /********************************** -* Determine if `va` has a lifetime that lasts past -* the destruction of `v` -* Params: -* va = variable assigned to -* v = variable being assigned -* Returns: -* true if it does -*/ -private bool enclosesLifetimeOf(const VarDeclaration va, const VarDeclaration v) pure + * Determine if `va` has a lifetime that lasts past + * the destruction of `v` + * Params: + * va = variable assigned to + * v = variable being assigned + * Returns: + * The way `va` encloses `v` (if any) + */ +private EnclosedBy enclosesLifetimeOf(VarDeclaration va, VarDeclaration v) { + if (!va) + return EnclosedBy.none; + + if (va.isDataseg()) + return EnclosedBy.global; + + if (va.isScope() && va.isReturn() && !v.isReturn()) + return EnclosedBy.returnScope; + + if (va.isReference() && va.isParameter()) + return EnclosedBy.refVar; + assert(va.sequenceNumber != va.sequenceNumber.init); assert(v.sequenceNumber != v.sequenceNumber.init); - return va.sequenceNumber < v.sequenceNumber; + if (va.sequenceNumber < v.sequenceNumber) + return EnclosedBy.longerScope; + + return EnclosedBy.none; } /*************************************** @@ -2576,53 +2560,6 @@ private void addMaybe(VarDeclaration va, VarDeclaration v) va.maybes.push(v); } -/*************************************** - * Like `FuncDeclaration.setUnsafe`, but modified for dip25 / dip1000 by default transitions - * - * With `-preview=dip1000` it actually sets the function as unsafe / prints an error, while - * without it, it only prints a deprecation in a `@safe` function. - * With `-revert=preview=dip1000`, it doesn't do anything. - * - * Params: - * sc = used for checking whether we are in a deprecated scope - * fs = command line setting of dip1000 / dip25 - * gag = surpress error message - * loc = location of error - * fmt = printf-style format string - * arg0 = (optional) argument for first %s format specifier - * arg1 = (optional) argument for second %s format specifier - * arg2 = (optional) argument for third %s format specifier - * Returns: whether an actual safe error (not deprecation) occured - */ -private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, - RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) -{ - if (fs == FeatureState.disabled) - { - return false; - } - else if (fs == FeatureState.enabled) - { - return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2); - } - else - { - if (sc.func.isSafeBypassingInference()) - { - if (!gag) - previewErrorFunc(sc.isDeprecated(), fs)( - loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "" - ); - } - else if (!sc.func.safetyViolation) - { - import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2); - } - return false; - } -} - // `setUnsafePreview` partially evaluated for dip1000 private bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) @@ -2671,13 +2608,19 @@ private bool checkScopeVarAddr(VarDeclaration v, Expression e, Scope* sc, bool g } /**************************** - * Determine if `v` is a typesafe variadic parameter. + * Determine if `v` is a typesafe variadic array, which is implicitly `scope` * Params: * v = variable to check * Returns: * true if `v` is a variadic parameter */ -bool isTypesafeVariadicParameter(VarDeclaration v) +private bool isTypesafeVariadicArray(VarDeclaration v) { - return !!(v.storage_class & STC.variadic); + if (v.storage_class & STC.variadic) + { + Type tb = v.type.toBasetype(); + if (tb.ty == Tarray || tb.ty == Tsarray) + return true; + } + return false; } diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 42b4dd4..21f5cc7 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -2949,7 +2949,7 @@ extern (C++) final class ArrayLiteralExp : Expression Expressions* elements; OwnedBy ownedByCtfe = OwnedBy.code; - + bool onstack = false; extern (D) this(const ref Loc loc, Type type, Expressions* elements) { diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index c9e3978..79bc528 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -419,6 +419,7 @@ public: Expression *basis; Expressions *elements; OwnedBy ownedByCtfe; + bool onstack; static ArrayLiteralExp *create(const Loc &loc, Expressions *elements); static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements); diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 8a4a13c..f899bd7 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -353,6 +353,37 @@ extern(D) bool arrayExpressionSemantic( return err; } +/* +Checks if `exp` contains a direct access to a `noreturn` +variable. If that is the case, an `assert(0)` expression +is generated and returned. This function should be called +only after semantic analysis has been performed on `exp`. + +Params: + exp = expression that is checked + +Returns: + An `assert(0)` expression if `exp` contains a `noreturn` + variable access, `exp` otherwise. +*/ + +Expression checkNoreturnVarAccess(Expression exp) +{ + assert(exp.type); + + Expression result = exp; + if (exp.type.isTypeNoreturn() && !exp.isAssertExp() && + !exp.isThrowExp() && !exp.isCallExp()) + { + auto msg = new StringExp(exp.loc, "Accessed expression of type `noreturn`"); + msg.type = Type.tstring; + result = new AssertExp(exp.loc, IntegerExp.literal!0, msg); + result.type = exp.type; + } + + return result; +} + /****************************** * Check the tail CallExp is really property function call. * Bugs: @@ -848,6 +879,18 @@ Lagain: if (d) d.checkDisabled(loc, sc); } + + if (auto sd = s.isDeclaration()) + { + if (sd.isSystem()) + { + if (sc.setUnsafePreview(global.params.systemVariables, false, loc, + "cannot access `@system` variable `%s` in @safe code", sd)) + { + return ErrorExp.get(); + } + } + } } if (auto em = s.isEnumMember()) @@ -1714,7 +1757,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, if (sc._module) sc._module.hasAlwaysInlines = true; if (sc.func) - sc.func.flags |= FUNCFLAG.hasAlwaysInline; + sc.func.hasAlwaysInlines = true; } const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration(); @@ -2200,14 +2243,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc, /* If calling C scanf(), printf(), or any variants, check the format string against the arguments */ const isVa_list = tf.parameterList.varargs == VarArg.none; - if (fd && fd.flags & FUNCFLAG.printf) + if (fd && fd.printf) { if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp()) { checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list); } } - else if (fd && fd.flags & FUNCFLAG.scanf) + else if (fd && fd.scanf) { if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp()) { @@ -4628,8 +4671,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else if (exp.arguments.dim == 1) { e = (*exp.arguments)[0]; - e = e.implicitCastTo(sc, t1); - e = new CastExp(exp.loc, e, t1); + if (!e.type.isTypeNoreturn()) + e = e.implicitCastTo(sc, t1); } else { @@ -7474,6 +7517,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + if (exp.e1.type.isTypeNoreturn() && (!exp.to || !exp.to.isTypeNoreturn())) + { + result = exp.e1; + return; + } if (exp.to && !exp.to.isTypeSArray() && !exp.to.isTypeFunction()) exp.e1 = exp.e1.arrayFuncConv(sc); @@ -7889,7 +7937,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } } - else if (t1b.ty == Tvector) + else if (t1b.ty == Tvector && exp.e1.isLvalue()) { // Convert e1 to corresponding static array TypeVector tv1 = cast(TypeVector)t1b; @@ -8896,7 +8944,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.e1 = e1x; assert(exp.e1.type); } - Type t1 = exp.e1.type.toBasetype(); + Type t1 = exp.e1.type.isTypeEnum() ? exp.e1.type : exp.e1.type.toBasetype(); /* Run this.e2 semantic. * Different from other binary expressions, the analysis of e2 @@ -8918,14 +8966,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor e2x.checkSharedAccess(sc)) return setError(); - if (e2x.type.isTypeNoreturn() && !e2x.isAssertExp() && !e2x.isThrowExp() && !e2x.isCallExp()) - { - auto msg = new StringExp(e2x.loc, "Accessed expression of type `noreturn`"); - msg.type = Type.tstring; - e2x = new AssertExp(e2x.loc, IntegerExp.literal!0, msg); - e2x.type = Type.tnoreturn; - return setResult(e2x); - } + auto etmp = checkNoreturnVarAccess(e2x); + if (etmp != e2x) + return setResult(etmp); + exp.e2 = e2x; } @@ -9890,14 +9934,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.type = exp.e1.type; assert(exp.type); + auto assignElem = exp.e2; auto res = exp.op == EXP.assign ? exp.reorderSettingAAElem(sc) : exp; - Expression tmp; /* https://issues.dlang.org/show_bug.cgi?id=22366 * * `reorderSettingAAElem` creates a tree of comma expressions, however, * `checkAssignExp` expects only AssignExps. */ - checkAssignEscape(sc, Expression.extractLast(res, tmp), false, false); + if (res == exp) // no `AA[k] = v` rewrite was performed + checkAssignEscape(sc, res, false, false); + else + checkNewEscape(sc, assignElem, false); // assigning to AA puts it on heap if (auto ae = res.isConstructExp()) { @@ -9905,40 +9952,48 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (t1b.ty != Tsarray && t1b.ty != Tarray) return setResult(res); - /* Do not lower Rvalues and references, as they need to be moved, - * not copied. - * Skip the lowering when the RHS is an array literal, as e2ir - * already handles such cases more elegantly. - */ - const isArrayCtor = - (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) && - ae.e2.isLvalue && - !(ae.e1.isVarExp && - ae.e1.isVarExp.var.isVarDeclaration.isReference) && - (ae.e2.isVarExp || - ae.e2.isSliceExp || - (ae.e2.type.ty == Tsarray && !ae.e2.isArrayLiteralExp)) && - ae.e1.type.nextOf && - ae.e2.type.nextOf && - ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf); - - /* Unlike isArrayCtor above, lower all Rvalues. If the RHS is a literal, - * then we do want to make a temporary for it and call its destructor. - */ - const isArraySetCtor = - (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) && - (ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) && - ae.e1.type.nextOf && - ae.e1.type.nextOf.equivalent(ae.e2.type); + // only non-trivial array constructions may need to be lowered (non-POD elements basically) + Type t1e = t1b.nextOf(); + TypeStruct ts = t1e.baseElemOf().isTypeStruct(); + if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor)) + return setResult(res); - if (isArrayCtor || isArraySetCtor) + // don't lower ref-constructions etc. + if (!(t1b.ty == Tsarray || ae.e1.isSliceExp) || + (ae.e1.isVarExp && ae.e1.isVarExp.var.isVarDeclaration.isReference)) + return setResult(res); + + // Construction from an equivalent other array? + // Only lower with lvalue RHS elements; let the glue layer move rvalue elements. + Type t2b = ae.e2.type.toBasetype(); + // skip over a (possibly implicit) cast of a static array RHS to a slice + Expression rhs = ae.e2; + Type rhsType = t2b; + if (t2b.ty == Tarray) { - const ts = t1b.nextOf().baseElemOf().isTypeStruct(); - if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor)) - return setResult(res); + if (auto ce = rhs.isCastExp()) + { + auto ct = ce.e1.type.toBasetype(); + if (ct.ty == Tsarray) + { + rhs = ce.e1; + rhsType = ct; + } + } + } + const lowerToArrayCtor = + ( (rhsType.ty == Tarray && !rhs.isArrayLiteralExp) || + (rhsType.ty == Tsarray && rhs.isLvalue) ) && + t1e.equivalent(t2b.nextOf); + + // Construction from a single element? + // If the RHS is an rvalue, then we'll need to make a temporary for it (copied multiple times). + const lowerToArraySetCtor = !lowerToArrayCtor && t1e.equivalent(t2b); - auto func = isArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor; - const other = isArrayCtor ? "other array" : "value"; + if (lowerToArrayCtor || lowerToArraySetCtor) + { + auto func = lowerToArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor; + const other = lowerToArrayCtor ? "other array" : "value"; if (!verifyHookExist(exp.loc, *sc, func, "construct array with " ~ other, Id.object)) return setError(); @@ -9948,18 +10003,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor id = new DotIdExp(exp.loc, id, func); auto arguments = new Expressions(); - arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf).expressionSemantic(sc)); - if (isArrayCtor) + arguments.push(new CastExp(ae.loc, ae.e1, t1e.arrayOf).expressionSemantic(sc)); + if (lowerToArrayCtor) { - arguments.push(new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf).expressionSemantic(sc)); + arguments.push(new CastExp(ae.loc, rhs, t2b.nextOf.arrayOf).expressionSemantic(sc)); Expression ce = new CallExp(exp.loc, id, arguments); res = ce.expressionSemantic(sc); } else { Expression e0; - // If ae.e2 is not a variable, construct a temp variable, as _d_arraysetctor requires `ref` access - if (!ae.e2.isVarExp) + // promote an rvalue RHS element to a temporary, it's passed by ref to _d_arraysetctor + if (!ae.e2.isLvalue) { auto vd = copyToTemp(STC.scope_, "__setctor", ae.e2); e0 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc); @@ -11759,6 +11814,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = arrayLowering; return; } + + if (t1.isTypeVector()) + exp.type = t1; + result = exp; return; } @@ -12038,6 +12097,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + if (t1.isTypeVector()) + exp.type = t1; + result = exp; } @@ -12490,8 +12552,7 @@ Expression semanticX(DotIdExp exp, Scope* sc) if (f.checkForwardRef(loc)) return ErrorExp.get(); - if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess | - FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess)) + if (f.purityInprocess || f.safetyInprocess || f.nothrowInprocess || f.nogcInprocess) { f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes"); return ErrorExp.get(); @@ -13099,7 +13160,7 @@ Lerr: */ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) { - if (!global.params.noSharedAccess || + if (global.params.noSharedAccess != FeatureState.enabled || sc.intypeof || sc.flags & SCOPE.ctfe) { diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index bcae282..3b0b34e 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -182,7 +182,7 @@ public: catches.push(ctch); Statement s2 = new TryCatchStatement(Loc.initial, s._body, catches); - fd.flags &= ~FUNCFLAG.noEH; + fd.hasNoEH = false; replaceCurrent(s2); s2.accept(this); } @@ -191,31 +191,31 @@ public: } } -enum FUNCFLAG : uint +private struct FUNCFLAG { - purityInprocess = 1, /// working on determining purity - safetyInprocess = 2, /// working on determining safety - nothrowInprocess = 4, /// working on determining nothrow - nogcInprocess = 8, /// working on determining @nogc - returnInprocess = 0x10, /// working on inferring 'return' for parameters - inlineScanned = 0x20, /// function has been scanned for inline possibilities - inferScope = 0x40, /// infer 'scope' for parameters - hasCatches = 0x80, /// function has try-catch statements - compileTimeOnly = 0x100, /// is a compile time only function; no code will be generated for it - printf = 0x200, /// is a printf-like function - scanf = 0x400, /// is a scanf-like function - noreturn = 0x800, /// the function does not return - NRVO = 0x1000, /// Support for named return value optimization - naked = 0x2000, /// The function is 'naked' (see inline ASM) - generated = 0x4000, /// The function is compiler generated (e.g. `opCmp`) - introducing = 0x8000, /// If this function introduces the overload set - semantic3Errors = 0x10000, /// If errors in semantic3 this function's frame ptr - noEH = 0x20000, /// No exception unwinding is needed - inferRetType = 0x40000, /// Return type is to be inferred - dualContext = 0x80000, /// has a dual-context 'this' parameter - hasAlwaysInline = 0x100000, /// Contains references to functions that must be inlined - CRTCtor = 0x200000, /// Has attribute pragma(crt_constructor) - CRTDtor = 0x400000, /// Has attribute pragma(crt_destructor) + bool purityInprocess; /// working on determining purity + bool safetyInprocess; /// working on determining safety + bool nothrowInprocess; /// working on determining nothrow + bool nogcInprocess; /// working on determining @nogc + bool returnInprocess; /// working on inferring 'return' for parameters + bool inlineScanned; /// function has been scanned for inline possibilities + bool inferScope; /// infer 'scope' for parameters + bool hasCatches; /// function has try-catch statements + bool isCompileTimeOnly; /// is a compile time only function; no code will be generated for it + bool printf; /// is a printf-like function + bool scanf; /// is a scanf-like function + bool noreturn; /// the function does not return + bool isNRVO = true; /// Support for named return value optimization + bool isNaked; /// The function is 'naked' (see inline ASM) + bool isGenerated; /// The function is compiler generated (e.g. `opCmp`) + bool isIntroducing; /// If this function introduces the overload set + bool hasSemantic3Errors; /// If errors in semantic3 this function's frame ptr + bool hasNoEH; /// No exception unwinding is needed + bool inferRetType; /// Return type is to be inferred + bool hasDualContext; /// has a dual-context 'this' parameter + bool hasAlwaysInlines; /// Contains references to functions that must be inlined + bool isCrtCtor; /// Has attribute pragma(crt_constructor) + bool isCrtDtor; /// Has attribute pragma(crt_destructor) } /*********************************************************** @@ -348,9 +348,9 @@ extern (C++) class FuncDeclaration : Declaration /// better diagnostics AttributeViolation* safetyViolation; - /// Function flags: A collection of boolean packed for memory efficiency - /// See the `FUNCFLAG` enum - uint flags = FUNCFLAG.NRVO; + /// See the `FUNCFLAG` struct + import dmd.common.bitfields; + mixin(generateBitFields!(FUNCFLAG, uint)); /** * Data for a function declaration that is needed for the Objective-C @@ -373,13 +373,13 @@ extern (C++) class FuncDeclaration : Declaration } this.endloc = endloc; if (noreturn) - this.flags |= FUNCFLAG.noreturn; + this.noreturn = true; /* The type given for "infer the return type" is a TypeFunction with * NULL for the return type. */ if (type && type.nextOf() is null) - this.flags |= FUNCFLAG.inferRetType; + this.inferRetType = true; } static FuncDeclaration create(const ref Loc loc, const ref Loc endloc, Identifier id, StorageClass storage_class, Type type, bool noreturn = false) @@ -391,7 +391,7 @@ extern (C++) class FuncDeclaration : Declaration { //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars()); FuncDeclaration f = s ? cast(FuncDeclaration)s - : new FuncDeclaration(loc, endloc, ident, storage_class, type.syntaxCopy(), (flags & FUNCFLAG.noreturn) != 0); + : new FuncDeclaration(loc, endloc, ident, storage_class, type.syntaxCopy(), this.noreturn != 0); f.frequires = frequires ? Statement.arraySyntaxCopy(frequires) : null; f.fensures = fensures ? Ensure.arraySyntaxCopy(fensures) : null; f.fbody = fbody ? fbody.syntaxCopy() : null; @@ -522,7 +522,7 @@ extern (C++) class FuncDeclaration : Declaration { const bool dualCtx = (toParent2() != toParentLocal()); if (dualCtx) - this.flags |= FUNCFLAG.dualContext; + this.hasDualContext = true; auto ad = isThis(); if (!dualCtx && !ad && !isNested()) { @@ -1376,29 +1376,29 @@ extern (C++) class FuncDeclaration : Declaration //printf("initInferAttributes() for %s (%s)\n", toPrettyChars(), ident.toChars()); TypeFunction tf = type.toTypeFunction(); if (tf.purity == PURE.impure) // purity not specified - flags |= FUNCFLAG.purityInprocess; + purityInprocess = true; if (tf.trust == TRUST.default_) - flags |= FUNCFLAG.safetyInprocess; + safetyInprocess = true; if (!tf.isnothrow) - flags |= FUNCFLAG.nothrowInprocess; + nothrowInprocess = true; if (!tf.isnogc) - flags |= FUNCFLAG.nogcInprocess; + nogcInprocess = true; if (!isVirtual() || this.isIntroducing()) - flags |= FUNCFLAG.returnInprocess; + returnInprocess = true; // Initialize for inferring STC.scope_ - flags |= FUNCFLAG.inferScope; + inferScope = true; } final PURE isPure() { //printf("FuncDeclaration::isPure() '%s'\n", toChars()); TypeFunction tf = type.toTypeFunction(); - if (flags & FUNCFLAG.purityInprocess) + if (purityInprocess) setImpure(); if (tf.purity == PURE.fwdref) tf.purityLevel(); @@ -1424,7 +1424,7 @@ extern (C++) class FuncDeclaration : Declaration final PURE isPureBypassingInference() { - if (flags & FUNCFLAG.purityInprocess) + if (purityInprocess) return PURE.fwdref; else return isPure(); @@ -1437,9 +1437,9 @@ extern (C++) class FuncDeclaration : Declaration */ extern (D) final bool setImpure() { - if (flags & FUNCFLAG.purityInprocess) + if (purityInprocess) { - flags &= ~FUNCFLAG.purityInprocess; + purityInprocess = false; if (fes) fes.func.setImpure(); } @@ -1448,21 +1448,32 @@ extern (C++) class FuncDeclaration : Declaration return false; } + extern (D) final uint flags() + { + return bitFields; + } + + extern (D) final uint flags(uint f) + { + bitFields = f; + return bitFields; + } + final bool isSafe() { - if (flags & FUNCFLAG.safetyInprocess) + if (safetyInprocess) setUnsafe(); return type.toTypeFunction().trust == TRUST.safe; } final bool isSafeBypassingInference() { - return !(flags & FUNCFLAG.safetyInprocess) && isSafe(); + return !(safetyInprocess) && isSafe(); } final bool isTrusted() { - if (flags & FUNCFLAG.safetyInprocess) + if (safetyInprocess) setUnsafe(); return type.toTypeFunction().trust == TRUST.trusted; } @@ -1483,9 +1494,9 @@ extern (C++) class FuncDeclaration : Declaration bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { - if (flags & FUNCFLAG.safetyInprocess) + if (safetyInprocess) { - flags &= ~FUNCFLAG.safetyInprocess; + safetyInprocess = false; type.toTypeFunction().trust = TRUST.system; if (fmt || arg0) safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1, arg2); @@ -1518,99 +1529,14 @@ extern (C++) class FuncDeclaration : Declaration final bool isNogc() { //printf("isNogc() %s, inprocess: %d\n", toChars(), !!(flags & FUNCFLAG.nogcInprocess)); - if (flags & FUNCFLAG.nogcInprocess) + if (nogcInprocess) setGC(); return type.toTypeFunction().isnogc; } final bool isNogcBypassingInference() { - return !(flags & FUNCFLAG.nogcInprocess) && isNogc(); - } - - final bool isNRVO() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.NRVO); - } - - final void isNRVO(bool v) pure nothrow @safe @nogc - { - if (v) this.flags |= FUNCFLAG.NRVO; - else this.flags &= ~FUNCFLAG.NRVO; - } - - final bool isNaked() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.naked); - } - - final void isNaked(bool v) @safe pure nothrow @nogc - { - if (v) this.flags |= FUNCFLAG.naked; - else this.flags &= ~FUNCFLAG.naked; - } - - final bool isGenerated() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.generated); - } - - final void isGenerated(bool v) pure nothrow @safe @nogc - { - if (v) this.flags |= FUNCFLAG.generated; - else this.flags &= ~FUNCFLAG.generated; - } - - final bool isIntroducing() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.introducing); - } - - final bool hasSemantic3Errors() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.semantic3Errors); - } - - final bool hasNoEH() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.noEH); - } - - final bool inferRetType() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.inferRetType); - } - - final bool hasDualContext() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.dualContext); - } - - final bool hasAlwaysInlines() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.hasAlwaysInline); - } - - final bool isCrtCtor() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.CRTCtor); - } - - final void isCrtCtor(bool v) @safe pure nothrow @nogc - { - if (v) this.flags |= FUNCFLAG.CRTCtor; - else this.flags &= ~FUNCFLAG.CRTCtor; - } - - final bool isCrtDtor() const scope @safe pure nothrow @nogc - { - return !!(this.flags & FUNCFLAG.CRTDtor); - } - - final void isCrtDtor(bool v) @safe pure nothrow @nogc - { - if (v) this.flags |= FUNCFLAG.CRTDtor; - else this.flags &= ~FUNCFLAG.CRTDtor; + return !nogcInprocess && isNogc(); } /************************************** @@ -1622,15 +1548,15 @@ extern (C++) class FuncDeclaration : Declaration extern (D) final bool setGC() { //printf("setGC() %s\n", toChars()); - if (flags & FUNCFLAG.nogcInprocess && semanticRun < PASS.semantic3 && _scope) + if (nogcInprocess && semanticRun < PASS.semantic3 && _scope) { this.semantic2(_scope); this.semantic3(_scope); } - if (flags & FUNCFLAG.nogcInprocess) + if (nogcInprocess) { - flags &= ~FUNCFLAG.nogcInprocess; + nogcInprocess = false; type.toTypeFunction().isnogc = false; if (fes) fes.func.setGC(); @@ -3384,6 +3310,28 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, // re-resolve to check for supplemental message if (!global.gag || global.params.showGaggedErrors) { + if (tthis) + { + if (auto classType = tthis.isTypeClass()) + { + if (auto baseClass = classType.sym.baseClass) + { + if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident)) + { + MatchAccumulator mErr; + functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, fargs, null); + if (mErr.last > MATCH.nomatch && mErr.lastf) + { + errorSupplemental(loc, "%s `%s` hides base class function `%s`", + fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars()); + errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets", + fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars()); + return null; + } + } + } + } + } const(char)* failMessage; functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, &failMessage); if (failMessage) @@ -3767,7 +3715,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration this.fes = fes; // Always infer scope for function literals // See https://issues.dlang.org/show_bug.cgi?id=20362 - this.flags |= FUNCFLAG.inferScope; + this.inferScope = true; //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this.ident.toChars(), type.toChars()); } @@ -4431,6 +4379,58 @@ bool setUnsafe(Scope* sc, return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1, arg2); } +/*************************************** + * Like `setUnsafe`, but for safety errors still behind preview switches + * + * Given a `FeatureState fs`, for example dip1000 / dip25 / systemVariables, + * the behavior changes based on the setting: + * + * - In case of `-revert=fs`, it does nothing. + * - In case of `-preview=fs`, it's the same as `setUnsafe` + * - By default, print a deprecation in `@safe` functions, or store an attribute violation in inferred functions. + * + * Params: + * sc = used to find affected function/variable, and for checking whether we are in a deprecated / speculative scope + * fs = feature state from the preview flag + * gag = surpress error message + * loc = location of error + * msg = printf-style format string + * arg0 = (optional) argument for first %s format specifier + * arg1 = (optional) argument for second %s format specifier + * arg2 = (optional) argument for third %s format specifier + * Returns: whether an actual safe error (not deprecation) occured + */ +bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) +{ + if (fs == FeatureState.disabled) + { + return false; + } + else if (fs == FeatureState.enabled) + { + return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2); + } + else + { + if (!sc.func) + return false; + if (sc.func.isSafeBypassingInference()) + { + if (!gag) + previewErrorFunc(sc.isDeprecated(), fs)( + loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "" + ); + } + else if (!sc.func.safetyViolation) + { + import dmd.func : AttributeViolation; + sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2); + } + return false; + } +} + /// Stores a reason why a function failed to infer a function attribute like `@safe` or `pure` /// /// Has two modes: diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d index 745d5eb..2770f5a 100644 --- a/gcc/d/dmd/globals.d +++ b/gcc/d/dmd/globals.d @@ -160,15 +160,16 @@ extern (C++) struct Param // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html // Implementation: https://github.com/dlang/dmd/pull/9817 - bool noSharedAccess; // read/write access to shared memory objects + FeatureState noSharedAccess; // read/write access to shared memory objects bool previewIn; // `in` means `[ref] scope const`, accepts rvalues bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract - bool shortenedMethods; // allow => in normal function declarations + bool shortenedMethods = true; // allow => in normal function declarations bool fixImmutableConv; // error on unsound immutable conversion - https://github.com/dlang/dmd/pull/14070 bool fix16997 = true; // fix integral promotions for unary + - ~ operators // https://issues.dlang.org/show_bug.cgi?id=16997 FeatureState dtorFields; // destruct fields of partially constructed objects // https://issues.dlang.org/show_bug.cgi?id=14246 + FeatureState systemVariables; // limit access to variables marked @system from @safe code CHECKENABLE useInvariants = CHECKENABLE._default; // generate class invariant checks CHECKENABLE useIn = CHECKENABLE._default; // generate precondition checks diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index a6b1c90..d9cb76c 100644 --- a/gcc/d/dmd/globals.h +++ b/gcc/d/dmd/globals.h @@ -158,7 +158,7 @@ struct Param // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html // Implementation: https://github.com/dlang/dmd/pull/9817 - bool noSharedAccess; // read/write access to shared memory objects + FeatureState noSharedAccess; // read/write access to shared memory objects bool previewIn; // `in` means `[ref] scope const`, accepts rvalues bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract bool shortenedMethods; // allow => in normal function declarations @@ -166,7 +166,9 @@ struct Param bool fix16997; // fix integral promotions for unary + - ~ operators // https://issues.dlang.org/show_bug.cgi?id=16997 FeatureState dtorFields; // destruct fields of partially constructed objects - // https://issues.dlang.org/show_bug.cgi?id=14246 + // https://issues.dlang.org/show_bug.cgi?id=14246 + FeatureState systemVariables; // limit access to variables marked @system from @safe code + CHECKENABLE useInvariants; // generate class invariant checks CHECKENABLE useIn; // generate precondition checks CHECKENABLE useOut; // generate postcondition checks diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index 48995db..debf01d 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -64,6 +64,7 @@ struct HdrGenState int tpltMember; int autoMember; int forStmtInit; + int insideFuncBody; bool declstring; // set while declaring alias for string,wstring or dstring EnumDeclaration inEnumDecl; @@ -1045,8 +1046,18 @@ public: buf.writestring(", "); argsToBuffer(d.args, buf, hgs); } + buf.writeByte(')'); + + // https://issues.dlang.org/show_bug.cgi?id=14690 + // Unconditionally perform a full output dump + // for `pragma(inline)` declarations. + bool savedFullDump = global.params.dihdr.fullOutput; + if (d.ident == Id.Pinline) + global.params.dihdr.fullOutput = true; + visit(cast(AttribDeclaration)d); + global.params.dihdr.fullOutput = savedFullDump; } override void visit(ConditionalDeclaration d) @@ -1549,7 +1560,7 @@ public: bodyToBuffer(f); hgs.autoMember--; } - else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false) + else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false && !hgs.insideFuncBody) { if (!f.fbody) { @@ -1634,7 +1645,7 @@ public: void bodyToBuffer(FuncDeclaration f) { - if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember)) + if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody)) { if (!f.fbody && (f.fensures || f.frequires)) { @@ -1645,6 +1656,18 @@ public: buf.writenl(); return; } + + // there is no way to know if a function is nested + // or not after parsing. We need scope information + // for that, which is avaible during semantic + // analysis. To overcome that, a simple mechanism + // is implemented: everytime we print a function + // body (templated or not) we increment a counter. + // We decredement the counter when we stop + // printing the function body. + ++hgs.insideFuncBody; + scope(exit) { --hgs.insideFuncBody; } + const savetlpt = hgs.tpltMember; const saveauto = hgs.autoMember; hgs.tpltMember = 0; diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index 1de89d4..451e227 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -1197,9 +1197,9 @@ class Lexer /******************************************* * Parse escape sequence. */ - private uint escapeSequence() + private uint escapeSequence(out dchar c2) { - return Lexer.escapeSequence(token.loc, p, Ccompile); + return Lexer.escapeSequence(token.loc, p, Ccompile, c2); } /******** @@ -1211,10 +1211,11 @@ class Lexer * sequence = pointer to string with escape sequence to parse. Updated to * point past the end of the escape sequence * Ccompile = true for compile C11 escape sequences + * c2 = returns second `dchar` of html entity with 2 code units, otherwise stays `dchar.init` * Returns: * the escape sequence as a single character */ - private dchar escapeSequence(const ref Loc loc, ref const(char)* sequence, bool Ccompile) + private dchar escapeSequence(const ref Loc loc, ref const(char)* sequence, bool Ccompile, out dchar c2) { const(char)* p = sequence; // cache sequence reference on stack scope(exit) sequence = p; @@ -1326,12 +1327,16 @@ class Lexer switch (*p) { case ';': - c = HtmlNamedEntity(idstart[0 .. p - idstart]); - if (c == ~0) + auto entity = HtmlNamedEntity(idstart[0 .. p - idstart]); + c = entity[0]; + if (entity == entity.init) { error(loc, "unnamed character entity &%.*s;", cast(int)(p - idstart), idstart); c = '?'; } + if (entity[1] != entity.init[1]) + c2 = entity[1]; + p++; break; default: @@ -1665,6 +1670,7 @@ class Lexer while (1) { dchar c = *p++; + dchar c2; switch (c) { case '\\': @@ -1673,15 +1679,19 @@ class Lexer case '&': if (Ccompile) goto default; - goto case; + c = escapeSequence(c2); + stringbuffer.writeUTF8(c); + if (c2 != dchar.init) + stringbuffer.writeUTF8(c2); + continue; case 'u': case 'U': - c = escapeSequence(); + c = escapeSequence(c2); stringbuffer.writeUTF8(c); continue; default: - c = escapeSequence(); + c = escapeSequence(c2); break; } break; @@ -1746,22 +1756,26 @@ class Lexer //printf("Lexer::charConstant\n"); p++; dchar c = *p++; + dchar c2; switch (c) { case '\\': switch (*p) { case 'u': - t.unsvalue = escapeSequence(); tk = TOK.wcharLiteral; - break; + goto default; case 'U': case '&': - t.unsvalue = escapeSequence(); tk = TOK.dcharLiteral; - break; + goto default; default: - t.unsvalue = escapeSequence(); + t.unsvalue = escapeSequence(c2); + if (c2 != c2.init) + { + error("html entity requires 2 code units, use a string instead of a character"); + t.unsvalue = '?'; + } break; } break; @@ -1978,8 +1992,6 @@ class Lexer break; case 'b': case 'B': - if (Ccompile) - error("binary constants not allowed"); ++p; base = 2; break; @@ -3185,8 +3197,9 @@ unittest static void test(T)(string sequence, T expected, bool Ccompile = false) { auto p = cast(const(char)*)sequence.ptr; + dchar c2; Lexer lexer = new Lexer(); - assert(expected == lexer.escapeSequence(Loc.initial, p, Ccompile)); + assert(expected == lexer.escapeSequence(Loc.initial, p, Ccompile, c2)); assert(p == sequence.ptr + sequence.length); } @@ -3253,7 +3266,8 @@ unittest expected = expectedError; auto p = cast(const(char)*)sequence.ptr; Lexer lexer = new Lexer(); - auto actualReturnValue = lexer.escapeSequence(Loc.initial, p, Ccompile); + dchar c2; + auto actualReturnValue = lexer.escapeSequence(Loc.initial, p, Ccompile, c2); assert(gotError); assert(expectedReturnValue == actualReturnValue); diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h index 341ce36..48046de 100644 --- a/gcc/d/dmd/module.h +++ b/gcc/d/dmd/module.h @@ -116,7 +116,7 @@ public: size_t namelen; // length of module name in characters static Module* create(const char *arg, Identifier *ident, int doDocComment, int doHdrGen); - + static const char *find(const char *filename); static Module *load(const Loc &loc, Identifiers *packages, Identifier *ident); const char *kind() const override; diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index 1240f5a..265f731 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -2488,6 +2488,16 @@ extern (C++) abstract class Type : ASTNode return false; } + /************************************* + * Detect if this is an unsafe type because of the presence of `@system` members + * Returns: + * true if so + */ + bool hasSystemFields() + { + return false; + } + /*************************************** * Returns: true if type has any invariants */ @@ -3821,6 +3831,16 @@ extern (C++) final class TypeSArray : TypeArray return next.hasPointers(); } + override bool hasSystemFields() + { + return next.hasSystemFields(); + } + + override bool hasVoidInitPointers() + { + return next.hasVoidInitPointers(); + } + override bool hasInvariant() { return next.hasInvariant(); @@ -5532,52 +5552,32 @@ extern (C++) final class TypeStruct : Type override bool hasPointers() { - // Probably should cache this information in sym rather than recompute - StructDeclaration s = sym; - if (sym.members && !sym.determineFields() && sym.type != Type.terror) error(sym.loc, "no size because of forward references"); - foreach (VarDeclaration v; s.fields) - { - if (v.storage_class & STC.ref_ || v.hasPointers()) - return true; - } - return false; + sym.determineTypeProperties(); + return sym.hasPointerField; } override bool hasVoidInitPointers() { - // Probably should cache this information in sym rather than recompute - StructDeclaration s = sym; + sym.size(Loc.initial); // give error for forward references + sym.determineTypeProperties(); + return sym.hasVoidInitPointers; + } + override bool hasSystemFields() + { sym.size(Loc.initial); // give error for forward references - foreach (VarDeclaration v; s.fields) - { - if (v._init && v._init.isVoidInitializer() && v.type.hasPointers()) - return true; - if (!v._init && v.type.hasVoidInitPointers()) - return true; - } - return false; + sym.determineTypeProperties(); + return sym.hasSystemFields; } override bool hasInvariant() { - // Probably should cache this information in sym rather than recompute - StructDeclaration s = sym; - sym.size(Loc.initial); // give error for forward references - - if (s.hasInvariant()) - return true; - - foreach (VarDeclaration v; s.fields) - { - if (v.type.hasInvariant()) - return true; - } - return false; + sym.determineTypeProperties(); + return sym.hasInvariant() || sym.hasFieldWithInvariant; } extern (D) MATCH implicitConvToWithoutAliasThis(Type to) @@ -5857,6 +5857,11 @@ extern (C++) final class TypeEnum : Type return memType().hasVoidInitPointers(); } + override bool hasSystemFields() + { + return memType().hasSystemFields(); + } + override bool hasInvariant() { return memType().hasInvariant(); diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index 2b9c94c..c81c25a 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -311,6 +311,7 @@ public: virtual int hasWild() const; virtual bool hasPointers(); virtual bool hasVoidInitPointers(); + virtual bool hasSystemFields(); virtual bool hasInvariant(); virtual Type *nextOf(); Type *baseElemOf(); @@ -458,6 +459,8 @@ public: MATCH implicitConvTo(Type *to) override; Expression *defaultInitLiteral(const Loc &loc) override; bool hasPointers() override; + bool hasSystemFields() override; + bool hasVoidInitPointers() override; bool hasInvariant() override; bool needsDestruction() override; bool needsCopyOrPostblit() override; @@ -794,6 +797,7 @@ public: bool needsNested() override; bool hasPointers() override; bool hasVoidInitPointers() override; + bool hasSystemFields() override; bool hasInvariant() override; MATCH implicitConvTo(Type *to) override; MATCH constConv(Type *to) override; @@ -832,6 +836,7 @@ public: bool isZeroInit(const Loc &loc) override; bool hasPointers() override; bool hasVoidInitPointers() override; + bool hasSystemFields() override; bool hasInvariant() override; Type *nextOf() override; diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d index 8cf3585..7ddeeec 100644 --- a/gcc/d/dmd/nogc.d +++ b/gcc/d/dmd/nogc.d @@ -99,7 +99,7 @@ public: override void visit(ArrayLiteralExp e) { - if (e.type.ty != Tarray || !e.elements || !e.elements.dim) + if (e.type.ty != Tarray || !e.elements || !e.elements.dim || e.onstack) return; if (f.setGC()) { @@ -221,7 +221,7 @@ Expression checkGC(Scope* sc, Expression e) FuncDeclaration f = sc.func; if (e && e.op != EXP.error && f && sc.intypeof != 1 && !(sc.flags & SCOPE.ctfe) && (f.type.ty == Tfunction && - (cast(TypeFunction)f.type).isnogc || (f.flags & FUNCFLAG.nogcInprocess) || global.params.vgc) && + (cast(TypeFunction)f.type).isnogc || f.nogcInprocess || global.params.vgc) && !(sc.flags & SCOPE.debug_)) { scope NOGCVisitor gcv = new NOGCVisitor(f); diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index ed85a5d..6fb542f 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -888,6 +888,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer error("redundant visibility attribute `%s`", AST.visibilityToChars(prot)); } pAttrs.visibility.kind = prot; + const attrloc = token.loc; nextToken(); @@ -908,7 +909,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } } - const attrloc = token.loc; a = parseBlock(pLastDecl, pAttrs); if (pAttrs.visibility.kind != AST.Visibility.Kind.undefined) { @@ -3168,9 +3168,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (udas) { - auto s = new AST.Dsymbols(); - s.push(em); - auto uad = new AST.UserAttributeDeclaration(udas, s); + auto uad = new AST.UserAttributeDeclaration(udas, new AST.Dsymbols()); em.userAttribDecl = uad; } diff --git a/gcc/d/dmd/printast.d b/gcc/d/dmd/printast.d index bba3481..8c71a1a 100644 --- a/gcc/d/dmd/printast.d +++ b/gcc/d/dmd/printast.d @@ -203,6 +203,13 @@ extern (C++) final class PrintASTVisitor : Visitor printf(".func: %s\n", e.func ? e.func.toChars() : ""); } + override void visit(CompoundLiteralExp e) + { + visit(cast(Expression)e); + printIndent(indent + 2); + printf(".init: %s\n", e.initializer ? e.initializer.toChars() : ""); + } + static void printIndent(int indent) { foreach (i; 0 .. indent) diff --git a/gcc/d/dmd/root/utf.d b/gcc/d/dmd/root/utf.d index 15838e9..eb198fc 100644 --- a/gcc/d/dmd/root/utf.d +++ b/gcc/d/dmd/root/utf.d @@ -288,7 +288,7 @@ bool isUniAlpha(dchar c) // Binary search while (low <= high) { - size_t mid = (low + high) >> 1; + const size_t mid = low + ((high - low) >> 1); if (c < ALPHA_TABLE[mid][0]) high = mid - 1; else if (ALPHA_TABLE[mid][1] < c) diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d index 4446b5e..397fd2ef 100644 --- a/gcc/d/dmd/safe.d +++ b/gcc/d/dmd/safe.d @@ -26,7 +26,7 @@ import dmd.identifier; import dmd.mtype; import dmd.target; import dmd.tokens; -import dmd.func : setUnsafe; +import dmd.func : setUnsafe, setUnsafePreview; /************************************************************* * Check for unsafe access in @safe code: @@ -57,6 +57,14 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) if (!ad) return false; + import dmd.globals : global; + if (v.isSystem()) + { + if (sc.setUnsafePreview(global.params.systemVariables, !printmsg, e.loc, + "cannot access `@system` field `%s.%s` in `@safe` code", ad, v)) + return true; + } + // needed to set v.overlapped and v.overlapUnsafe if (ad.sizeok != Sizeok.done) ad.determineSize(ad.loc); diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index d2f9c0a..8ea419a 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -282,7 +282,7 @@ private extern(C++) final class Semantic3Visitor : Visitor // Disable generated opAssign, because some members forbid identity assignment. funcdecl.storage_class |= STC.disable; funcdecl.fbody = null; // remove fbody which contains the error - funcdecl.flags &= ~FUNCFLAG.semantic3Errors; + funcdecl.hasSemantic3Errors = false; } return; } @@ -292,7 +292,7 @@ private extern(C++) final class Semantic3Visitor : Visitor if (funcdecl.semanticRun >= PASS.semantic3) return; funcdecl.semanticRun = PASS.semantic3; - funcdecl.flags &= ~FUNCFLAG.semantic3Errors; + funcdecl.hasSemantic3Errors = false; if (!funcdecl.type || funcdecl.type.ty != Tfunction) return; @@ -650,7 +650,7 @@ private extern(C++) final class Semantic3Visitor : Visitor // handle NRVO if (!target.isReturnOnStack(f, funcdecl.needThis()) || !funcdecl.checkNRVO()) - funcdecl.flags &= ~FUNCFLAG.NRVO; + funcdecl.isNRVO = false; if (funcdecl.fbody.isErrorStatement()) { @@ -753,15 +753,15 @@ private extern(C++) final class Semantic3Visitor : Visitor if (f.isnothrow && blockexit & BE.throw_) error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars()); - if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.flags & FUNCFLAG.hasCatches)) + if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.hasCatches)) { /* Don't generate unwind tables for this function * https://issues.dlang.org/show_bug.cgi?id=17997 */ - funcdecl.flags |= FUNCFLAG.noEH; + funcdecl.hasNoEH = true; } - if (funcdecl.flags & FUNCFLAG.nothrowInprocess) + if (funcdecl.nothrowInprocess) { if (funcdecl.type == f) f = cast(TypeFunction)f.copy(); @@ -976,7 +976,7 @@ private extern(C++) final class Semantic3Visitor : Visitor /* Do the semantic analysis on the [in] preconditions and * [out] postconditions. */ - immutable bool isnothrow = f.isnothrow && !(funcdecl.flags & FUNCFLAG.nothrowInprocess); + immutable bool isnothrow = f.isnothrow && !funcdecl.nothrowInprocess; if (freq) { /* frequire is composed of the [in] contracts @@ -1001,11 +1001,11 @@ private extern(C++) final class Semantic3Visitor : Visitor // Deprecated in 2.101, can be made an error in 2.111 deprecation(funcdecl.loc, "`%s`: `in` contract may throw but function is marked as `nothrow`", funcdecl.toPrettyChars()); - else if (funcdecl.flags & FUNCFLAG.nothrowInprocess) + else if (funcdecl.nothrowInprocess) f.isnothrow = false; } - funcdecl.flags &= ~FUNCFLAG.noEH; + funcdecl.hasNoEH = false; sc2 = sc2.pop(); @@ -1048,11 +1048,11 @@ private extern(C++) final class Semantic3Visitor : Visitor // Deprecated in 2.101, can be made an error in 2.111 deprecation(funcdecl.loc, "`%s`: `out` contract may throw but function is marked as `nothrow`", funcdecl.toPrettyChars()); - else if (funcdecl.flags & FUNCFLAG.nothrowInprocess) + else if (funcdecl.nothrowInprocess) f.isnothrow = false; } - funcdecl.flags &= ~FUNCFLAG.noEH; + funcdecl.hasNoEH = false; sc2 = sc2.pop(); @@ -1180,10 +1180,10 @@ private extern(C++) final class Semantic3Visitor : Visitor const blockexit = s.blockExit(funcdecl, isnothrow); if (blockexit & BE.throw_) { - funcdecl.flags &= ~FUNCFLAG.noEH; + funcdecl.hasNoEH = false; if (isnothrow) error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars()); - else if (funcdecl.flags & FUNCFLAG.nothrowInprocess) + else if (funcdecl.nothrowInprocess) f.isnothrow = false; } @@ -1195,7 +1195,7 @@ private extern(C++) final class Semantic3Visitor : Visitor } } // from this point on all possible 'throwers' are checked - funcdecl.flags &= ~FUNCFLAG.nothrowInprocess; + funcdecl.nothrowInprocess = false; if (funcdecl.isSynchronized()) { @@ -1274,25 +1274,25 @@ private extern(C++) final class Semantic3Visitor : Visitor /* If function survived being marked as impure, then it is pure */ - if (funcdecl.flags & FUNCFLAG.purityInprocess) + if (funcdecl.purityInprocess) { - funcdecl.flags &= ~FUNCFLAG.purityInprocess; + funcdecl.purityInprocess = false; if (funcdecl.type == f) f = cast(TypeFunction)f.copy(); f.purity = PURE.fwdref; } - if (funcdecl.flags & FUNCFLAG.safetyInprocess) + if (funcdecl.safetyInprocess) { - funcdecl.flags &= ~FUNCFLAG.safetyInprocess; + funcdecl.safetyInprocess = false; if (funcdecl.type == f) f = cast(TypeFunction)f.copy(); f.trust = TRUST.safe; } - if (funcdecl.flags & FUNCFLAG.nogcInprocess) + if (funcdecl.nogcInprocess) { - funcdecl.flags &= ~FUNCFLAG.nogcInprocess; + funcdecl.nogcInprocess = false; if (funcdecl.type == f) f = cast(TypeFunction)f.copy(); f.isnogc = true; @@ -1395,9 +1395,9 @@ private extern(C++) final class Semantic3Visitor : Visitor */ funcdecl.semanticRun = PASS.semantic3done; if ((global.errors != oldErrors) || (funcdecl.fbody && funcdecl.fbody.isErrorStatement())) - funcdecl.flags |= FUNCFLAG.semantic3Errors; + funcdecl.hasSemantic3Errors = true; else - funcdecl.flags &= ~FUNCFLAG.semantic3Errors; + funcdecl.hasSemantic3Errors = false; if (funcdecl.type.ty == Terror) funcdecl.errors = true; //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), sc, funcdecl.loc.toChars()); diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index e5e5753..4f9baf8 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -2010,32 +2010,8 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor //printf("body = %p\n", ps._body); if (ps.ident == Id.msg) { - if (ps.args) - { - foreach (arg; *ps.args) - { - sc = sc.startCTFE(); - auto e = arg.expressionSemantic(sc); - e = resolveProperties(sc, e); - sc = sc.endCTFE(); - - // pragma(msg) is allowed to contain types as well as expressions - e = ctfeInterpretForPragmaMsg(e); - if (e.op == EXP.error) - { - errorSupplemental(ps.loc, "while evaluating `pragma(msg, %s)`", arg.toChars()); - return setError(); - } - if (auto se = e.toStringExp()) - { - const slice = se.toUTF8(sc).peekString(); - fprintf(stderr, "%.*s", cast(int)slice.length, slice.ptr); - } - else - fprintf(stderr, "%s", e.toChars()); - } - fprintf(stderr, "\n"); - } + if (!pragmaMsgSemantic(ps.loc, sc, ps.args)) + return setError(); } else if (ps.ident == Id.lib) { @@ -2075,75 +2051,19 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor } else if (ps.ident == Id.startaddress) { - if (!ps.args || ps.args.dim != 1) - ps.error("function name expected for start address"); - else - { - Expression e = (*ps.args)[0]; - sc = sc.startCTFE(); - e = e.expressionSemantic(sc); - e = resolveProperties(sc, e); - sc = sc.endCTFE(); - - e = e.ctfeInterpret(); - (*ps.args)[0] = e; - Dsymbol sa = getDsymbol(e); - if (!sa || !sa.isFuncDeclaration()) - { - ps.error("function name expected for start address, not `%s`", e.toChars()); - return setError(); - } - if (ps._body) - { - ps._body = ps._body.statementSemantic(sc); - if (ps._body.isErrorStatement()) - { - result = ps._body; - return; - } - } - result = ps; - return; - } + if (!pragmaStartAddressSemantic(ps.loc, sc, ps.args)) + return setError(); } else if (ps.ident == Id.Pinline) { - PINLINE inlining = PINLINE.default_; - if (!ps.args || ps.args.dim == 0) - inlining = PINLINE.default_; - else if (!ps.args || ps.args.dim != 1) + if (auto fd = sc.func) { - ps.error("boolean expression expected for `pragma(inline)`"); - return setError(); + fd.inlining = evalPragmaInline(ps.loc, sc, ps.args); } else { - Expression e = (*ps.args)[0]; - sc = sc.startCTFE(); - e = e.expressionSemantic(sc); - e = resolveProperties(sc, e); - sc = sc.endCTFE(); - e = e.ctfeInterpret(); - e = e.toBoolean(sc); - if (e.isErrorExp()) - { - ps.error("pragma(`inline`, `true` or `false`) expected, not `%s`", (*ps.args)[0].toChars()); - return setError(); - } - - const opt = e.toBool(); - if (opt.hasValue(true)) - inlining = PINLINE.always; - else if (opt.hasValue(false)) - inlining = PINLINE.never; - - FuncDeclaration fd = sc.func; - if (!fd) - { - ps.error("`pragma(inline)` is not inside a function"); - return setError(); - } - fd.inlining = inlining; + ps.error("`pragma(inline)` is not inside a function"); + return setError(); } } else if (!global.params.ignoreUnsupportedPragmas) @@ -2932,13 +2852,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor } // https://issues.dlang.org/show_bug.cgi?id=23063 - if (texp.isTypeNoreturn() && !rs.exp.isAssertExp() && !rs.exp.isThrowExp() && !rs.exp.isCallExp()) - { - auto msg = new StringExp(rs.exp.loc, "Accessed expression of type `noreturn`"); - msg.type = Type.tstring; - rs.exp = new AssertExp(rs.loc, IntegerExp.literal!0, msg); - rs.exp.type = texp; - } + rs.exp = checkNoreturnVarAccess(rs.exp); // @@@DEPRECATED_2.111@@@ const olderrors = global.startGagging(); @@ -3022,7 +2936,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor // If we previously assumed the function could be ref when // checking for `shared`, make sure we were right - if (global.params.noSharedAccess && rs.exp.type.isShared()) + if (global.params.noSharedAccess == FeatureState.enabled && rs.exp.type.isShared()) { fd.error("function returns `shared` but cannot be inferred `ref`"); supplemental(); @@ -3648,7 +3562,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor if (sc.func) { - sc.func.flags |= FUNCFLAG.hasCatches; + sc.func.hasCatches = true; if (flags == (FLAGcpp | FLAGd)) { tcs.error("cannot mix catching D and C++ exceptions in the same try-catch"); @@ -4925,3 +4839,83 @@ private void debugThrowWalker(Statement s) scope walker = new DebugWalker(); s.accept(walker); } + +/*********************************************************** + * Evaluate and print a `pragma(msg, args)` + * + * Params: + * loc = location for error messages + * sc = scope for argument interpretation + * args = expressions to print + * Returns: + * `true` on success + */ +bool pragmaMsgSemantic(Loc loc, Scope* sc, Expressions* args) +{ + if (!args) + return true; + foreach (arg; *args) + { + sc = sc.startCTFE(); + auto e = arg.expressionSemantic(sc); + e = resolveProperties(sc, e); + sc = sc.endCTFE(); + + // pragma(msg) is allowed to contain types as well as expressions + e = ctfeInterpretForPragmaMsg(e); + if (e.op == EXP.error) + { + errorSupplemental(loc, "while evaluating `pragma(msg, %s)`", arg.toChars()); + return false; + } + if (auto se = e.toStringExp()) + { + const slice = se.toUTF8(sc).peekString(); + fprintf(stderr, "%.*s", cast(int)slice.length, slice.ptr); + } + else + fprintf(stderr, "%s", e.toChars()); + } + fprintf(stderr, "\n"); + return true; +} + +/*********************************************************** + * Evaluate `pragma(startAddress, func)` and store the resolved symbol in `args` + * + * Params: + * loc = location for error messages + * sc = scope for argument interpretation + * args = pragma arguments + * Returns: + * `true` on success + */ +bool pragmaStartAddressSemantic(Loc loc, Scope* sc, Expressions* args) +{ + if (!args || args.dim != 1) + { + .error(loc, "function name expected for start address"); + return false; + } + else + { + /* https://issues.dlang.org/show_bug.cgi?id=11980 + * resolveProperties and ctfeInterpret call are not necessary. + */ + Expression e = (*args)[0]; + sc = sc.startCTFE(); + e = e.expressionSemantic(sc); + // e = resolveProperties(sc, e); + sc = sc.endCTFE(); + + // e = e.ctfeInterpret(); + (*args)[0] = e; + Dsymbol sa = getDsymbol(e); + if (!sa || !sa.isFuncDeclaration()) + { + .error(loc, "function name expected for start address, not `%s`", e.toChars()); + return false; + } + } + return true; +} diff --git a/gcc/d/dmd/templateparamsem.d b/gcc/d/dmd/templateparamsem.d index e093260..e79a9ec 100644 --- a/gcc/d/dmd/templateparamsem.d +++ b/gcc/d/dmd/templateparamsem.d @@ -73,6 +73,15 @@ private extern (C++) final class TemplateParameterSemanticVisitor : Visitor result = !(ttp.specType && isError(ttp.specType)); } + override void visit(TemplateThisParameter ttp) + { + import dmd.errors; + + if (!sc.getStructClassScope()) + error(ttp.loc, "cannot use `this` outside an aggregate type"); + visit(cast(TemplateTypeParameter)ttp); + } + override void visit(TemplateValueParameter tvp) { tvp.valType = tvp.valType.typeSemantic(tvp.loc, sc); diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d index 0d7240f..cbe6daa 100644 --- a/gcc/d/dmd/transitivevisitor.d +++ b/gcc/d/dmd/transitivevisitor.d @@ -799,6 +799,15 @@ package mixin template ParseVisitMethods(AST) s.accept(this); } + override void visit(AST.InterfaceDeclaration d) + { + //printf("Visiting InterfaceDeclaration\n"); + visitBaseClasses(d); + if (d.members) + foreach (s; *d.members) + s.accept(this); + } + override void visit(AST.AliasDeclaration d) { //printf("Visting AliasDeclaration\n"); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index fa5ec90..e939e77 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -1099,6 +1099,7 @@ public: this assignment should call dtors on old assigned elements. */ if ((!postblit && !destructor) || (e->op == EXP::construct && e->e2->op == EXP::arrayLiteral) + || (e->op == EXP::construct && e->e2->op == EXP::call) || (e->op == EXP::construct && !lvalue && postblit) || (e->op == EXP::blit || e->e1->type->size () == 0)) { @@ -2704,6 +2705,14 @@ public: this->result_ = compound_expr (saved_elems, d_convert (type, ctor)); } + else if (e->onstack) + { + /* Array literal for a `scope' dynamic array. */ + gcc_assert (tb->ty == TY::Tarray); + ctor = force_target_expr (ctor); + this->result_ = d_array_value (type, size_int (e->elements->length), + build_address (ctor)); + } else { /* Allocate space on the memory managed heap. */ diff --git a/gcc/d/gdc.texi b/gcc/d/gdc.texi index 2bff627..d3bf75c 100644 --- a/gcc/d/gdc.texi +++ b/gcc/d/gdc.texi @@ -344,6 +344,9 @@ Turns on generation of struct equality to use field-wise comparisons. @item fixaliasthis Implements new lookup rules that check the current scope for @code{alias this} before searching in upper scopes. +@item fiximmutableconv +Disallows unsound immutable conversions that were formerly incorrectly +permitted. @item in Implements @code{in} parameters to mean @code{scope const [ref]} and accepts rvalues. @@ -357,9 +360,8 @@ expressions. Turns off and disallows all access to shared memory objects. @item rvaluerefparam Implements rvalue arguments to @code{ref} parameters. -@item shortenedmethods -Implements use of @code{=>} for methods and top-level functions in addition to -lambdas. +@item systemvariables +Disables access to variables marked @code{@@system} from @code{@@safe} code. @end table @item -frelease diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt index da65239..15ab725 100644 --- a/gcc/d/lang.opt +++ b/gcc/d/lang.opt @@ -396,9 +396,9 @@ fpreview=rvaluerefparam D RejectNegative Enable rvalue arguments to ref parameters. -fpreview=shortenedmethods +fpreview=systemvariables D RejectNegative -Allow use of '=>' for methods and top-level functions in addition to lambdas. +Disable access to variables marked `@system' from @safe code. frelease D diff --git a/gcc/testsuite/gdc.dg/simd18867.d b/gcc/testsuite/gdc.dg/simd18867.d new file mode 100644 index 0000000..295b0f8 --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd18867.d @@ -0,0 +1,11 @@ +// https://issues.dlang.org/show_bug.cgi?id=18867 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } +import core.simd; + +ulong2 test18867(ulong s) +{ + ulong2 v; + v[0] = s; + return v; +} diff --git a/gcc/testsuite/gdc.dg/simd19630.d b/gcc/testsuite/gdc.dg/simd19630.d index 0d45d28..c29acfe 100644 --- a/gcc/testsuite/gdc.dg/simd19630.d +++ b/gcc/testsuite/gdc.dg/simd19630.d @@ -3,19 +3,13 @@ // { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } import core.simd; -enum fail19630a = int4.init[1..2]; enum fail19630b = int4.init.array[1..2]; enum fail19630c = (cast(int[4])int4.init.array)[1..2]; enum fail19630d = (cast(int[4])int4.init)[1..2]; -enum fail19630e = int4(0)[1..2]; enum fail19630f = int4(0).array[1..2]; enum fail19630g = (cast(int[4])int4(0).array)[1..2]; enum fail19630h = (cast(int[4])int4(0))[1..2]; -enum int4 v19630a = int4.init; -enum slice19630a = v19630a[1..2]; -static assert(slice19630a == [0]); - enum int[4] v19630b = int4.init.array; enum slice19630b = v19630b[1..2]; static assert(slice19630b == [0]); @@ -28,10 +22,6 @@ enum int[4] v19630d = cast(int[4])int4.init; enum slice19630d = v19630d[1..2]; static assert(slice19630d == [0]); -enum int4 v19630e = int4(0); -enum slice19630e = v19630e[1..2]; -static assert(slice19630e == [0]); - enum int[4] v19630f = int4(0).array; enum slice19630f = v19630f[1..2]; static assert(slice19630f == [0]); diff --git a/gcc/testsuite/gdc.dg/simd19630b.d b/gcc/testsuite/gdc.dg/simd19630b.d new file mode 100644 index 0000000..4f09597 --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd19630b.d @@ -0,0 +1,17 @@ +// https://issues.dlang.org/show_bug.cgi?id=19630 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } +import core.simd; + +enum fail19630a = int4.init[1..2]; +// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 } +enum fail19630e = int4(0)[1..2]; +// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 } + +enum int4 v19630a = int4.init; +enum slice19630a = v19630a[1..2]; +// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 } + +enum int4 v19630e = int4(0); +enum slice19630e = v19630e[1..2]; +// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/gdc.dg/simd19630c.d b/gcc/testsuite/gdc.dg/simd19630c.d new file mode 100644 index 0000000..d17cf1a --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd19630c.d @@ -0,0 +1,15 @@ +// https://issues.dlang.org/show_bug.cgi?id=19630 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } +import core.simd; + +int4 testz19630() +{ + return [0,0,0,0]; +} + +void test19630() +{ + assert(testz19630()[] == [0,0,0,0]); + // { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/gdc.dg/simd19788.d b/gcc/testsuite/gdc.dg/simd19788.d new file mode 100644 index 0000000..74ab008 --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd19788.d @@ -0,0 +1,11 @@ +// https://issues.dlang.org/show_bug.cgi?id=19788 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } + +void test19788() +{ + enum v = __vector(float[4]).init; + const(float)[] a = v[]; + // { dg-error "'__vector\\\(float\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/gdc.dg/simd21469.d b/gcc/testsuite/gdc.dg/simd21469.d new file mode 100644 index 0000000..9596f5e --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd21469.d @@ -0,0 +1,9 @@ +// https://issues.dlang.org/show_bug.cgi?id=18867 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } +import core.simd; + +int4 test21469(short a) +{ + return cast(int4)(short8(a)); +} diff --git a/gcc/testsuite/gdc.dg/simd21672.d b/gcc/testsuite/gdc.dg/simd21672.d new file mode 100644 index 0000000..c5bd1df --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd21672.d @@ -0,0 +1,17 @@ +// https://bugzilla.gdcproject.org/show_bug.cgi?id=213 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } + +import core.simd; + +struct S213 +{ + int4 vec; +} + +void test213() +{ + S213 s, b; + + assert(s == b); +} diff --git a/gcc/testsuite/gdc.dg/simd23077.d b/gcc/testsuite/gdc.dg/simd23077.d new file mode 100644 index 0000000..150ec9f --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd23077.d @@ -0,0 +1,11 @@ +// https://issues.dlang.org/show_bug.cgi?id=23077 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } + +float test23077(float x) +{ + short i = *cast(short*)&x; + ++i; + return *cast(float*)&i; // this cast is not allowed in @safe code +} diff --git a/gcc/testsuite/gdc.dg/simd23084.d b/gcc/testsuite/gdc.dg/simd23084.d new file mode 100644 index 0000000..1f40e3c --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd23084.d @@ -0,0 +1,17 @@ +// https://issues.dlang.org/show_bug.cgi?id=23084 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +import core.simd; + +__vector(int[4]) test23084a(__vector(int[4]) a) +{ + __vector(short[8]) r = cast(short)(a.array[0]); + return cast(__vector(int[4]))r; +} + +__vector(int[4]) test23084b(__vector(int[4]) a) +{ + __vector(byte[16]) r = cast(byte)(a.array[0]); + return cast(__vector(int[4]))r; +} diff --git a/gcc/testsuite/gdc.dg/simd23085.d b/gcc/testsuite/gdc.dg/simd23085.d new file mode 100644 index 0000000..66444ad --- /dev/null +++ b/gcc/testsuite/gdc.dg/simd23085.d @@ -0,0 +1,11 @@ +// https://issues.dlang.org/show_bug.cgi?id=23085 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } + +float test23085(float x) +{ + byte i = *cast(byte*)&x; + ++i; + return *cast(float*)&i; // this cast is not allowed in @safe code +} diff --git a/gcc/testsuite/gdc.dg/simd_ctfe.d b/gcc/testsuite/gdc.dg/simd_ctfe.d deleted file mode 100644 index 507de17..0000000 --- a/gcc/testsuite/gdc.dg/simd_ctfe.d +++ /dev/null @@ -1,88 +0,0 @@ -// { dg-additional-options "-mavx" { target avx_runtime } } -// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } } -import core.simd; - -// https://issues.dlang.org/show_bug.cgi?id=19627 -enum int[4] fail19627 = cast(int[4])int4(0); - -// https://issues.dlang.org/show_bug.cgi?id=19628 -enum ice19628a = int4.init[0]; -enum ice19628b = int4.init.array[0]; -enum ice19628c = (cast(int[4])int4.init.array)[0]; -enum ice19628d = (cast(int[4])int4.init)[0]; - -// https://issues.dlang.org/show_bug.cgi?id=19629 -enum fail19629a = int4(0)[0]; -enum fail19629b = int4(0).array[0]; -enum fail19629c = (cast(int[4])int4(0).array)[0]; -enum fail19628d = (cast(int[4])int4(0))[0]; - -// https://issues.dlang.org/show_bug.cgi?id=19630 -enum fail19630a = int4.init[1..2]; -enum fail19630b = int4.init.array[1..2]; -enum fail19630c = (cast(int[4])int4.init.array)[1..2]; -enum fail19630d = int4(0)[1..2]; -enum fail19630e = int4(0).array[1..2]; -enum fail19630f = (cast(int[4])int4(0).array)[1..2]; -enum fail19630g = (cast(int[4])int4.init)[1..2]; -enum fail19630h = (cast(int[4])int4(0))[1..2]; - -// Same tests as above, but use access via enum. -enum int4 V1 = int4.init; -enum int[4] V2 = int4.init.array; -enum int[4] V3 = cast(int[4])int4.init; -enum int[4] V4 = cast(int[4])int4.init.array; -enum int4 V5 = int4(0); -enum int[4] V6 = int4(0).array; -enum int[4] V7 = cast(int[4])int4(0); -enum int[4] V8 = cast(int[4])int4(0).array; - -// CTFE index tests -enum I1 = V1[0]; static assert(I1 == 0); -enum I2 = V2[0]; static assert(I2 == 0); -enum I3 = V3[0]; static assert(I3 == 0); -enum I4 = V4[0]; static assert(I4 == 0); -enum I5 = V5[0]; static assert(I5 == 0); -enum I6 = V6[0]; static assert(I6 == 0); -enum I7 = V7[0]; static assert(I7 == 0); -enum I8 = V8[0]; static assert(I8 == 0); - -// CTFE slice tests -enum S1 = V1[1..2]; static assert(S1 == [0]); -enum S2 = V2[1..2]; static assert(S2 == [0]); -enum S3 = V3[1..2]; static assert(S3 == [0]); -enum S4 = V4[1..2]; static assert(S4 == [0]); -enum S5 = V5[1..2]; static assert(S5 == [0]); -enum S6 = V6[1..2]; static assert(S6 == [0]); -enum S7 = V7[1..2]; static assert(S7 == [0]); -enum S8 = V8[1..2]; static assert(S8 == [0]); - -// Same tests as above, but use access via immutable. -//immutable int4 v1 = int4.init; // Cannot cast to immutable at compile time -immutable int[4] v2 = int4.init.array; -immutable int[4] v3 = cast(int[4])int4.init; -immutable int[4] v4 = cast(int[4])int4.init.array; -//immutable int4 v5 = int4(0); // Cannot cast to immutable at compile time -immutable int[4] v6 = int4(0).array; -immutable int[4] v7 = cast(int[4])int4(0); -immutable int[4] v8 = cast(int[4])int4(0).array; - -// CTFE index tests -//immutable i1 = v1[0]; static assert(i1 == 0); -immutable i2 = v2[0]; static assert(i2 == 0); -immutable i3 = v3[0]; static assert(i3 == 0); -immutable i4 = v4[0]; static assert(i4 == 0); -//immutable i5 = v5[0]; static assert(i5 == 0); -immutable i6 = v6[0]; static assert(i6 == 0); -immutable i7 = v7[0]; static assert(i7 == 0); -immutable i8 = v8[0]; static assert(i8 == 0); - -// CTFE slice tests -//immutable s1 = v1[1..2]; static assert(s1 == [0]); -immutable s2 = v2[1..2]; static assert(s2 == [0]); -immutable s3 = v3[1..2]; static assert(s3 == [0]); -immutable s4 = v4[1..2]; static assert(s4 == [0]); -//immutable s5 = v5[1..2]; static assert(s5 == [0]); -immutable s6 = v6[1..2]; static assert(s6 == [0]); -immutable s7 = v7[1..2]; static assert(s7 == [0]); -immutable s8 = v8[1..2]; static assert(s8 == [0]); diff --git a/gcc/testsuite/gdc.dg/torture/simd19632.d b/gcc/testsuite/gdc.dg/torture/simd19632.d new file mode 100644 index 0000000..e74a3e8 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd19632.d @@ -0,0 +1,15 @@ +// https://issues.dlang.org/show_bug.cgi?id=19632 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +import core.simd; + +void main() +{ + int4 v = [1, 2, 3, 4]; + int sum = 0; + foreach (ref e; v) + sum += (e *= 2); + assert(v.array[] == [2, 4, 6, 8]); + assert(sum == 20); +} diff --git a/gcc/testsuite/gdc.dg/torture/simd20041.d b/gcc/testsuite/gdc.dg/torture/simd20041.d new file mode 100644 index 0000000..a74f58a --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd20041.d @@ -0,0 +1,22 @@ +// https://issues.dlang.org/show_bug.cgi?id=20041 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +import core.simd; + +immutable(float4) test20041() +{ + float4 raw = 2.0f; + raw.array[0] = 1; + return cast(immutable)raw; +} + +void main() +{ + static immutable float4 v = test20041(); + + assert(v.array[0] == 1); + assert(v.array[1] == 2); + assert(v.array[2] == 2); + assert(v.array[3] == 2); +} diff --git a/gcc/testsuite/gdc.dg/torture/simd21673.d b/gcc/testsuite/gdc.dg/torture/simd21673.d new file mode 100644 index 0000000..701e33a --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd21673.d @@ -0,0 +1,20 @@ +// https://issues.dlang.org/show_bug.cgi?id=21673 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +import core.simd; + +float4 _mm_move_ss(float4 a, float4 b) +{ + a.ptr[0] = b.array[0]; + return a; +} + +void main() +{ + float4 A = [1.0f, 2.0f, 3.0f, 4.0f]; + float4 B = [5.0f, 6.0f, 7.0f, 8.0f]; + float4 R = _mm_move_ss(A, B); + float[4] correct = [5.0f, 2.0f, 3.0f, 4.0f]; + assert(R.array == correct); +} diff --git a/gcc/testsuite/gdc.dg/torture/simd21676.d b/gcc/testsuite/gdc.dg/torture/simd21676.d new file mode 100644 index 0000000..1d7b911 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd21676.d @@ -0,0 +1,36 @@ +// https://issues.dlang.org/show_bug.cgi?id=23009 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +import core.simd; + +double2 loadUnaligned21676(const(double)* pvec) +{ + double2 result; + foreach(i; 0..2) + { + result[i] = pvec[i]; + } + return result; +} + +double2 _mm_setr_pd(double e1, double e0) +{ + double[2] result = [e1, e0]; + return loadUnaligned21676(result.ptr); +} + +double2 fun(double2 a, double2 b) +{ + a[0] = (a[0] < b[0]) ? a[0] : b[0]; + return a; +} + +void main() +{ + double2 A = _mm_setr_pd(1.0, 2.0); + double2 B = _mm_setr_pd(4.0, 1.0); + double2 C = fun(A, B); + assert(C.array[0] == 1.0); + assert(C.array[1] == 2.0); +} diff --git a/gcc/testsuite/gdc.dg/torture/simd22438.d b/gcc/testsuite/gdc.dg/torture/simd22438.d new file mode 100644 index 0000000..9199be6 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd22438.d @@ -0,0 +1,18 @@ +// https://issues.dlang.org/show_bug.cgi?id=22438 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do run } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } + +struct T22438 { int x; double d; } + +T22438 foo22438(int x, double d) { return T22438(x, d); } + +struct S22438 { T22438 t; string r; } + +void main() +{ + S22438 s = S22438(foo22438(10, 3.14), "str"); + assert(s.t.x == 10); + assert(s.t.d == 3.14); + assert(s.r == "str"); +} diff --git a/gcc/testsuite/gdc.dg/torture/simd23009.d b/gcc/testsuite/gdc.dg/torture/simd23009.d new file mode 100644 index 0000000..a45ec4d --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd23009.d @@ -0,0 +1,22 @@ +// https://issues.dlang.org/show_bug.cgi?id=23009 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +import core.simd; + +double2 _mm_loadl_pd(double2 a, const(double)* mem_addr) +{ + a[0] = *mem_addr; + return a; +} + +void main() +{ + double A = 7.0; + double2 B; + B[0] = 4.0; + B[1] = -5.0; + double2 R = _mm_loadl_pd(B, &A); + double[2] correct = [ 7.0, -5.0 ]; + assert(R.array == correct); +} diff --git a/gcc/testsuite/gdc.dg/torture/simd23077.d b/gcc/testsuite/gdc.dg/torture/simd23077.d new file mode 100644 index 0000000..150ec9f --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd23077.d @@ -0,0 +1,11 @@ +// https://issues.dlang.org/show_bug.cgi?id=23077 +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do compile } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } + +float test23077(float x) +{ + short i = *cast(short*)&x; + ++i; + return *cast(float*)&i; // this cast is not allowed in @safe code +} diff --git a/gcc/testsuite/gdc.dg/torture/simd8.d b/gcc/testsuite/gdc.dg/torture/simd8.d new file mode 100644 index 0000000..3847732 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd8.d @@ -0,0 +1,26 @@ +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +import gcc.simd; + +alias __m128 = __vector(float[4]); + +__m128 _mm_setr_ps (float e3, float e2, float e1, float e0) pure @trusted +{ + float[4] result = [e3, e2, e1, e0]; + return loadUnaligned!(__m128)(cast(__m128*)result.ptr); +} + +__m128 _mm_movehdup_ps (__m128 a) pure @trusted +{ + a.ptr[0] = a.array[1]; + a.ptr[2] = a.array[3]; + return a; +} + +void main() +{ + __m128 A = _mm_movehdup_ps(_mm_setr_ps(1, 2, 3, 4)); + float[4] correct = [2.0f, 2, 4, 4 ]; + assert(A.array == correct); +} diff --git a/gcc/testsuite/gdc.dg/torture/simd9.d b/gcc/testsuite/gdc.dg/torture/simd9.d new file mode 100644 index 0000000..0653531 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd9.d @@ -0,0 +1,46 @@ +// { dg-additional-options "-mavx" { target avx_runtime } } +// { dg-do run } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } + +__gshared int testsroa_x; + +template SROA(T1, T2) +{ + struct FPoint + { + T1 x; + T2 y; + } + + void sroa(FPoint p1, ref FPoint quad) + { + quad = FPoint(p1.x, p1.y); + } + + void testit() + { + FPoint p1 = FPoint(1, 2); + + FPoint quad; + sroa(p1, quad); + + if (quad != p1) + { + assert(0); + } + ++testsroa_x; + } +} + +void main() +{ + SROA!(int, int ).testit(); + SROA!(int, float).testit(); + SROA!(float, float).testit(); + SROA!(float, int ).testit(); + + SROA!(long, long ).testit(); + SROA!(long, double).testit(); + SROA!(double, double).testit(); + SROA!(double, long ).testit(); +} diff --git a/gcc/testsuite/gdc.dg/torture/simd_prefetch.d b/gcc/testsuite/gdc.dg/torture/simd_prefetch.d new file mode 100644 index 0000000..1778476 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/simd_prefetch.d @@ -0,0 +1,21 @@ +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +import gcc.simd; + +int testprefetch(byte a) +{ + prefetch!(false, 0)(&a); + prefetch!(false, 1)(&a); + prefetch!(false, 2)(&a); + prefetch!(false, 3)(&a); + prefetch!(true, 0)(&a); + prefetch!(true, 1)(&a); + prefetch!(true, 2)(&a); + prefetch!(true, 3)(&a); + return 3; +} + +void main() +{ + int i = testprefetch(1); + assert(i == 3); +} diff --git a/gcc/testsuite/gdc.test/compilable/cdcmp.d b/gcc/testsuite/gdc.test/compilable/cdcmp.d index 305f097b..16abde0 100644 --- a/gcc/testsuite/gdc.test/compilable/cdcmp.d +++ b/gcc/testsuite/gdc.test/compilable/cdcmp.d @@ -60,20 +60,6 @@ bool test_nez(long x) { return x != 0; } bool test_gez(long x) { return x >= 0; } bool test_gtz(long x) { return x > 0; } -bool test_ltz(float x) { return x < 0; } -bool test_lez(float x) { return x <= 0; } -bool test_eqz(float x) { return x == 0; } -bool test_nez(float x) { return x != 0; } -bool test_gez(float x) { return x >= 0; } -bool test_gtz(float x) { return x > 0; } - -bool test_ltz(double x) { return x < 0; } -bool test_lez(double x) { return x <= 0; } -bool test_eqz(double x) { return x == 0; } -bool test_nez(double x) { return x != 0; } -bool test_gez(double x) { return x >= 0; } -bool test_gtz(double x) { return x > 0; } - /* ----------------------------------- */ bool test_lt(ubyte x, ubyte y) { return x < y; } diff --git a/gcc/testsuite/gdc.test/compilable/extra-files/header2.d b/gcc/testsuite/gdc.test/compilable/extra-files/header2.d index 7dc4659..7c011d2 100644 --- a/gcc/testsuite/gdc.test/compilable/extra-files/header2.d +++ b/gcc/testsuite/gdc.test/compilable/extra-files/header2.d @@ -162,6 +162,18 @@ align(2) struct S12200_2 align(1): } +// https://issues.dlang.org/show_bug.cgi?id=14694 +inout(T)[] overlap(T)(inout(T)[] r1, inout(T)[] r2) @trusted pure nothrow +{ + alias U = inout(T); + static U* max(U* a, U* b) nothrow { return a > b ? a : b; } + static U* min(U* a, U* b) nothrow { return a < b ? a : b; } + + auto b = max(r1.ptr, r2.ptr); + auto e = min(r1.ptr + r1.length, r2.ptr + r2.length); + return b < e ? b[0 .. e - b] : null; +} + // https://issues.dlang.org/show_bug.cgi?id=16140 void gun()() { @@ -173,6 +185,13 @@ void gun()() else break; } +// https://issues.dlang.org/show_bug.cgi?id=14690 +pragma(inline, true) +int fun(int a, int b) +{ + return 3; +} + // https://issues.dlang.org/show_bug.cgi?id=16649 void leFoo()() { diff --git a/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i b/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i index c8ff976..0d001e8 100644 --- a/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i +++ b/gcc/testsuite/gdc.test/compilable/imports/cimports2a.i @@ -2,3 +2,10 @@ extern int xx; typedef struct Foo *FooRef; FooRef make_foo(void); + + +typedef struct Foo2 *FooRef2; +struct Foo2 { + int x; +}; +FooRef2 make_foo2(void); diff --git a/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i b/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i index 03b22b2..a0a9c2f 100644 --- a/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i +++ b/gcc/testsuite/gdc.test/compilable/imports/cimports2b.i @@ -2,3 +2,11 @@ extern int xx; typedef struct Foo *FooRef; void free_foo(FooRef foo); + +/****************************/ + +typedef struct Foo2 *FooRef2; +struct Foo2 { + int x; +}; +void free_foo2(FooRef2 foo); diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg22952/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg22952/package.d new file mode 100644 index 0000000..1a804d9 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/pkg22952/package.d @@ -0,0 +1 @@ +module lib; diff --git a/gcc/testsuite/gdc.test/compilable/noreturn3.d b/gcc/testsuite/gdc.test/compilable/noreturn3.d new file mode 100644 index 0000000..737125d --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/noreturn3.d @@ -0,0 +1,257 @@ +/* +REQUIRED_ARGS: -w -o- -d + +More complex examples from the DIP +https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1034.md +*/ + +alias noreturn = typeof(*null); +static assert (!is(noreturn == void)); + +void initialize() +{ + noreturn a; + noreturn b = noreturn.init; +} + +void foo(const noreturn); +void foo(const int); + +noreturn bar(); + +void overloads() +{ + noreturn n; + foo(n); + + foo(bar()); +} + +// /*****************************************************************************/ + +auto inferNoreturn(int i) +{ + if (i < 0) + return assert(false); + else if (i == 0) + return assert(false); + else + return assert(false); +} + +auto inferReturn(int i) +{ + if (i < 0) + return assert(false); + else if (i == 0) + return i; + else + return assert(false); +} + +// /*****************************************************************************/ +// // https://issues.dlang.org/show_bug.cgi?id=22004 + +alias fun22004 = _ => {}(); +alias gun22004 = _ => assert(0); +auto bun22004(bool b) +{ + if (b) + return gun22004(0); + else + return fun22004(0); +} + +static assert(is(typeof(bun22004(true)) == void)); + +// // Reversed order +auto bun22004_reversed(bool b) +{ + if (b) + return fun22004(0); + else + return gun22004(0); +} + +static assert(is(typeof(bun22004_reversed(true)) == void)); + +// /*****************************************************************************/ + +// // Also works fine with non-void types and ref inference + +int global; + +auto ref forwardOrExit(ref int num) +{ + if (num) + return num; + else + return assert(false); +} + +static assert( is(typeof(forwardOrExit(global)) == int)); + +// // Must not infer ref due to the noreturn rvalue +static assert(!is(typeof(&forwardOrExit(global)))); + +auto ref forwardOrExit2(ref int num) +{ + if (num) + return assert(false); + else + return num; +} + +static assert( is(typeof(forwardOrExit2(global)) == int)); + +// // Must not infer ref due to the noreturn rvalue +static assert(!is(typeof(&forwardOrExit2(global)))); + +/*****************************************************************************/ + +void inference() +{ + auto inf = cast(noreturn) 1; + static assert(is(typeof(inf) == noreturn)); + + noreturn n; + auto c = cast(const shared noreturn) n; + static assert(is(typeof(c) == const shared noreturn)); + static assert(is(typeof(n) == noreturn)); + + auto c2 = cast(immutable noreturn) n; + static assert(is(typeof(c) == const shared noreturn)); + static assert(is(typeof(c2) == immutable noreturn)); + static assert(is(typeof(n) == noreturn)); +} + + +/******************************************************************************/ +// https://issues.dlang.org/show_bug.cgi?id=21957 +// Calculate proper alignment and size for noreturn members + +enum longPad = long.alignof - int.sizeof; + +struct BasicStruct +{ + int firstInt; + noreturn noRet; + long lastLong; +} + +static assert(BasicStruct.sizeof == (int.sizeof + longPad + long.sizeof)); + +static assert(BasicStruct.firstInt.offsetof == 0); +static assert(BasicStruct.noRet.offsetof == 4); +static assert(BasicStruct.lastLong.offsetof == (4 + longPad)); + +struct AlignedStruct +{ + int firstInt; + align(16) noreturn noRet; + long lastLong; +} + +static assert(AlignedStruct.sizeof == 32); + +static assert(AlignedStruct.firstInt.offsetof == 0); +static assert(AlignedStruct.noRet.offsetof == 16); +static assert(AlignedStruct.lastLong.offsetof == 16); + +union BasicUnion +{ + int firstInt; + noreturn noRet; + long lastLong; +} + +static assert(BasicUnion.sizeof == 8); + +static assert(BasicUnion.firstInt.offsetof == 0); +static assert(BasicUnion.noRet.offsetof == 0); +static assert(BasicUnion.lastLong.offsetof == 0); + +union AlignedUnion +{ + int firstInt; + align(16) noreturn noRet; + long lastLong; +} + +static assert(AlignedUnion.sizeof == 16); + +static assert(AlignedUnion.firstInt.offsetof == 0); +static assert(AlignedUnion.noRet.offsetof == 0); +static assert(AlignedUnion.lastLong.offsetof == 0); + +class BasicClass +{ + int firstInt; + noreturn noRet; + long lastLong; +} + +enum objectMemberSize = __traits(classInstanceSize, Object); + +static assert(__traits(classInstanceSize, BasicClass) == objectMemberSize + (int.sizeof + longPad + long.sizeof)); + +static assert(BasicClass.firstInt.offsetof == objectMemberSize + 0); +static assert(BasicClass.noRet.offsetof == objectMemberSize + 4); +static assert(BasicClass.lastLong.offsetof == objectMemberSize + (4 + longPad)); + +class AlignedClass +{ + int firstInt; + align(16) noreturn noRet; + long lastLong; +} + +enum offset = (objectMemberSize + 4 + 16) & ~15; + +static assert(__traits(classInstanceSize, AlignedClass) == offset + 8); + +static assert(AlignedClass.firstInt.offsetof == objectMemberSize + 0); +static assert(AlignedClass.noRet.offsetof == offset); +static assert(AlignedClass.lastLong.offsetof == offset); + +struct EmptyStruct +{ + noreturn noRet; +} + +static assert(EmptyStruct.sizeof == 1); +static assert(EmptyStruct.noRet.offsetof == 0); + +struct EmptyStruct2 +{ + noreturn[4] noRet; +} + +static assert(EmptyStruct2.sizeof == 1); +static assert(EmptyStruct2.noRet.offsetof == 0); + +// https://issues.dlang.org/show_bug.cgi?id=22858 +// Shouldn't mess with the alignment of other zero-sized types. + +struct S22858 +{ + int a; + void*[0] arr; + char c; + noreturn[0] arr2; + char c2; +} + +static assert (S22858.arr.offsetof % size_t.sizeof == 0); +static assert (S22858.arr2.offsetof == S22858.c.offsetof + 1); +static assert (S22858.arr2.offsetof == S22858.c2.offsetof); + +// https://issues.dlang.org/show_bug.cgi?id=23331 + +auto fun() { return double(new noreturn[](0)[0]); } +auto gun() { return double(assert(0)); } +auto hun() { return int(assert(0)); } + +// https://issues.dlang.org/show_bug.cgi?id=23379 + +void casting_noreturn() { auto b = cast(double)(assert(0)); } diff --git a/gcc/testsuite/gdc.test/compilable/scope_tuple_expansion.d b/gcc/testsuite/gdc.test/compilable/scope_tuple_expansion.d new file mode 100644 index 0000000..cac180c --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/scope_tuple_expansion.d @@ -0,0 +1,21 @@ +// REQUIRED_ARGS: -preview=dip1000 + +// Reduced from `std.systime`. +// Tuple expansion can trip up scope checking with errors like: +// Error: scope variable `__tup4` assigned to `found` with longer lifetime + +struct Tuple(T...) +{ + T t; + alias t this; +} + +Tuple!(int*, int) find(return scope int* x) @safe +{ + assert(0); +} + +void fromISOExtString(scope int* str) @safe +{ + int* found = str.find()[0]; +} diff --git a/gcc/testsuite/gdc.test/compilable/shortened_methods.d b/gcc/testsuite/gdc.test/compilable/shortened_methods.d index 5a7ac87..71350af 100644 --- a/gcc/testsuite/gdc.test/compilable/shortened_methods.d +++ b/gcc/testsuite/gdc.test/compilable/shortened_methods.d @@ -1,4 +1,4 @@ -// REQUIRED_ARGS: -preview=shortenedMethods +// N.B. Shortened methods are no longer under a preview flag class A { int _x = 34; // short syntax works in all contexts diff --git a/gcc/testsuite/gdc.test/compilable/test11980.d b/gcc/testsuite/gdc.test/compilable/test11980.d index 27974e4..29ec7a1 100644 --- a/gcc/testsuite/gdc.test/compilable/test11980.d +++ b/gcc/testsuite/gdc.test/compilable/test11980.d @@ -1,2 +1,5 @@ -void start() {} +void start() +{ + pragma(startaddress, start); +} pragma(startaddress, start); diff --git a/gcc/testsuite/gdc.test/compilable/test22674.d b/gcc/testsuite/gdc.test/compilable/test22674.d index cc6e3bb..00750b0 100644 --- a/gcc/testsuite/gdc.test/compilable/test22674.d +++ b/gcc/testsuite/gdc.test/compilable/test22674.d @@ -8,3 +8,10 @@ void do_foo(){ FooRef f = make_foo(); // use_foo.d(5) free_foo(f); // use_foo.d(6) } + +// https://issues.dlang.org/show_bug.cgi?id=23357 + +void do_foo2(){ + FooRef2 f = make_foo2(); + free_foo2(f); +} diff --git a/gcc/testsuite/gdc.test/compilable/test22784.d b/gcc/testsuite/gdc.test/compilable/test22784.d new file mode 100644 index 0000000..1709be4 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test22784.d @@ -0,0 +1,10 @@ +// Issue 22784 - pragma(printf) applies to nested functions +// https://issues.dlang.org/show_bug.cgi?id=22784 + +import core.stdc.stdarg; +extern(C) +pragma(printf) +void fn(const(char)* fmt, ...) +{ + void inner(){} +} diff --git a/gcc/testsuite/gdc.test/compilable/test22952.d b/gcc/testsuite/gdc.test/compilable/test22952.d new file mode 100644 index 0000000..d0524b1 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test22952.d @@ -0,0 +1,10 @@ +/* +REQUIRED_ARGS: -Icompilable/imports -mv=lib=pkg22952 +EXTRA_FILES: imports/pkg22952/package.d +*/ + +// Issue 22952 - Compiler fails to find package.d modules via -mv map +// https://issues.dlang.org/show_bug.cgi?id=22952 + +module test22952; +import lib; diff --git a/gcc/testsuite/gdc.test/compilable/test23380.d b/gcc/testsuite/gdc.test/compilable/test23380.d new file mode 100644 index 0000000..bf82604 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23380.d @@ -0,0 +1,9 @@ +// REQUIRED_ARGS: -preview=dip1000 + +// https://issues.dlang.org/show_bug.cgi?id=23380 +// Issue 23380 - [dip1000] class parameter should not be treated as ref qua lifetime + +@safe void test(scope Object o0, scope Object o1) +{ + o1 = o0; +} diff --git a/gcc/testsuite/gdc.test/compilable/test23386.d b/gcc/testsuite/gdc.test/compilable/test23386.d new file mode 100644 index 0000000..dc1d754 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23386.d @@ -0,0 +1,12 @@ +// https://issues.dlang.org/show_bug.cgi?id=23386 +// Segfault on enum member UDA inside template + +template E() +{ + enum E : byte + { + @(1) none, + } +} + +alias T = E!(); diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag23384.d b/gcc/testsuite/gdc.test/fail_compilation/diag23384.d new file mode 100644 index 0000000..1fa4da5 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/diag23384.d @@ -0,0 +1,29 @@ +// https://issues.dlang.org/show_bug.cgi?id=23384 + +/* +TEST_OUTPUT: +--- +fail_compilation/diag23384.d(28): Error: function `diag23384.Derived.fun(B b)` is not callable using argument types `(A)` +fail_compilation/diag23384.d(28): function `diag23384.Derived.fun` hides base class function `diag23384.Base.fun` +fail_compilation/diag23384.d(28): add `alias fun = diag23384.Base.fun` to `diag23384.Derived`'s body to merge the overload sets +--- +*/ + +struct A {} +struct B {} + +class Base +{ + void fun(A a) {} +} + +class Derived : Base +{ + void fun(B b) {} +} + +void main() +{ + Derived d; + d.fun(A()); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10905.d b/gcc/testsuite/gdc.test/fail_compilation/fail10905.d deleted file mode 100644 index 52b5285..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/fail10905.d +++ /dev/null @@ -1,22 +0,0 @@ -/* -REQUIRED_ARGS: -m64 -TEST_OUTPUT: ---- -fail_compilation/fail10905.d(20): Error: incompatible types for `(this.x) == (cast(const(__vector(long[2])))cast(__vector(long[2]))1L)`: both operands are of type `const(__vector(long[2]))` ---- -*/ - -struct Foo -{ - enum __vector(long[2]) y = 1; -} - -struct Bar -{ - __vector(long[2]) x; - - bool spam() const - { - return x == Foo.y; - } -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d b/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d index ccdbb57..e23ed04 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d @@ -2,7 +2,7 @@ REQUIRED_ARGS: -m64 TEST_OUTPUT: --- -fail_compilation/fail19898a.d(10): Error: incompatible types for `(__key2) < (__limit3)`: both operands are of type `__vector(int[4])` +fail_compilation/fail19898a.d(10): Error: expression `__key2 < __limit3` of type `__vector(int[4])` does not have a boolean value --- */ void f (__vector(int[4]) n) diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d b/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d index 254c2ca..5101da5 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d @@ -3,7 +3,7 @@ REQUIRED_ARGS: -m64 TEST_OUTPUT: --- fail_compilation/fail19898b.d(17): Error: cannot implicitly convert expression `m` of type `S` to `__vector(int[4])` -fail_compilation/fail19898b.d(17): Error: incompatible types for `(__key2) != (__limit3)`: both operands are of type `__vector(int[4])` +fail_compilation/fail19898b.d(17): Error: expression `__key2 != __limit3` of type `__vector(int[4])` does not have a boolean value fail_compilation/fail19898b.d(17): Error: cannot cast expression `__key2` of type `__vector(int[4])` to `S` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22366.d b/gcc/testsuite/gdc.test/fail_compilation/fail22366.d index 3a2469f..6960d5e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail22366.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail22366.d @@ -3,7 +3,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail22366.d(13): Error: scope variable `__aaval2` assigned to non-scope `aa[0]` +fail_compilation/fail22366.d(13): Error: scope variable `x` may not be copied into allocated memory --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23406.d b/gcc/testsuite/gdc.test/fail_compilation/fail23406.d new file mode 100644 index 0000000..8ac3f14 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail23406.d @@ -0,0 +1,40 @@ +// https://issues.dlang.org/show_bug.cgi?id=23406 + +/* +TEST_OUTPUT: +--- +fail_compilation/fail23406.d(39): Error: cannot implicitly convert expression `0` of type `int` to `alphakey` +--- +*/ + +struct flagenum +{ + int i = 1; + alias i this; + + auto opBinary(string s)(int j) + { + assert(j == 1); + return typeof(this)(i*2); + } + + auto opEquals(int a) + { + return false; + } +} + +enum alphakey +{ + a = flagenum(), + b,c,d,e,f,g,h,i, + k,l,m,n,o,p,q,r, + s,t,u,v,w,x,y,z +} + +alphakey alpha; + +void main() +{ + alpha = 0; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue21378.d b/gcc/testsuite/gdc.test/fail_compilation/issue21378.d index 22c60a3..172110a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/issue21378.d +++ b/gcc/testsuite/gdc.test/fail_compilation/issue21378.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/issue21378.d(13): Error: function `issue21378.fn` circular dependency. Functions cannot be interpreted while being compiled fail_compilation/issue21378.d(12): called from here: `fn()` -fail_compilation/issue21378.d(12): Error: pragma `inline` pragma(`inline`, `true` or `false`) expected, not `fn()` +fail_compilation/issue21378.d(12): Error: pragma(`inline`, `true` or `false`) expected, not `fn()` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer1.d b/gcc/testsuite/gdc.test/fail_compilation/lexer1.d index e6cabf2..0ad3f01 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/lexer1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/lexer1.d @@ -23,9 +23,9 @@ fail_compilation/lexer1.d(49): Error: unterminated named entity &*; fail_compilation/lexer1.d(50): Error: unterminated named entity &s1"; fail_compilation/lexer1.d(51): Error: unterminated named entity &2; fail_compilation/lexer1.d(52): Error: escape octal sequence \400 is larger than \377 +fail_compilation/lexer1.d(53): Error: html entity requires 2 code units, use a string instead of a character --- */ - // https://dlang.dawg.eu/coverage/src/lexer.c.gcov.html x"01 02 03"w; 0x80000001; @@ -50,3 +50,4 @@ static s5 = "\&*"; static s6 = "\&s1"; static s7 = "\&2;"; static s7 = "\400;"; +dchar s8 = '\∾̳'; diff --git a/gcc/testsuite/gdc.test/fail_compilation/pragmainline.d b/gcc/testsuite/gdc.test/fail_compilation/pragmainline.d index 5d43277..23f3bfe 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/pragmainline.d +++ b/gcc/testsuite/gdc.test/fail_compilation/pragmainline.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/pragmainline.d(8): Error: pragma `inline` one boolean expression expected for `pragma(inline)`, not 3 +fail_compilation/pragmainline.d(8): Error: one boolean expression expected for `pragma(inline)`, not 3 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/pragmas.d b/gcc/testsuite/gdc.test/fail_compilation/pragmas.d index cd56ff4..5a4b5d9 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/pragmas.d +++ b/gcc/testsuite/gdc.test/fail_compilation/pragmas.d @@ -3,8 +3,8 @@ /* TEST_OUTPUT: --- -fail_compilation/pragmas.d(103): Error: boolean expression expected for `pragma(inline)` -fail_compilation/pragmas.d(108): Error: boolean expression expected for `pragma(inline)` +fail_compilation/pragmas.d(103): Error: one boolean expression expected for `pragma(inline)`, not 2 +fail_compilation/pragmas.d(108): Error: one boolean expression expected for `pragma(inline)`, not 2 fail_compilation/pragmas.d(118): Error: unrecognized `pragma(unrecognized)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/previewin.d b/gcc/testsuite/gdc.test/fail_compilation/previewin.d index ce0cf92..ca54093 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/previewin.d +++ b/gcc/testsuite/gdc.test/fail_compilation/previewin.d @@ -8,10 +8,10 @@ fail_compilation/previewin.d(5): Error: function `previewin.takeFunction(void fu fail_compilation/previewin.d(5): cannot pass argument `__lambda2` of type `void function(const(real) x) pure nothrow @nogc @safe` to parameter `void function(in real) f` fail_compilation/previewin.d(6): Error: function `previewin.takeFunction(void function(in real) f)` is not callable using argument types `(void function(ref const(real) x) pure nothrow @nogc @safe)` fail_compilation/previewin.d(6): cannot pass argument `__lambda3` of type `void function(ref const(real) x) pure nothrow @nogc @safe` to parameter `void function(in real) f` -fail_compilation/previewin.d(15): Error: scope variable `arg` assigned to non-scope `myGlobal` -fail_compilation/previewin.d(16): Error: scope variable `arg` assigned to non-scope `myGlobal` +fail_compilation/previewin.d(15): Error: scope variable `arg` assigned to global variable `myGlobal` +fail_compilation/previewin.d(16): Error: scope variable `arg` assigned to global variable `myGlobal` fail_compilation/previewin.d(17): Error: scope parameter `arg` may not be returned -fail_compilation/previewin.d(18): Error: scope variable `arg` assigned to `escape` with longer lifetime +fail_compilation/previewin.d(18): Error: scope variable `arg` assigned to `ref` variable `escape` with longer lifetime fail_compilation/previewin.d(22): Error: returning `arg` escapes a reference to parameter `arg` fail_compilation/previewin.d(22): perhaps annotate the parameter with `return` --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d b/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d index 6e7e909..29f96ec 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d +++ b/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d @@ -117,6 +117,7 @@ fail_compilation/reserved_version.d(218): Error: version identifier `D_PreCondit fail_compilation/reserved_version.d(219): Error: version identifier `D_PostConditions` is reserved and cannot be set fail_compilation/reserved_version.d(220): Error: version identifier `D_ProfileGC` is reserved and cannot be set fail_compilation/reserved_version.d(221): Error: version identifier `D_Invariants` is reserved and cannot be set +fail_compilation/reserved_version.d(222): Error: version identifier `D_Optimized` is reserved and cannot be set --- */ @@ -240,6 +241,7 @@ version = D_PreConditions; version = D_PostConditions; version = D_ProfileGC; version = D_Invariants; +version = D_Optimized; // This should work though debug = DigitalMars; @@ -351,3 +353,4 @@ debug = AVR; debug = D_PreConditions; debug = D_PostConditions; debug = D_ProfileGC; +debug = D_Optimized; diff --git a/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d b/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d index cd85b41..f5f6b1c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d +++ b/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d @@ -107,6 +107,7 @@ // REQUIRED_ARGS: -version=D_PostConditions // REQUIRED_ARGS: -version=D_ProfileGC // REQUIRED_ARGS: -version=D_Invariants +// REQUIRED_ARGS: -version=D_Optimized // REQUIRED_ARGS: -debug=DigitalMars // REQUIRED_ARGS: -debug=GNU // REQUIRED_ARGS: -debug=LDC @@ -211,6 +212,7 @@ // REQUIRED_ARGS: -debug=D_PostConditions // REQUIRED_ARGS: -debug=D_ProfileGC // REQUIRED_ARGS: -debug=D_Invariants +// REQUIRED_ARGS: -debug=D_Optimized /* TEST_OUTPUT: --- @@ -321,5 +323,6 @@ Error: version identifier `D_PreConditions` is reserved and cannot be set Error: version identifier `D_PostConditions` is reserved and cannot be set Error: version identifier `D_ProfileGC` is reserved and cannot be set Error: version identifier `D_Invariants` is reserved and cannot be set +Error: version identifier `D_Optimized` is reserved and cannot be set --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope.d b/gcc/testsuite/gdc.test/fail_compilation/retscope.d index 2a69fe0..ece6a8c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope.d @@ -4,9 +4,9 @@ TEST_OUTPUT: --- fail_compilation/retscope.d(22): Error: scope parameter `p` may not be returned fail_compilation/retscope.d(32): Error: returning `b ? nested1(& i) : nested2(& j)` escapes a reference to local variable `j` -fail_compilation/retscope.d(45): Error: scope variable `p` assigned to non-scope `q` +fail_compilation/retscope.d(45): Error: scope variable `p` assigned to global variable `q` fail_compilation/retscope.d(47): Error: address of variable `i` assigned to `q` with longer lifetime -fail_compilation/retscope.d(48): Error: scope variable `a` assigned to non-scope `b` +fail_compilation/retscope.d(48): Error: scope variable `a` assigned to global variable `b` fail_compilation/retscope.d(49): Error: address of struct temporary returned by `(*fp2)()` assigned to longer lived variable `q` --- */ @@ -662,7 +662,7 @@ int test21() /********************************************* TEST_OUTPUT: --- -fail_compilation/retscope.d(1907): Error: scope variable `x` assigned to `this` with longer lifetime +fail_compilation/retscope.d(1907): Error: scope variable `x` assigned to `ref` variable `this` with longer lifetime fail_compilation/retscope.d(1913): Error: scope variable `x` may not be returned --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d index 9f1e13d..1cb76d6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d @@ -2,7 +2,7 @@ REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/retscope2.d(102): Error: scope variable `s` assigned to `p` with longer lifetime +fail_compilation/retscope2.d(102): Error: scope variable `s` assigned to `ref` variable `p` with longer lifetime fail_compilation/retscope2.d(107): Error: address of variable `s` assigned to `p` with longer lifetime --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d index 95d5dbe..9736d37 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d @@ -25,7 +25,7 @@ int* test() @safe --- fail_compilation/retscope6.d(7034): Error: address of variable `i` assigned to `s` with longer lifetime fail_compilation/retscope6.d(7035): Error: address of variable `i` assigned to `s` with longer lifetime -fail_compilation/retscope6.d(7025): Error: scope variable `_param_2` assigned to `t` with longer lifetime +fail_compilation/retscope6.d(7025): Error: scope variable `_param_2` assigned to `ref` variable `t` with longer lifetime fail_compilation/retscope6.d(7037): Error: template instance `retscope6.S.emplace4!(int*)` error instantiating fail_compilation/retscope6.d(7037): Error: address of variable `i` assigned to `s` with longer lifetime --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/systemvariables.d b/gcc/testsuite/gdc.test/fail_compilation/systemvariables.d new file mode 100644 index 0000000..0079719 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/systemvariables.d @@ -0,0 +1,48 @@ +/* +REQUIRED_ARGS: -preview=systemVariables +TEST_OUTPUT: +--- +fail_compilation/systemvariables.d(30): Error: cannot access `@system` variable `gInt` in @safe code +fail_compilation/systemvariables.d(31): Error: cannot access `@system` variable `gInt` in @safe code +fail_compilation/systemvariables.d(32): Error: cannot access `@system` variable `gArr` in @safe code +fail_compilation/systemvariables.d(33): Error: cannot access `@system` variable `gArr` in @safe code +fail_compilation/systemvariables.d(34): Error: cannot access `@system` variable `gInt` in @safe code +fail_compilation/systemvariables.d(37): Error: cannot access `@system` variable `lSys` in @safe code +fail_compilation/systemvariables.d(38): Error: cannot access `@system` variable `lSys` in @safe code +fail_compilation/systemvariables.d(39): Error: cannot access `@system` variable `lSys` in @safe code +fail_compilation/systemvariables.d(41): Error: cannot access `@system` variable `eInt` in @safe code +--- +*/ + +// http://dlang.org/dips/1035 + + +@system int gInt; +@system enum int eInt = 3; +@system { int[] gArr; } +alias aliasToSys = gInt; + +void increment(ref int x) @safe { x++; } +void incrementP(int* x) @safe { (*x)++; } + +void basic() @safe +{ + gInt = 0; // error + gInt++; // error + gArr ~= 30; // error + const c = gArr[0]; // error + aliasToSys++; // error + + @system int lSys = 0; + lSys = 0; // error + increment(lSys); // error + incrementP(&lSys); // error + + int a = eInt; // error + int b = typeof(eInt).max; // allowed + + void f() @trusted + { + lSys = 0; // allowed + } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/systemvariables_deprecation.d b/gcc/testsuite/gdc.test/fail_compilation/systemvariables_deprecation.d new file mode 100644 index 0000000..75dbe2d --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/systemvariables_deprecation.d @@ -0,0 +1,28 @@ +/* +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/systemvariables_deprecation.d(16): Deprecation: `@safe` function `main` calling `middle` +fail_compilation/systemvariables_deprecation.d(21): which calls `systemvariables_deprecation.inferred` +fail_compilation/systemvariables_deprecation.d(27): which would be `@system` because of: +fail_compilation/systemvariables_deprecation.d(27): cannot access `@system` variable `x0` in @safe code +--- +*/ + +// test deprecation messages before -preview=systemVariables becomes default + +void main() @safe +{ + middle(); // nested deprecation +} + +auto middle() +{ + return inferred(); // no deprecation, inferredC is not explicit `@safe` +} + +auto inferred() +{ + @system int* x0; + x0 = null; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/systemvariables_struct.d b/gcc/testsuite/gdc.test/fail_compilation/systemvariables_struct.d new file mode 100644 index 0000000..7d8bfab --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/systemvariables_struct.d @@ -0,0 +1,60 @@ +/* +REQUIRED_ARGS: -preview=systemVariables +TEST_OUTPUT: +--- +fail_compilation/systemvariables_struct.d(31): Error: cannot access `@system` field `S.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(32): Error: cannot access `@system` field `S.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(33): Error: cannot access `@system` field `S.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(36): Error: cannot access `@system` field `S.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(37): Error: cannot access `@system` field `S.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(38): Error: cannot access `@system` field `S.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(54): Error: cannot access `@system` field `S2.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(55): Error: cannot access `@system` field `S2.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(56): Error: cannot access `@system` field `S.syst` in `@safe` code +fail_compilation/systemvariables_struct.d(57): Error: cannot access `@system` field `S.syst` in `@safe` code +--- +*/ + +// http://dlang.org/dips/1035 + +struct S +{ + @system S* syst; + @safe S* safe; +} + +void aggregate() @safe +{ + S s0; + + // write access + s0.syst = null; + __traits(getMember, s0, "syst") = null; + s0.tupleof[0] = null; + + // read access + auto a0 = s0.syst; + auto a1 = __traits(getMember, s0, "syst"); + auto a2 = s0.tupleof[0]; + + S s1; + s1 = s0; // allowed +} + +struct S2 +{ + @system S syst; + @safe S safe; +} + +@safe S2 gs2; + +void aggregate2() @safe +{ + gs2.syst.syst = null; + gs2.syst.safe = null; + gs2.safe.syst = null; + gs2.safe.syst.safe = null; + + gs2.safe.safe = null; // allowed +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/systemvariables_void_init.d b/gcc/testsuite/gdc.test/fail_compilation/systemvariables_void_init.d new file mode 100644 index 0000000..6f44093 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/systemvariables_void_init.d @@ -0,0 +1,32 @@ +/** +REQUIRED_ARGS: -preview=systemVariables +TEST_OUTPUT: +--- +fail_compilation/systemvariables_void_init.d(29): Error: `void` initializers for `@system` variables not allowed in safe functions +fail_compilation/systemvariables_void_init.d(30): Error: `void` initializers for `@system` variables not allowed in safe functions +fail_compilation/systemvariables_void_init.d(31): Error: `void` initializers for `@system` variables not allowed in safe functions +--- +*/ + +struct S +{ + int x; + @system int y; +} + +struct C +{ + S[2] x; +} + +enum E : C +{ + x = C.init, +} + +void main() @safe +{ + S s = void; + C c = void; + E e = void; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/templatethis.d b/gcc/testsuite/gdc.test/fail_compilation/templatethis.d new file mode 100644 index 0000000..73036d9 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/templatethis.d @@ -0,0 +1,37 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/templatethis.d(13): Error: cannot use `this` outside an aggregate type +fail_compilation/templatethis.d(17): Error: cannot use `this` outside an aggregate type +fail_compilation/templatethis.d(21): Error: cannot use `this` outside an aggregate type +fail_compilation/templatethis.d(23): Error: cannot use `this` outside an aggregate type +fail_compilation/templatethis.d(29): Error: cannot use `this` outside an aggregate type +fail_compilation/templatethis.d(32): Error: mixin `templatethis.t2!()` error instantiating +--- +*/ + +template t(this T) +{ +} + +struct S(this T) +{ +} + +enum e(this T) = 1; + +void f(this T)() +{ +} + +mixin template t2() +{ + int i(this T) = 1; +} + +mixin t2; + +class C +{ + mixin t2; // OK +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test14496.d b/gcc/testsuite/gdc.test/fail_compilation/test14496.d index 9f628ca..94d5d0f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test14496.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test14496.d @@ -6,10 +6,10 @@ fail_compilation/test14496.d(24): Error: `void` initializers for pointers not al fail_compilation/test14496.d(28): Error: `void` initializers for pointers not allowed in safe functions fail_compilation/test14496.d(48): Error: `void` initializers for pointers not allowed in safe functions fail_compilation/test14496.d(49): Error: `void` initializers for pointers not allowed in safe functions +fail_compilation/test14496.d(50): Error: `void` initializers for pointers not allowed in safe functions --- */ // https://issues.dlang.org/show_bug.cgi?id=14496 - @safe void foo() { struct Foo { @@ -47,4 +47,5 @@ struct Baz { @safe void sinister() { Bar bar; Baz baz; + Bar[2] bars; // https://issues.dlang.org/show_bug.cgi?id=23412 } diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17764.d b/gcc/testsuite/gdc.test/fail_compilation/test17764.d index 6ee988a..befcdb1 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test17764.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test17764.d @@ -1,7 +1,7 @@ /* REQUIRED_ARGS: -preview=dip1000 * TEST_OUTPUT: --- -fail_compilation/test17764.d(109): Error: scope variable `c` assigned to non-scope `global` +fail_compilation/test17764.d(109): Error: scope variable `c` assigned to global variable `global` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test19097.d b/gcc/testsuite/gdc.test/fail_compilation/test19097.d index 9c025a8..980931e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test19097.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test19097.d @@ -3,7 +3,7 @@ --- fail_compilation/test19097.d(44): Error: scope variable `s` may not be returned fail_compilation/test19097.d(48): Error: scope variable `s1` may not be returned -fail_compilation/test19097.d(77): Error: scope variable `z` assigned to `refPtr` with longer lifetime +fail_compilation/test19097.d(77): Error: scope variable `z` assigned to `ref` variable `refPtr` with longer lifetime fail_compilation/test19097.d(108): Error: scope variable `s4` may not be returned fail_compilation/test19097.d(126): Error: scope variable `s5c` may not be returned fail_compilation/test19097.d(130): Error: scope variable `s5m` may not be returned diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22145.d b/gcc/testsuite/gdc.test/fail_compilation/test22145.d index 394116d..55e7c63 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test22145.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test22145.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: REQUIRED_ARGS: -preview=dip1000 --- -fail_compilation/test22145.d(115): Error: scope variable `x` assigned to non-scope `global` +fail_compilation/test22145.d(115): Error: scope variable `x` assigned to global variable `global` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22680.d b/gcc/testsuite/gdc.test/fail_compilation/test22680.d index caf0f4a..85e653e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test22680.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test22680.d @@ -1,7 +1,7 @@ /* REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/test22680.d(104): Error: scope variable `this` assigned to non-scope `c` +fail_compilation/test22680.d(104): Error: scope variable `this` assigned to global variable `c` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/warn14905.d b/gcc/testsuite/gdc.test/fail_compilation/warn14905.d new file mode 100644 index 0000000..55520ba --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/warn14905.d @@ -0,0 +1,23 @@ +// REQUIRED_ARGS: -o- -w + +/* +TEST_OUTPUT: +--- +fail_compilation/warn14905.d(16): Warning: statement is not reachable in template instance warn14905.fun!"a".fun +fail_compilation/warn14905.d(16): Warning: statement is not reachable in template instance warn14905.fun!"b".fun +Error: warnings are treated as errors + Use -wi if you wish to treat warnings only as informational. +--- +*/ + +bool fun(string s)() +{ + return true; + return false; +} + +void main() +{ + cast(void)fun!"a"; + cast(void)fun!"b"; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/xmmslice.d b/gcc/testsuite/gdc.test/fail_compilation/xmmslice.d new file mode 100644 index 0000000..6cf0e23 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/xmmslice.d @@ -0,0 +1,22 @@ + +/* REQUIRED_ARGS: -mcpu=avx +DISABLED: win32 freebsd32 linux32 osx32 +TEST_OUTPUT: +--- +fail_compilation/xmmslice.d(110): Error: `__vector(int[4])` cannot be sliced with `[]` +--- + */ + +#line 100 + +import core.simd; + +int4 testz4() +{ + return [0,0,0,0]; +} + +void test() +{ + assert(testz4()[] == [0,0,0,0]); +} diff --git a/gcc/testsuite/gdc.test/runnable/cdcmp.d b/gcc/testsuite/gdc.test/runnable/cdcmp.d new file mode 100644 index 0000000..1c998dc --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/cdcmp.d @@ -0,0 +1,146 @@ + + +bool test_ltz(float x) { return x < 0; } +bool test_lez(float x) { return x <= 0; } +bool test_eqz(float x) { return x == 0; } +bool test_nez(float x) { return x != 0; } +bool test_gez(float x) { return x >= 0; } +bool test_gtz(float x) { return x > 0; } + +void test1f() +{ + assert(!test_ltz(0.0f)); + assert(!test_ltz(1.0f)); + assert( test_ltz(-1.0f)); + + assert( test_lez(0.0f)); + assert(!test_lez(1.0f)); + assert( test_lez(-1.0f)); + + assert( test_eqz(0.0f)); + assert(!test_eqz(1.0f)); + assert(!test_eqz(-1.0f)); + + assert(!test_nez(0.0f)); + assert( test_nez(1.0f)); + assert( test_nez(-1.0f)); + + assert( test_gez(0.0f)); + assert( test_gez(1.0f)); + assert(!test_gez(-1.0f)); + + assert(!test_gtz(0.0f)); + assert( test_gtz(1.0f)); + assert(!test_gtz(-1.0f)); +} + +bool test_ltz(double x) { return x < 0; } +bool test_lez(double x) { return x <= 0; } +bool test_eqz(double x) { return x == 0; } +bool test_nez(double x) { return x != 0; } +bool test_gez(double x) { return x >= 0; } +bool test_gtz(double x) { return x > 0; } + +void test1d() +{ + assert(!test_ltz(0.0)); + assert(!test_ltz(1.0)); + assert( test_ltz(-1.0)); + + assert( test_lez(0.0)); + assert(!test_lez(1.0)); + assert( test_lez(-1.0)); + + assert( test_eqz(0.0)); + assert(!test_eqz(1.0)); + assert(!test_eqz(-1.0)); + + assert(!test_nez(0.0)); + assert( test_nez(1.0)); + assert( test_nez(-1.0)); + + assert( test_gez(0.0)); + assert( test_gez(1.0)); + assert(!test_gez(-1.0)); + + assert(!test_gtz(0.0)); + assert( test_gtz(1.0)); + assert(!test_gtz(-1.0)); +} + +bool test_lt(float x, float y) { return x < y; } +bool test_le(float x, float y) { return x <= y; } +bool test_eq(float x, float y) { return x == y; } +bool test_ne(float x, float y) { return x != y; } +bool test_ge(float x, float y) { return x >= y; } +bool test_gt(float x, float y) { return x > y; } + +void test2f() +{ + assert(!test_lt(1.0f, 1.0f)); + assert( test_lt(1.0f, 2.0f)); + assert(!test_lt(2.0f, 1.0f)); + + assert( test_le(1.0f, 1.0f)); + assert( test_le(1.0f, 2.0f)); + assert(! test_le(2.0f, 1.0f)); + + assert( test_eq(1.0f, 1.0f)); + assert(!test_eq(1.0f, 2.0f)); + assert(!test_eq(2.0f, 1.0f)); + + assert(!test_ne(1.0f, 1.0f)); + assert( test_ne(1.0f, 2.0f)); + assert( test_ne(2.0f, 1.0f)); + + assert( test_ge(1.0f, 1.0f)); + assert(!test_ge(1.0f, 2.0f)); + assert( test_ge(2.0f, 1.0f)); + + assert(!test_gt(1.0f, 1.0f)); + assert(!test_gt(1.0f, 2.0f)); + assert( test_gt(2.0f, 1.0f)); +} + +bool test_lt(double x, double y) { return x < y; } +bool test_le(double x, double y) { return x <= y; } +bool test_eq(double x, double y) { return x == y; } +bool test_ne(double x, double y) { return x != y; } +bool test_ge(double x, double y) { return x >= y; } +bool test_gt(double x, double y) { return x > y; } + +void test2d() +{ + assert(!test_lt(1.0, 1.0)); + assert( test_lt(1.0, 2.0)); + assert(!test_lt(2.0, 1.0)); + + assert( test_le(1.0, 1.0)); + assert( test_le(1.0, 2.0)); + assert(! test_le(2.0, 1.0)); + + assert( test_eq(1.0, 1.0)); + assert(!test_eq(1.0, 2.0)); + assert(!test_eq(2.0, 1.0)); + + assert(!test_ne(1.0, 1.0)); + assert( test_ne(1.0, 2.0)); + assert( test_ne(2.0, 1.0)); + + assert( test_ge(1.0, 1.0)); + assert(!test_ge(1.0, 2.0)); + assert( test_ge(2.0, 1.0)); + + assert(!test_gt(1.0, 1.0)); + assert(!test_gt(1.0, 2.0)); + assert( test_gt(2.0, 1.0)); +} + +int main() +{ + test1f(); + test1d(); + test2f(); + test2d(); + return 0; +} diff --git a/gcc/testsuite/gdc.test/runnable/lexer.d b/gcc/testsuite/gdc.test/runnable/lexer.d index 6e31c07..8975146 100644 --- a/gcc/testsuite/gdc.test/runnable/lexer.d +++ b/gcc/testsuite/gdc.test/runnable/lexer.d @@ -87,6 +87,10 @@ enum e13102=184467440737095516153.6L; /*********************************************************/ +static assert("\∾̳" == "\U0000223E\U00000333"); // ="\xe2\x88\xbe\xcc\xb3" + +/*********************************************************/ + int main() { test6(); diff --git a/gcc/testsuite/gdc.test/runnable/test20734.d b/gcc/testsuite/gdc.test/runnable/test20734.d index b3c5916..bd012bb 100644 --- a/gcc/testsuite/gdc.test/runnable/test20734.d +++ b/gcc/testsuite/gdc.test/runnable/test20734.d @@ -17,6 +17,14 @@ extern(C) int main() nothrow @nogc @safe takeScopeSlice([ S(1), S(2) ]); // @nogc => no GC allocation (() @trusted { assert(numDtor == 2); })(); // stack-allocated array literal properly destructed assert23100([]); + + // https://issues.dlang.org/show_bug.cgi?id=22306 + // scope array variable should be stack allocated + scope int[] sa = [10, 20]; + assert(sa[0] == 10); + assert(sa[1] == 20); + assert(sa.length == 2); + return 0; } diff --git a/gcc/testsuite/gdc.test/runnable/test23337.d b/gcc/testsuite/gdc.test/runnable/test23337.d new file mode 100644 index 0000000..47deaba --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test23337.d @@ -0,0 +1,182 @@ +// https://issues.dlang.org/show_bug.cgi?id=23337 + +int copies, destroyed; + +void reset() { copies = destroyed = 0; } + +struct S +{ + this(inout ref S) inout { ++copies; } + ~this() { ++destroyed; } +} + +S[3] globals; + +S[3] makeStaticArray() { return (S[3]).init; } + +S[] makeSlice(ref S[3] sa) { return sa[]; } + +void main() +{ + { + S[3] fromLvalStaticArray = globals; + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + S[3] fromRvalStaticArray = makeStaticArray(); + assert(copies == 0); // moved or emplaced + } + assert(destroyed == 3); + reset(); + + { + S[3] fromArrayLiteral = [S(), S(), S()]; + assert(copies == 0); // moved or emplaced + } + assert(destroyed == 3); + reset(); + + { + S[3] fromSliceExp = globals[]; + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + S[] slice = globals[]; + S[3] fromLvalSlice = slice; + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + S[3] fromRvalSlice = makeSlice(globals); + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + S *p = &globals[0]; + S[3] fromSingleLval = *p; + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + S[3] fromSingleRval = S(); + assert(destroyed == 1); // temporary + assert(copies == 3); + } + assert(destroyed == 4); + reset(); + + // slice-exp left-hand-sides (*construction* only in ctors): + + { + static struct T + { + S[3] ss; + this(int) { ss[] = globals; } + } + T fromLvalStaticArray = T(0); + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + static struct T + { + S[3] ss; + this(int) { ss[] = makeStaticArray(); } + } + T fromRvalStaticArray = T(0); + assert(copies == 0); // moved or emplaced + } + assert(destroyed == 3); + reset(); + + { + static struct T + { + S[3] ss; + this(int) { ss[] = [S(), S(), S()]; } + } + T fromArrayLiteral = T(0); + assert(copies == 0); // moved or emplaced + } + assert(destroyed == 3); + reset(); + + { + static struct T + { + S[3] ss; + this(int) { ss[] = globals[]; } + } + T fromSliceExp = T(0); + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + static struct T + { + S[3] ss; + this(int) + { + S[] slice = globals[]; + ss[] = slice; + } + } + T fromLvalSlice = T(0); + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + static struct T + { + S[3] ss; + this(int) { ss[] = makeSlice(globals); } + } + T fromRvalSlice = T(0); + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + static struct T + { + S[3] ss; + this(int) { ss[] = globals[0]; } + } + T fromSingleLval = T(0); + assert(copies == 3); + } + assert(destroyed == 3); + reset(); + + { + static struct T + { + S[3] ss; + this(int) { ss[] = S(); } + } + T fromSingleRval = T(0); + assert(destroyed == 1); // temporary + assert(copies == 3); + } + assert(destroyed == 4); + reset(); +} -- cgit v1.1 From 96ba0c369ee86d61b6df2f8fb8364028a113acf7 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Sat, 29 Oct 2022 10:16:18 +0200 Subject: Restore RTL alias analysis for hard frame pointer The change: 2021-07-28 Bin Cheng alias.c (init_alias_analysis): Don't skip prologue/epilogue. broke the alias analysis for the hard frame pointer (when it is used as a frame pointer, i.e. when the frame pointer is not eliminated) described in the large comment at the top of the file, because static_reg_base_value is set for it and, consequently, new_reg_base_value too. When the instruction saving the stack pointer into the hard frame pointer in the prologue is processed, it is viewed as a second set of the hard frame pointer and to a different value by record_set, which then proceeds to reset new_reg_base_value to 0 and the game is over. gcc/ * alias.cc (init_alias_analysis): Do not record sets to the hard frame pointer if the frame pointer has not been eliminated. --- gcc/alias.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/alias.cc b/gcc/alias.cc index d54feb1..c62837d 100644 --- a/gcc/alias.cc +++ b/gcc/alias.cc @@ -3369,6 +3369,10 @@ memory_modified_in_insn_p (const_rtx mem, const_rtx insn) void init_alias_analysis (void) { + const bool frame_pointer_eliminated + = reload_completed + && !frame_pointer_needed + && targetm.can_eliminate (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM); unsigned int maxreg = max_reg_num (); int changed, pass; int i; @@ -3446,12 +3450,8 @@ init_alias_analysis (void) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (static_reg_base_value[i] /* Don't treat the hard frame pointer as special if we - eliminated the frame pointer to the stack pointer instead. */ - && !(i == HARD_FRAME_POINTER_REGNUM - && reload_completed - && !frame_pointer_needed - && targetm.can_eliminate (FRAME_POINTER_REGNUM, - STACK_POINTER_REGNUM))) + eliminated the frame pointer to the stack pointer. */ + && !(i == HARD_FRAME_POINTER_REGNUM && frame_pointer_eliminated)) { new_reg_base_value[i] = static_reg_base_value[i]; bitmap_set_bit (reg_seen, i); @@ -3467,10 +3467,15 @@ init_alias_analysis (void) { rtx note, set; + /* Treat the hard frame pointer as special unless we + eliminated the frame pointer to the stack pointer. */ + if (!frame_pointer_eliminated + && modified_in_p (hard_frame_pointer_rtx, insn)) + continue; + /* If this insn has a noalias note, process it, Otherwise, scan for sets. A simple set will have no side effects which could change the base value of any other register. */ - if (GET_CODE (PATTERN (insn)) == SET && REG_NOTES (insn) != 0 && find_reg_note (insn, REG_NOALIAS, NULL_RTX)) -- cgit v1.1 From 7f067400109efa816d68d13bae1a3d20297ad51b Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Sat, 29 Oct 2022 14:12:04 +0200 Subject: Repair --disable-sjlj-exceptions It was broken by: 2022-08-31 Martin Liska config.build: Remove deprecated ports. config.gcc: Likewise. config.host: Likewise. configure.ac: Likewise. configure: Regenerate. config/pa/pa-hpux10.h: Removed. config/pa/pa-hpux10.opt: Removed. config/pa/t-dce-thr: Removed. gcc/ * configure.ac (sjlj-exceptions): Restore dropped line. * configure: Regenerate. --- gcc/configure | 8 +++++--- gcc/configure.ac | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/configure b/gcc/configure index 89e00b7..0ee4be4 100755 --- a/gcc/configure +++ b/gcc/configure @@ -12684,7 +12684,9 @@ objext='.o' # With Setjmp/Longjmp based exception handling. # Check whether --enable-sjlj-exceptions was given. if test "${enable_sjlj_exceptions+set}" = set; then : - enableval=$enable_sjlj_exceptions; case $target in + enableval=$enable_sjlj_exceptions; force_sjlj_exceptions=yes +else + case $target in lm32*-*-*) force_sjlj_exceptions=yes enableval=yes @@ -19718,7 +19720,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19721 "configure" +#line 19723 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -19824,7 +19826,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19827 "configure" +#line 19829 "configure" #include "confdefs.h" #if HAVE_DLFCN_H diff --git a/gcc/configure.ac b/gcc/configure.ac index eb92a37..4ecccff 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -1805,6 +1805,7 @@ AC_SUBST(objext) AC_ARG_ENABLE(sjlj-exceptions, [AS_HELP_STRING([--enable-sjlj-exceptions], [arrange to use setjmp/longjmp exception handling])], +[force_sjlj_exceptions=yes], [case $target in lm32*-*-*) force_sjlj_exceptions=yes -- cgit v1.1 From f36bba013361d8d4f9c7237c3307630de0cc0416 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 30 Oct 2022 00:16:29 +0000 Subject: Daily bump. --- gcc/ChangeLog | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/d/ChangeLog | 29 ++++++++++++++++++++++ gcc/lto/ChangeLog | 4 ++++ gcc/testsuite/ChangeLog | 24 +++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 27e2c49..82da445 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,67 @@ +2022-10-29 Eric Botcazou + + * configure.ac (sjlj-exceptions): Restore dropped line. + * configure: Regenerate. + +2022-10-29 Eric Botcazou + + * alias.cc (init_alias_analysis): Do not record sets to the hard + frame pointer if the frame pointer has not been eliminated. + +2022-10-29 Iain Buclaw + + * config/darwin-d.cc (TARGET_D_MINFO_START_NAME): Rename to ... + (TARGET_D_MINFO_SECTION_START): ...this. + (TARGET_D_MINFO_END_NAME): Rename to ... + (TARGET_D_MINFO_SECTION_END): ... this. + * config/elfos.h (TARGET_D_MINFO_SECTION): Remove. + (TARGET_D_MINFO_START_NAME): Remove. + (TARGET_D_MINFO_END_NAME): Remove. + * config/i386/cygwin-d.cc (TARGET_D_MINFO_SECTION): Remove. + (TARGET_D_MINFO_START_NAME): Remove. + (TARGET_D_MINFO_END_NAME): Remove. + * config/i386/winnt-d.cc (TARGET_D_MINFO_SECTION): Remove. + (TARGET_D_MINFO_START_NAME): Remove. + (TARGET_D_MINFO_END_NAME): Remove. + * doc/tm.texi: Regenerate. + * doc/tm.texi.in (TARGET_D_MINFO_START_NAME): Rename to ... + (TARGET_D_MINFO_SECTION_START): ...this. + (TARGET_D_MINFO_END_NAME): Rename to ... + (TARGET_D_MINFO_SECTION_END): ...this. + +2022-10-29 Iain Buclaw + + * config.gcc: Split out glibc-d.o into linux-d.o, kfreebsd-d.o, + kopensolaris-d.o, and gnu-d.o. Split out cygwin-d.o from winnt-d.o. + * config/arm/linux-eabi.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. + * config/gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Remove. + * config/i386/cygwin.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. + * config/i386/linux-common.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. + * config/i386/mingw32.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. + * config/i386/t-cygming: Add cygwin-d.o. + * config/i386/winnt-d.cc (winnt_d_os_builtins): Only add + MinGW-specific version condition. + * config/kfreebsd-gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Remove. + * config/kopensolaris-gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Remove. + * config/linux-android.h (ANDROID_TARGET_D_OS_VERSIONS): Remove. + * config/linux.h (GNU_USER_TARGET_D_OS_VERSIONS): Remove. + * config/mips/linux-common.h (EXTRA_TARGET_D_OS_VERSIONS): Remove. + * config/t-glibc: Remove glibc-d.o, add gnu-d.o, kfreebsd-d.o, + kopensolaris-d.o. + * config/t-linux: Add linux-d.o. + * config/glibc-d.cc: Remove file. + * config/gnu-d.cc: New file. + * config/i386/cygwin-d.cc: New file. + * config/kfreebsd-d.cc: New file. + * config/kopensolaris-d.cc: New file. + * config/linux-d.cc: New file. + +2022-10-29 Jeff Law + + * config/h8300/h8300.cc (pre_incdec_with_reg): Make reg argument + an unsigned int + * config/h8300/h8300-protos.h (pre_incdec_with_reg): Adjust prototype. + 2022-10-28 Joseph Myers * config/aarch64/aarch64.cc (aarch64_setup_incoming_varargs): diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 06511cc..1440bc5 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20221029 +20221030 diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 434c1c6..888d82b 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,32 @@ +2022-10-29 Iain Buclaw + + * d-attribs.cc (apply_user_attributes): Update for new front-end + interface. + * d-builtins.cc (d_init_versions): Predefine `D_Optimized' with + compiling with optimizations enabled. + * d-lang.cc (d_handle_option): Update for new front-end interface. + Handle new option `-fpreview=systemvariables'. + * dmd/MERGE: Merge upstream dmd e4f8919591. + * dmd/VERSION: Bump version to v2.101.0-beta.1. + * expr.cc (ExprVisitor::visit (AssignExp *)): Treat construction of + static arrays from a call expression as a simple assignment. + (ExprVisitor::visit (ArrayLiteralExp *)): Handle array literals with + `scope' storage. + * gdc.texi: Update documentation of `-fpreview=' options. + * lang.opt (fpreview=shortenedmethods): Remove. + (fpreview=systemvariables): New option. + +2022-10-29 Iain Buclaw + + * d-target.def (d_minfo_section): Expand documentation of hook. + Default initialize to "minfo". + (d_minfo_start_name): Rename to ... + (d_minfo_section_start): ... this. Default initialize to + "__start_minfo". + (d_minfo_end_name): Rename to ... + (d_minfo_section_end): ... this. Default initialize to "__stop_minfo". + * modules.cc (register_moduleinfo): Use new targetdm hook names. + 2022-09-27 Iain Buclaw * dmd/MERGE: Merge upstream dmd d579c467c1. diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index b350d50..3ede467 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,7 @@ +2022-10-29 Thomas Schwinge + + * lang.opt: Better separate 'LTO' vs. 'LTODump'. + 2022-10-28 Joseph Myers * lto-common.cc (compare_tree_sccs_1): Compare diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 90c3b92..6e6635e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,27 @@ +2022-10-29 Iain Buclaw + + * gdc.dg/simd19630.d: Move tests with errors to ... + * gdc.dg/simd19630b.d: ... here. New test. + * gdc.dg/simd19630c.d: New test. + * gdc.dg/simd_ctfe.d: Removed. + * gdc.dg/simd18867.d: New test. + * gdc.dg/simd19788.d: New test. + * gdc.dg/simd21469.d: New test. + * gdc.dg/simd21672.d: New test. + * gdc.dg/simd23077.d: New test. + * gdc.dg/simd23084.d: New test. + * gdc.dg/simd23085.d: New test. + * gdc.dg/torture/simd19632.d: New test. + * gdc.dg/torture/simd20041.d: New test. + * gdc.dg/torture/simd21673.d: New test. + * gdc.dg/torture/simd21676.d: New test. + * gdc.dg/torture/simd22438.d: New test. + * gdc.dg/torture/simd23009.d: New test. + * gdc.dg/torture/simd23077.d: New test. + * gdc.dg/torture/simd8.d: New test. + * gdc.dg/torture/simd9.d: New test. + * gdc.dg/torture/simd_prefetch.d: New test. + 2022-10-28 Marek Polacek * g++.dg/warn/Wdangling-reference4.C: New test. -- cgit v1.1 From da5e884411903f82cb665476a0e8df3fe51a84ae Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 31 Oct 2022 00:18:12 +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 1440bc5..bed449a 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20221030 +20221031 -- cgit v1.1 From 6913cad2a38bc406b137b06d579b650f6fe9a2e6 Mon Sep 17 00:00:00 2001 From: liuhongt Date: Tue, 25 Oct 2022 13:31:54 +0800 Subject: Enable V4BFmode and V2BFmode. Enable V4BFmode and V2BFmode with the same ABI as V4HFmode and V2HFmode. No real operation is supported for them except for movement. This should solve PR target/107261. Also I notice there's redundancy in VALID_AVX512FP16_REG_MODE, and remove V2BFmode remove it. gcc/ChangeLog: PR target/107261 * config/i386/i386-modes.def (VECTOR_MODE): Support V2BFmode. * config/i386/i386.cc (classify_argument): Handle V4BFmode and V2BFmode. (ix86_convert_const_vector_to_integer): Ditto. * config/i386/i386.h (VALID_AVX512FP16_REG_MODE): Remove V2BFmode. (VALID_SSE2_REG_MODE): Add V4BFmode and V2BFmode. (VALID_MMX_REG_MODE): Add V4BFmode. * config/i386/i386.md (mode): Add V4BF and V2BF. (MODE_SIZE): Ditto. * config/i386/mmx.md (MMXMODE) Add V4BF. (V_32): Add V2BF. (V_16_32_64): Add V4BF and V2BF. (mmxinsnmode): Add V4BF and V2BF. (*mov_internal): Hanlde V4BFmode and V2BFmode. gcc/testsuite/ChangeLog: * gcc.target/i386/pr107261.c: New test. --- gcc/config/i386/i386-modes.def | 1 + gcc/config/i386/i386.cc | 6 +++++ gcc/config/i386/i386.h | 9 ++++---- gcc/config/i386/i386.md | 5 +++-- gcc/config/i386/mmx.md | 26 +++++++++++++--------- gcc/testsuite/gcc.target/i386/pr107261.c | 38 ++++++++++++++++++++++++++++++++ 6 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr107261.c (limited to 'gcc') diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def index b49daae..dbc3165 100644 --- a/gcc/config/i386/i386-modes.def +++ b/gcc/config/i386/i386-modes.def @@ -93,6 +93,7 @@ VECTOR_MODES (FLOAT, 64); /* V32HF V16SF V8DF V4TF */ VECTOR_MODES (FLOAT, 128); /* V64HF V32SF V16DF V8TF */ VECTOR_MODES (FLOAT, 256); /* V128HF V64SF V32DF V16TF */ VECTOR_MODE (FLOAT, HF, 2); /* V2HF */ +VECTOR_MODE (FLOAT, BF, 2); /* V2BF */ VECTOR_MODE (FLOAT, HF, 6); /* V6HF */ VECTOR_MODE (INT, TI, 1); /* V1TI */ VECTOR_MODE (INT, DI, 1); /* V1DI */ diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index e775ba4..c0f3714 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -2507,7 +2507,9 @@ classify_argument (machine_mode mode, const_tree type, case E_V2SImode: case E_V4HImode: case E_V4HFmode: + case E_V4BFmode: case E_V2HFmode: + case E_V2BFmode: case E_V8QImode: classes[0] = X86_64_SSE_CLASS; return 1; @@ -2991,6 +2993,7 @@ pass_in_reg: case E_V8QImode: case E_V4HImode: case E_V4HFmode: + case E_V4BFmode: case E_V2SImode: case E_V2SFmode: case E_V1TImode: @@ -3240,6 +3243,7 @@ pass_in_reg: case E_V8QImode: case E_V4HImode: case E_V4HFmode: + case E_V4BFmode: case E_V2SImode: case E_V2SFmode: case E_V1TImode: @@ -15811,7 +15815,9 @@ ix86_convert_const_vector_to_integer (rtx op, machine_mode mode) } break; case E_V2HFmode: + case E_V2BFmode: case E_V4HFmode: + case E_V4BFmode: case E_V2SFmode: for (int i = 0; i < nunits; ++i) { diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index fd7c9df..16d9c60 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1033,13 +1033,12 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (MODE) == V8BFmode || (MODE) == TImode) #define VALID_AVX512FP16_REG_MODE(MODE) \ - ((MODE) == V8HFmode || (MODE) == V16HFmode || (MODE) == V32HFmode \ - || (MODE) == V2HFmode) + ((MODE) == V8HFmode || (MODE) == V16HFmode || (MODE) == V32HFmode) #define VALID_SSE2_REG_MODE(MODE) \ ((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \ || (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode \ - || (MODE) == V8BFmode \ + || (MODE) == V8BFmode || (MODE) == V4BFmode || (MODE) == V2BFmode \ || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \ || (MODE) == V2DImode || (MODE) == V2QImode || (MODE) == DFmode \ || (MODE) == HFmode || (MODE) == BFmode) @@ -1057,7 +1056,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); ((MODE) == V1DImode || (MODE) == DImode \ || (MODE) == V2SImode || (MODE) == SImode \ || (MODE) == V4HImode || (MODE) == V8QImode \ - || (MODE) == V4HFmode) + || (MODE) == V4HFmode || (MODE) == V4BFmode) #define VALID_MASK_REG_MODE(MODE) ((MODE) == HImode || (MODE) == QImode) @@ -1074,7 +1073,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (MODE) == CSImode || (MODE) == CDImode \ || (MODE) == SDmode || (MODE) == DDmode \ || (MODE) == HFmode || (MODE) == HCmode || (MODE) == BFmode \ - || (MODE) == V2HImode || (MODE) == V2HFmode \ + || (MODE) == V2HImode || (MODE) == V2HFmode || (MODE) == V2BFmode \ || (MODE) == V1SImode || (MODE) == V4QImode || (MODE) == V2QImode \ || (TARGET_64BIT \ && ((MODE) == TImode || (MODE) == CTImode \ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index aaa678e..8081df7 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -501,7 +501,7 @@ ;; Main data type used by the insn (define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,BF,SF,DF,XF,TF,V32HF,V16HF,V8HF, - V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V2HF" + V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V4BF,V2HF,V2BF" (const_string "unknown")) ;; The CPU unit operations uses. @@ -1120,7 +1120,8 @@ (V4SF "16") (V8SF "32") (V16SF "64") (V8HF "16") (V16HF "32") (V32HF "64") (V4HF "8") (V2HF "4") - (V8BF "16") (V16BF "32") (V32BF "64")]) + (V8BF "16") (V16BF "32") (V32BF "64") + (V4BF "8") (V2BF "4")]) ;; Double word integer modes as mode attribute. (define_mode_attr DWI [(QI "HI") (HI "SI") (SI "DI") (DI "TI") (TI "OI")]) diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index c359e2d..d5134cc 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -48,7 +48,7 @@ (define_mode_iterator MMXMODEI8 [V8QI V4HI V2SI (V1DI "TARGET_SSE2")]) ;; All 8-byte vector modes handled by MMX -(define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF V4HF]) +(define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF V4HF V4BF]) (define_mode_iterator MMXMODE124 [V8QI V4HI V2SI V2SF]) ;; Mix-n-match @@ -58,7 +58,7 @@ (define_mode_iterator MMXMODE248 [V4HI V2SI V1DI]) ;; All 4-byte integer/float16 vector modes -(define_mode_iterator V_32 [V4QI V2HI V1SI V2HF]) +(define_mode_iterator V_32 [V4QI V2HI V1SI V2HF V2BF]) ;; 4-byte integer vector modes (define_mode_iterator VI_32 [V4QI V2HI]) @@ -72,7 +72,8 @@ ;; All 2-byte, 4-byte and 8-byte vector modes with more than 1 element (define_mode_iterator V_16_32_64 [V2QI V4QI V2HI V2HF - (V8QI "TARGET_64BIT") (V4HI "TARGET_64BIT") (V4HF "TARGET_64BIT") + (V8QI "TARGET_64BIT") (V4HI "TARGET_64BIT") + (V4HF "TARGET_64BIT") (V4BF "TARGET_64BIT") (V2SI "TARGET_64BIT") (V2SF "TARGET_64BIT")]) ;; V2S* modes @@ -92,6 +93,7 @@ (V4HI "DI") (V2HI "SI") (V2SI "DI") (V4HF "DI") (V2HF "SI") + (V4BF "DI") (V2BF "SI") (V2SF "DI")]) (define_mode_attr mmxdoublemode @@ -213,9 +215,9 @@ (cond [(eq_attr "alternative" "2") (const_string "SI") (eq_attr "alternative" "11,12") - (cond [(match_test "mode == V2SFmode") - (const_string "V4SF") - (match_test "mode == V4HFmode") + (cond [(match_test "mode == V2SFmode + || mode == V4HFmode + || mode == V4BFmode") (const_string "V4SF") (ior (not (match_test "TARGET_SSE2")) (match_test "optimize_function_for_size_p (cfun)")) @@ -227,13 +229,15 @@ (ior (ior (and (match_test "mode == V2SFmode") (not (match_test "TARGET_MMX_WITH_SSE"))) (not (match_test "TARGET_SSE2"))) - (match_test "mode == V4HFmode"))) + (match_test "mode == V4HFmode + || mode == V4BFmode"))) (const_string "V2SF") (and (eq_attr "alternative" "14") (ior (ior (match_test "mode == V2SFmode") (not (match_test "TARGET_SSE2"))) - (match_test "mode == V4HFmode"))) + (match_test "mode == V4HFmode + || mode == V4BFmode"))) (const_string "V2SF") ] (const_string "DI"))) @@ -321,7 +325,8 @@ (const_string "*"))) (set (attr "mode") (cond [(eq_attr "alternative" "2,3") - (cond [(match_test "mode == V2HFmode") + (cond [(match_test "mode == V2HFmode + || mode == V2BFmode") (const_string "V4SF") (match_test "TARGET_AVX") (const_string "TI") @@ -332,7 +337,8 @@ (const_string "TI")) (and (eq_attr "alternative" "4,5") - (ior (match_test "mode == V2HFmode") + (ior (match_test "mode == V2HFmode + || mode == V2BFmode") (not (match_test "TARGET_SSE2")))) (const_string "SF") ] diff --git a/gcc/testsuite/gcc.target/i386/pr107261.c b/gcc/testsuite/gcc.target/i386/pr107261.c new file mode 100644 index 0000000..eb1d232 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr107261.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2" } */ + +typedef __bf16 v4bf __attribute__ ((vector_size (8))); +typedef __bf16 v2bf __attribute__ ((vector_size (4))); + +v4bf +v4bf_abi_1 (v4bf a) +{ + return a; +} + +v4bf +v4bf_abi_3 (v4bf a, v4bf b, v4bf c) +{ + return c; +} + +/* { dg-final { scan-assembler-times "movq\[\\t \]*%mm2, %mm0" 1 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "movaps\[\\t \]*%xmm2, %xmm0" 1 { target { ! ia32 } } } } */ + +v4bf +v4bf_abi_4 (v4bf a, v4bf b, v4bf c, v4bf d) +{ + return d; +} + +/* { dg-final { scan-assembler-times "movq\[\\t \]*4\\(%esp\\), %mm0" 1 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "movaps\[\\t \]*%xmm3, %xmm0" 1 { target { ! ia32 } } } } */ + +v2bf +v2bf_test (v2bf a, v2bf b, v2bf c, v2bf d) +{ + return b; +} + +/* { dg-final { scan-assembler-times "movl\[\\t \]*8\\(%esp\\), %eax" 1 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "movaps\[\\t \]*%xmm1, %xmm0" 1 { target { ! ia32 } } } } */ -- cgit v1.1 From 87235f1e5c740de9c6f72a5dd7d7eb9cb7df2e1d Mon Sep 17 00:00:00 2001 From: konglin1 Date: Mon, 31 Oct 2022 14:04:08 +0800 Subject: i386:: using __bf16 for AVX512BF16 intrinsics gcc/ChangeLog: * config/i386/avx512bf16intrin.h (__attribute__): Change short to bf16. (_mm_cvtsbh_ss): Ditto. (_mm512_cvtne2ps_pbh): Ditto. (_mm512_mask_cvtne2ps_pbh): Ditto. (_mm512_maskz_cvtne2ps_pbh): Ditto. * config/i386/avx512bf16vlintrin.h (__attribute__): Ditto. (_mm256_cvtne2ps_pbh): Ditto. (_mm256_mask_cvtne2ps_pbh): Ditto. (_mm256_maskz_cvtne2ps_pbh): Ditto. (_mm_cvtne2ps_pbh): Ditto. (_mm_mask_cvtne2ps_pbh): Ditto. (_mm_maskz_cvtne2ps_pbh): Ditto. (_mm_cvtness_sbh): Ditto. * config/i386/i386-builtin-types.def (V8BF): Add new DEF_VECTOR_TYPE for BFmode. (V16BF): Ditto. (V32BF): Ditto. * config/i386/i386-builtin.def (BDESC): Fixed builtins. * config/i386/i386-expand.cc (ix86_expand_args_builtin): Changed avx512bf16 ix86_builtin_func_type included HI to BF. * config/i386/immintrin.h: Add SSE2 depend for avx512bf16. * config/i386/sse.md (TARGET_AVX512VL): Changed HI vector to BF vector. (avx512f_cvtneps2bf16_v4sf): New define_expand. (*avx512f_cvtneps2bf16_v4sf): New define_insn. (avx512f_cvtneps2bf16_v4sf_maskz):Ditto. (avx512f_cvtneps2bf16_v4sf_mask): Ditto. (avx512f_cvtneps2bf16_v4sf_mask_1): Ditto. gcc/testsuite/ChangeLog: * gcc.target/i386/avx512bf16-cvtsbh2ss-1.c: Add fpmath option. * gcc.target/i386/avx512bf16-vdpbf16ps-2.c: Fixed scan-assembler. * gcc.target/i386/avx512bf16vl-cvtness2sbh-1.c: Add x/y suffix for vcvtneps2bf16. * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c: Ditto. --- gcc/config/i386/avx512bf16intrin.h | 12 +-- gcc/config/i386/avx512bf16vlintrin.h | 29 +++--- gcc/config/i386/i386-builtin-types.def | 51 ++++++----- gcc/config/i386/i386-builtin.def | 54 +++++------ gcc/config/i386/i386-expand.cc | 48 +++++----- gcc/config/i386/immintrin.h | 2 + gcc/config/i386/sse.md | 101 ++++++++++++++++----- .../gcc.target/i386/avx512bf16-cvtsbh2ss-1.c | 2 +- .../gcc.target/i386/avx512bf16-vdpbf16ps-2.c | 2 +- .../gcc.target/i386/avx512bf16vl-cvtness2sbh-1.c | 2 +- .../gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c | 12 +-- 11 files changed, 189 insertions(+), 126 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/avx512bf16intrin.h b/gcc/config/i386/avx512bf16intrin.h index b6e9dda..ea1d012 100644 --- a/gcc/config/i386/avx512bf16intrin.h +++ b/gcc/config/i386/avx512bf16intrin.h @@ -35,16 +35,16 @@ #endif /* __AVX512BF16__ */ /* Internal data types for implementing the intrinsics. */ -typedef short __v32bh __attribute__ ((__vector_size__ (64))); +typedef __bf16 __v32bf __attribute__ ((__vector_size__ (64))); /* The Intel API is flexible enough that we must allow aliasing with other vector types, and their scalar components. */ -typedef short __m512bh __attribute__ ((__vector_size__ (64), __may_alias__)); +typedef __bf16 __m512bh __attribute__ ((__vector_size__ (64), __may_alias__)); /* Convert One BF16 Data to One Single Float Data. */ extern __inline float __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) -_mm_cvtsbh_ss (__bfloat16 __A) +_mm_cvtsbh_ss (__bf16 __A) { union{ float a; unsigned int b;} __tmp; __tmp.b = ((unsigned int)(__A)) << 16; @@ -57,21 +57,21 @@ extern __inline __m512bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm512_cvtne2ps_pbh (__m512 __A, __m512 __B) { - return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32hi(__A, __B); + return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf(__A, __B); } extern __inline __m512bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm512_mask_cvtne2ps_pbh (__m512bh __A, __mmask32 __B, __m512 __C, __m512 __D) { - return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32hi_mask(__C, __D, __A, __B); + return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf_mask(__C, __D, __A, __B); } extern __inline __m512bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm512_maskz_cvtne2ps_pbh (__mmask32 __A, __m512 __B, __m512 __C) { - return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32hi_maskz(__B, __C, __A); + return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf_maskz(__B, __C, __A); } /* vcvtneps2bf16 */ diff --git a/gcc/config/i386/avx512bf16vlintrin.h b/gcc/config/i386/avx512bf16vlintrin.h index 969335f..56c28f1 100644 --- a/gcc/config/i386/avx512bf16vlintrin.h +++ b/gcc/config/i386/avx512bf16vlintrin.h @@ -35,57 +35,58 @@ #endif /* __AVX512BF16__ */ /* Internal data types for implementing the intrinsics. */ -typedef short __v16bh __attribute__ ((__vector_size__ (32))); -typedef short __v8bh __attribute__ ((__vector_size__ (16))); +typedef __bf16 __v16bf __attribute__ ((__vector_size__ (32))); +typedef __bf16 __v8bf __attribute__ ((__vector_size__ (16))); /* The Intel API is flexible enough that we must allow aliasing with other vector types, and their scalar components. */ -typedef short __m256bh __attribute__ ((__vector_size__ (32), __may_alias__)); -typedef short __m128bh __attribute__ ((__vector_size__ (16), __may_alias__)); +typedef __bf16 __m256bh __attribute__ ((__vector_size__ (32), __may_alias__)); +typedef __bf16 __m128bh __attribute__ ((__vector_size__ (16), __may_alias__)); + +typedef __bf16 __bfloat16; -typedef unsigned short __bfloat16; /* vcvtne2ps2bf16 */ extern __inline __m256bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm256_cvtne2ps_pbh (__m256 __A, __m256 __B) { - return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16hi(__A, __B); + return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf(__A, __B); } extern __inline __m256bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm256_mask_cvtne2ps_pbh (__m256bh __A, __mmask16 __B, __m256 __C, __m256 __D) { - return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16hi_mask(__C, __D, __A, __B); + return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf_mask(__C, __D, __A, __B); } extern __inline __m256bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm256_maskz_cvtne2ps_pbh (__mmask16 __A, __m256 __B, __m256 __C) { - return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16hi_maskz(__B, __C, __A); + return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf_maskz(__B, __C, __A); } extern __inline __m128bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_cvtne2ps_pbh (__m128 __A, __m128 __B) { - return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8hi(__A, __B); + return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf(__A, __B); } extern __inline __m128bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_mask_cvtne2ps_pbh (__m128bh __A, __mmask8 __B, __m128 __C, __m128 __D) { - return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8hi_mask(__C, __D, __A, __B); + return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf_mask(__C, __D, __A, __B); } extern __inline __m128bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_maskz_cvtne2ps_pbh (__mmask8 __A, __m128 __B, __m128 __C) { - return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8hi_maskz(__B, __C, __A); + return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf_maskz(__B, __C, __A); } /* vcvtneps2bf16 */ @@ -176,13 +177,13 @@ _mm_maskz_dpbf16_ps (__mmask8 __A, __m128 __B, __m128bh __C, __m128bh __D) return (__m128)__builtin_ia32_dpbf16ps_v4sf_maskz(__B, __C, __D, __A); } -extern __inline __bfloat16 +extern __inline __bf16 __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm_cvtness_sbh (float __A) { __v4sf __V = {__A, 0, 0, 0}; - __v8hi __R = __builtin_ia32_cvtneps2bf16_v4sf_mask ((__v4sf)__V, - (__v8hi)_mm_undefined_si128 (), (__mmask8)-1); + __v8bf __R = __builtin_ia32_cvtneps2bf16_v4sf_mask ((__v4sf)__V, + (__v8bf)_mm_undefined_si128 (), (__mmask8)-1); return __R[0]; } diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def index 63a360b..aedae2d 100644 --- a/gcc/config/i386/i386-builtin-types.def +++ b/gcc/config/i386/i386-builtin-types.def @@ -87,6 +87,7 @@ DEF_VECTOR_TYPE (V8QI, QI) DEF_VECTOR_TYPE (V2DF, DOUBLE) DEF_VECTOR_TYPE (V4SF, FLOAT) DEF_VECTOR_TYPE (V8HF, FLOAT16) +DEF_VECTOR_TYPE (V8BF, BFLOAT16) DEF_VECTOR_TYPE (V2DI, DI) DEF_VECTOR_TYPE (V4SI, SI) DEF_VECTOR_TYPE (V8HI, HI) @@ -100,6 +101,7 @@ DEF_VECTOR_TYPE (V16UQI, UQI, V16QI) DEF_VECTOR_TYPE (V4DF, DOUBLE) DEF_VECTOR_TYPE (V8SF, FLOAT) DEF_VECTOR_TYPE (V16HF, FLOAT16) +DEF_VECTOR_TYPE (V16BF, BFLOAT16) DEF_VECTOR_TYPE (V4DI, DI) DEF_VECTOR_TYPE (V8SI, SI) DEF_VECTOR_TYPE (V16HI, HI) @@ -111,6 +113,7 @@ DEF_VECTOR_TYPE (V16UHI, UHI, V16HI) # AVX512F vectors DEF_VECTOR_TYPE (V32SF, FLOAT) DEF_VECTOR_TYPE (V32HF, FLOAT16) +DEF_VECTOR_TYPE (V32BF, BFLOAT16) DEF_VECTOR_TYPE (V16SF, FLOAT) DEF_VECTOR_TYPE (V8DF, DOUBLE) DEF_VECTOR_TYPE (V8DI, DI) @@ -1273,30 +1276,30 @@ DEF_FUNCTION_TYPE (V4SI, V4SI, V4SI, UHI) DEF_FUNCTION_TYPE (V8SI, V8SI, V8SI, UHI) # BF16 builtins -DEF_FUNCTION_TYPE (V32HI, V16SF, V16SF) -DEF_FUNCTION_TYPE (V32HI, V16SF, V16SF, V32HI, USI) -DEF_FUNCTION_TYPE (V32HI, V16SF, V16SF, USI) -DEF_FUNCTION_TYPE (V16HI, V8SF, V8SF) -DEF_FUNCTION_TYPE (V16HI, V8SF, V8SF, V16HI, UHI) -DEF_FUNCTION_TYPE (V16HI, V8SF, V8SF, UHI) -DEF_FUNCTION_TYPE (V8HI, V4SF, V4SF) -DEF_FUNCTION_TYPE (V8HI, V4SF, V4SF, V8HI, UQI) -DEF_FUNCTION_TYPE (V8HI, V4SF, V4SF, UQI) -DEF_FUNCTION_TYPE (V16HI, V16SF) -DEF_FUNCTION_TYPE (V16HI, V16SF, V16HI, UHI) -DEF_FUNCTION_TYPE (V16HI, V16SF, UHI) -DEF_FUNCTION_TYPE (V8HI, V8SF) -DEF_FUNCTION_TYPE (V8HI, V8SF, V8HI, UQI) -DEF_FUNCTION_TYPE (V8HI, V8SF, UQI) -DEF_FUNCTION_TYPE (V8HI, V4SF) -DEF_FUNCTION_TYPE (V8HI, V4SF, V8HI, UQI) -DEF_FUNCTION_TYPE (V8HI, V4SF, UQI) -DEF_FUNCTION_TYPE (V16SF, V16SF, V32HI, V32HI) -DEF_FUNCTION_TYPE (V16SF, V16SF, V32HI, V32HI, UHI) -DEF_FUNCTION_TYPE (V8SF, V8SF, V16HI, V16HI) -DEF_FUNCTION_TYPE (V8SF, V8SF, V16HI, V16HI, UQI) -DEF_FUNCTION_TYPE (V4SF, V4SF, V8HI, V8HI) -DEF_FUNCTION_TYPE (V4SF, V4SF, V8HI, V8HI, UQI) +DEF_FUNCTION_TYPE (V32BF, V16SF, V16SF) +DEF_FUNCTION_TYPE (V32BF, V16SF, V16SF, V32BF, USI) +DEF_FUNCTION_TYPE (V32BF, V16SF, V16SF, USI) +DEF_FUNCTION_TYPE (V16BF, V8SF, V8SF) +DEF_FUNCTION_TYPE (V16BF, V8SF, V8SF, V16BF, UHI) +DEF_FUNCTION_TYPE (V16BF, V8SF, V8SF, UHI) +DEF_FUNCTION_TYPE (V8BF, V4SF, V4SF) +DEF_FUNCTION_TYPE (V8BF, V4SF, V4SF, V8BF, UQI) +DEF_FUNCTION_TYPE (V8BF, V4SF, V4SF, UQI) +DEF_FUNCTION_TYPE (V16BF, V16SF) +DEF_FUNCTION_TYPE (V16BF, V16SF, V16BF, UHI) +DEF_FUNCTION_TYPE (V16BF, V16SF, UHI) +DEF_FUNCTION_TYPE (V8BF, V8SF) +DEF_FUNCTION_TYPE (V8BF, V8SF, V8BF, UQI) +DEF_FUNCTION_TYPE (V8BF, V8SF, UQI) +DEF_FUNCTION_TYPE (V8BF, V4SF) +DEF_FUNCTION_TYPE (V8BF, V4SF, V8BF, UQI) +DEF_FUNCTION_TYPE (V8BF, V4SF, UQI) +DEF_FUNCTION_TYPE (V16SF, V16SF, V32BF, V32BF) +DEF_FUNCTION_TYPE (V16SF, V16SF, V32BF, V32BF, UHI) +DEF_FUNCTION_TYPE (V8SF, V8SF, V16BF, V16BF) +DEF_FUNCTION_TYPE (V8SF, V8SF, V16BF, V16BF, UQI) +DEF_FUNCTION_TYPE (V4SF, V4SF, V8BF, V8BF) +DEF_FUNCTION_TYPE (V4SF, V4SF, V8BF, V8BF, UQI) # KEYLOCKER builtins DEF_FUNCTION_TYPE (UINT, UINT, V2DI, V2DI, PVOID) diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def index e35306e..5802e20 100644 --- a/gcc/config/i386/i386-builtin.def +++ b/gcc/config/i386/i386-builtin.def @@ -2779,33 +2779,33 @@ BDESC (0, OPTION_MASK_ISA2_VAES, CODE_FOR_vaesenclast_v32qi, "__builtin_ia32_vae BDESC (0, OPTION_MASK_ISA2_VAES, CODE_FOR_vaesenclast_v64qi, "__builtin_ia32_vaesenclast_v64qi", IX86_BUILTIN_VAESENCLAST64, UNKNOWN, (int) V64QI_FTYPE_V64QI_V64QI) /* BF16 */ -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v32hi, "__builtin_ia32_cvtne2ps2bf16_v32hi", IX86_BUILTIN_CVTNE2PS2HI16_V32HI, UNKNOWN, (int) V32HI_FTYPE_V16SF_V16SF) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v32hi_mask, "__builtin_ia32_cvtne2ps2bf16_v32hi_mask", IX86_BUILTIN_CVTNE2PS2HI16_V32HI_MASK, UNKNOWN, (int) V32HI_FTYPE_V16SF_V16SF_V32HI_USI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v32hi_maskz, "__builtin_ia32_cvtne2ps2bf16_v32hi_maskz", IX86_BUILTIN_CVTNE2PS2HI16_V32HI_MASKZ, UNKNOWN, (int) V32HI_FTYPE_V16SF_V16SF_USI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v16hi, "__builtin_ia32_cvtne2ps2bf16_v16hi", IX86_BUILTIN_CVTNE2PS2HI16_V16HI, UNKNOWN, (int) V16HI_FTYPE_V8SF_V8SF) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v16hi_mask, "__builtin_ia32_cvtne2ps2bf16_v16hi_mask", IX86_BUILTIN_CVTNE2PS2HI16_V16HI_MASK, UNKNOWN, (int) V16HI_FTYPE_V8SF_V8SF_V16HI_UHI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v16hi_maskz, "__builtin_ia32_cvtne2ps2bf16_v16hi_maskz", IX86_BUILTIN_CVTNE2PS2HI16_V16HI_MASKZ, UNKNOWN, (int) V16HI_FTYPE_V8SF_V8SF_UHI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v8hi, "__builtin_ia32_cvtne2ps2bf16_v8hi", IX86_BUILTIN_CVTNE2PS2HI16_V8HI, UNKNOWN, (int) V8HI_FTYPE_V4SF_V4SF) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v8hi_mask, "__builtin_ia32_cvtne2ps2bf16_v8hi_mask", IX86_BUILTIN_CVTNE2PS2HI16_V8HI_MASK, UNKNOWN, (int) V8HI_FTYPE_V4SF_V4SF_V8HI_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v8hi_maskz, "__builtin_ia32_cvtne2ps2bf16_v8hi_maskz", IX86_BUILTIN_CVTNE2PS2HI16_V8HI_MASKZ, UNKNOWN, (int) V8HI_FTYPE_V4SF_V4SF_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf, "__builtin_ia32_cvtneps2bf16_v16sf", IX86_BUILTIN_CVTNEPS2HI16_V16SF, UNKNOWN, (int) V16HI_FTYPE_V16SF) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf_mask, "__builtin_ia32_cvtneps2bf16_v16sf_mask", IX86_BUILTIN_CVTNEPS2HI16_V16SF_MASK, UNKNOWN, (int) V16HI_FTYPE_V16SF_V16HI_UHI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf_maskz, "__builtin_ia32_cvtneps2bf16_v16sf_maskz", IX86_BUILTIN_CVTNE2PS2HI16_V16SF_MASKZ, UNKNOWN, (int) V16HI_FTYPE_V16SF_UHI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf, "__builtin_ia32_cvtneps2bf16_v8sf", IX86_BUILTIN_CVTNEPS2HI16_V8SF, UNKNOWN, (int) V8HI_FTYPE_V8SF) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf_mask, "__builtin_ia32_cvtneps2bf16_v8sf_mask", IX86_BUILTIN_CVTNEPS2HI16_V8SF_MASK, UNKNOWN, (int) V8HI_FTYPE_V8SF_V8HI_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf_maskz, "__builtin_ia32_cvtneps2bf16_v8sf_maskz", IX86_BUILTIN_CVTNE2PS2HI16_V8SF_MASKZ, UNKNOWN, (int) V8HI_FTYPE_V8SF_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf, "__builtin_ia32_cvtneps2bf16_v4sf", IX86_BUILTIN_CVTNEPS2HI16_V4SF, UNKNOWN, (int) V8HI_FTYPE_V4SF) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf_mask, "__builtin_ia32_cvtneps2bf16_v4sf_mask", IX86_BUILTIN_CVTNEPS2HI16_V4SF_MASK, UNKNOWN, (int) V8HI_FTYPE_V4SF_V8HI_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf_maskz, "__builtin_ia32_cvtneps2bf16_v4sf_maskz", IX86_BUILTIN_CVTNE2PS2HI16_V4SF_MASKZ, UNKNOWN, (int) V8HI_FTYPE_V4SF_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v16sf, "__builtin_ia32_dpbf16ps_v16sf", IX86_BUILTIN_DPHI16PS_V16SF, UNKNOWN, (int) V16SF_FTYPE_V16SF_V32HI_V32HI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v16sf_mask, "__builtin_ia32_dpbf16ps_v16sf_mask", IX86_BUILTIN_DPHI16PS_V16SF_MASK, UNKNOWN, (int) V16SF_FTYPE_V16SF_V32HI_V32HI_UHI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v16sf_maskz, "__builtin_ia32_dpbf16ps_v16sf_maskz", IX86_BUILTIN_DPHI16PS_V16SF_MASKZ, UNKNOWN, (int) V16SF_FTYPE_V16SF_V32HI_V32HI_UHI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v8sf, "__builtin_ia32_dpbf16ps_v8sf", IX86_BUILTIN_DPHI16PS_V8SF, UNKNOWN, (int) V8SF_FTYPE_V8SF_V16HI_V16HI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v8sf_mask, "__builtin_ia32_dpbf16ps_v8sf_mask", IX86_BUILTIN_DPHI16PS_V8SF_MASK, UNKNOWN, (int) V8SF_FTYPE_V8SF_V16HI_V16HI_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v8sf_maskz, "__builtin_ia32_dpbf16ps_v8sf_maskz", IX86_BUILTIN_DPHI16PS_V8SF_MASKZ, UNKNOWN, (int) V8SF_FTYPE_V8SF_V16HI_V16HI_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf, "__builtin_ia32_dpbf16ps_v4sf", IX86_BUILTIN_DPHI16PS_V4SF, UNKNOWN, (int) V4SF_FTYPE_V4SF_V8HI_V8HI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf_mask, "__builtin_ia32_dpbf16ps_v4sf_mask", IX86_BUILTIN_DPHI16PS_V4SF_MASK, UNKNOWN, (int) V4SF_FTYPE_V4SF_V8HI_V8HI_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf_maskz, "__builtin_ia32_dpbf16ps_v4sf_maskz", IX86_BUILTIN_DPHI16PS_V4SF_MASKZ, UNKNOWN, (int) V4SF_FTYPE_V4SF_V8HI_V8HI_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v32bf, "__builtin_ia32_cvtne2ps2bf16_v32bf", IX86_BUILTIN_CVTNE2PS2BF16_V32BF, UNKNOWN, (int) V32BF_FTYPE_V16SF_V16SF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v32bf_mask, "__builtin_ia32_cvtne2ps2bf16_v32bf_mask", IX86_BUILTIN_CVTNE2PS2BF16_V32BF_MASK, UNKNOWN, (int) V32BF_FTYPE_V16SF_V16SF_V32BF_USI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v32bf_maskz, "__builtin_ia32_cvtne2ps2bf16_v32bf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V32BF_MASKZ, UNKNOWN, (int) V32BF_FTYPE_V16SF_V16SF_USI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v16bf, "__builtin_ia32_cvtne2ps2bf16_v16bf", IX86_BUILTIN_CVTNE2PS2BF16_V16BF, UNKNOWN, (int) V16BF_FTYPE_V8SF_V8SF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v16bf_mask, "__builtin_ia32_cvtne2ps2bf16_v16bf_mask", IX86_BUILTIN_CVTNE2PS2BF16_V16BF_MASK, UNKNOWN, (int) V16BF_FTYPE_V8SF_V8SF_V16BF_UHI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v16bf_maskz, "__builtin_ia32_cvtne2ps2bf16_v16bf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V16BF_MASKZ, UNKNOWN, (int) V16BF_FTYPE_V8SF_V8SF_UHI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v8bf, "__builtin_ia32_cvtne2ps2bf16_v8bf", IX86_BUILTIN_CVTNE2PS2BF16_V8BF, UNKNOWN, (int) V8BF_FTYPE_V4SF_V4SF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v8bf_mask, "__builtin_ia32_cvtne2ps2bf16_v8bf_mask", IX86_BUILTIN_CVTNE2PS2BF16_V8BF_MASK, UNKNOWN, (int) V8BF_FTYPE_V4SF_V4SF_V8BF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v8bf_maskz, "__builtin_ia32_cvtne2ps2bf16_v8bf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V8BF_MASKZ, UNKNOWN, (int) V8BF_FTYPE_V4SF_V4SF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf, "__builtin_ia32_cvtneps2bf16_v16sf", IX86_BUILTIN_CVTNEPS2BF16_V16SF, UNKNOWN, (int) V16BF_FTYPE_V16SF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf_mask, "__builtin_ia32_cvtneps2bf16_v16sf_mask", IX86_BUILTIN_CVTNEPS2BF16_V16SF_MASK, UNKNOWN, (int) V16BF_FTYPE_V16SF_V16BF_UHI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf_maskz, "__builtin_ia32_cvtneps2bf16_v16sf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V16SF_MASKZ, UNKNOWN, (int) V16BF_FTYPE_V16SF_UHI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf, "__builtin_ia32_cvtneps2bf16_v8sf", IX86_BUILTIN_CVTNEPS2BF16_V8SF, UNKNOWN, (int) V8BF_FTYPE_V8SF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf_mask, "__builtin_ia32_cvtneps2bf16_v8sf_mask", IX86_BUILTIN_CVTNEPS2BF16_V8SF_MASK, UNKNOWN, (int) V8BF_FTYPE_V8SF_V8BF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf_maskz, "__builtin_ia32_cvtneps2bf16_v8sf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V8SF_MASKZ, UNKNOWN, (int) V8BF_FTYPE_V8SF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf, "__builtin_ia32_cvtneps2bf16_v4sf", IX86_BUILTIN_CVTNEPS2BF16_V4SF, UNKNOWN, (int) V8BF_FTYPE_V4SF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf_mask, "__builtin_ia32_cvtneps2bf16_v4sf_mask", IX86_BUILTIN_CVTNEPS2BF16_V4SF_MASK, UNKNOWN, (int) V8BF_FTYPE_V4SF_V8BF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf_maskz, "__builtin_ia32_cvtneps2bf16_v4sf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V4SF_MASKZ, UNKNOWN, (int) V8BF_FTYPE_V4SF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v16sf, "__builtin_ia32_dpbf16ps_v16sf", IX86_BUILTIN_DPBF16PS_V16SF, UNKNOWN, (int) V16SF_FTYPE_V16SF_V32BF_V32BF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v16sf_mask, "__builtin_ia32_dpbf16ps_v16sf_mask", IX86_BUILTIN_DPBF16PS_V16SF_MASK, UNKNOWN, (int) V16SF_FTYPE_V16SF_V32BF_V32BF_UHI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v16sf_maskz, "__builtin_ia32_dpbf16ps_v16sf_maskz", IX86_BUILTIN_DPBF16PS_V16SF_MASKZ, UNKNOWN, (int) V16SF_FTYPE_V16SF_V32BF_V32BF_UHI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v8sf, "__builtin_ia32_dpbf16ps_v8sf", IX86_BUILTIN_DPBF16PS_V8SF, UNKNOWN, (int) V8SF_FTYPE_V8SF_V16BF_V16BF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v8sf_mask, "__builtin_ia32_dpbf16ps_v8sf_mask", IX86_BUILTIN_DPBF16PS_V8SF_MASK, UNKNOWN, (int) V8SF_FTYPE_V8SF_V16BF_V16BF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v8sf_maskz, "__builtin_ia32_dpbf16ps_v8sf_maskz", IX86_BUILTIN_DPBF16PS_V8SF_MASKZ, UNKNOWN, (int) V8SF_FTYPE_V8SF_V16BF_V16BF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf, "__builtin_ia32_dpbf16ps_v4sf", IX86_BUILTIN_DPBF16PS_V4SF, UNKNOWN, (int) V4SF_FTYPE_V4SF_V8BF_V8BF) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf_mask, "__builtin_ia32_dpbf16ps_v4sf_mask", IX86_BUILTIN_DPBF16PS_V4SF_MASK, UNKNOWN, (int) V4SF_FTYPE_V4SF_V8BF_V8BF_UQI) +BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf_maskz, "__builtin_ia32_dpbf16ps_v4sf_maskz", IX86_BUILTIN_DPBF16PS_V4SF_MASKZ, UNKNOWN, (int) V4SF_FTYPE_V4SF_V8BF_V8BF_UQI) /* AVX512FP16. */ BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_addv8hf3_mask, "__builtin_ia32_addph128_mask", IX86_BUILTIN_ADDPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI) diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 5d9e5a1..8e1ef0b 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -10462,9 +10462,9 @@ ix86_expand_args_builtin (const struct builtin_description *d, case V8DF_FTYPE_V2DF: case V8DF_FTYPE_V8DF: case V4DI_FTYPE_V4DI: - case V16HI_FTYPE_V16SF: - case V8HI_FTYPE_V8SF: - case V8HI_FTYPE_V4SF: + case V16BF_FTYPE_V16SF: + case V8BF_FTYPE_V8SF: + case V8BF_FTYPE_V4SF: nargs = 1; break; case V4SF_FTYPE_V4SF_VEC_MERGE: @@ -10592,12 +10592,12 @@ ix86_expand_args_builtin (const struct builtin_description *d, case USI_FTYPE_USI_USI: case UDI_FTYPE_UDI_UDI: case V16SI_FTYPE_V8DF_V8DF: - case V32HI_FTYPE_V16SF_V16SF: - case V16HI_FTYPE_V8SF_V8SF: - case V8HI_FTYPE_V4SF_V4SF: - case V16HI_FTYPE_V16SF_UHI: - case V8HI_FTYPE_V8SF_UQI: - case V8HI_FTYPE_V4SF_UQI: + case V32BF_FTYPE_V16SF_V16SF: + case V16BF_FTYPE_V8SF_V8SF: + case V8BF_FTYPE_V4SF_V4SF: + case V16BF_FTYPE_V16SF_UHI: + case V8BF_FTYPE_V8SF_UQI: + case V8BF_FTYPE_V4SF_UQI: nargs = 2; break; case V2DI_FTYPE_V2DI_INT_CONVERT: @@ -10803,15 +10803,15 @@ ix86_expand_args_builtin (const struct builtin_description *d, case V16HI_FTYPE_V16HI_V16HI_V16HI: case V8SI_FTYPE_V8SI_V8SI_V8SI: case V8HI_FTYPE_V8HI_V8HI_V8HI: - case V32HI_FTYPE_V16SF_V16SF_USI: - case V16HI_FTYPE_V8SF_V8SF_UHI: - case V8HI_FTYPE_V4SF_V4SF_UQI: - case V16HI_FTYPE_V16SF_V16HI_UHI: - case V8HI_FTYPE_V8SF_V8HI_UQI: - case V8HI_FTYPE_V4SF_V8HI_UQI: - case V16SF_FTYPE_V16SF_V32HI_V32HI: - case V8SF_FTYPE_V8SF_V16HI_V16HI: - case V4SF_FTYPE_V4SF_V8HI_V8HI: + case V32BF_FTYPE_V16SF_V16SF_USI: + case V16BF_FTYPE_V8SF_V8SF_UHI: + case V8BF_FTYPE_V4SF_V4SF_UQI: + case V16BF_FTYPE_V16SF_V16BF_UHI: + case V8BF_FTYPE_V8SF_V8BF_UQI: + case V8BF_FTYPE_V4SF_V8BF_UQI: + case V16SF_FTYPE_V16SF_V32BF_V32BF: + case V8SF_FTYPE_V8SF_V16BF_V16BF: + case V4SF_FTYPE_V4SF_V8BF_V8BF: nargs = 3; break; case V32QI_FTYPE_V32QI_V32QI_INT: @@ -10958,9 +10958,9 @@ ix86_expand_args_builtin (const struct builtin_description *d, case V16HI_FTYPE_V32QI_V32QI_V16HI_UHI: case V8SI_FTYPE_V16HI_V16HI_V8SI_UQI: case V4SI_FTYPE_V8HI_V8HI_V4SI_UQI: - case V32HI_FTYPE_V16SF_V16SF_V32HI_USI: - case V16HI_FTYPE_V8SF_V8SF_V16HI_UHI: - case V8HI_FTYPE_V4SF_V4SF_V8HI_UQI: + case V32BF_FTYPE_V16SF_V16SF_V32BF_USI: + case V16BF_FTYPE_V8SF_V8SF_V16BF_UHI: + case V8BF_FTYPE_V4SF_V4SF_V8BF_UQI: nargs = 4; break; case V2DF_FTYPE_V2DF_V2DF_V2DI_INT: @@ -10998,9 +10998,9 @@ ix86_expand_args_builtin (const struct builtin_description *d, break; case UCHAR_FTYPE_UCHAR_UINT_UINT_PUNSIGNED: case UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG: - case V16SF_FTYPE_V16SF_V32HI_V32HI_UHI: - case V8SF_FTYPE_V8SF_V16HI_V16HI_UQI: - case V4SF_FTYPE_V4SF_V8HI_V8HI_UQI: + case V16SF_FTYPE_V16SF_V32BF_V32BF_UHI: + case V8SF_FTYPE_V8SF_V16BF_V16BF_UQI: + case V4SF_FTYPE_V4SF_V8BF_V8BF_UQI: nargs = 4; break; case UQI_FTYPE_V8DI_V8DI_INT_UQI: diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h index ddea249..c62d50f 100644 --- a/gcc/config/i386/immintrin.h +++ b/gcc/config/i386/immintrin.h @@ -118,9 +118,11 @@ #include +#ifdef __SSE2__ #include #include +#endif #include diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index f4b5506..fba81a9 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -187,8 +187,6 @@ UNSPEC_VP2INTERSECT ;; For AVX512BF16 support - UNSPEC_VCVTNE2PS2BF16 - UNSPEC_VCVTNEPS2BF16 UNSPEC_VDPBF16PS ;; For AVX512FP16 suppport @@ -28918,41 +28916,101 @@ "vp2intersectd\t{%2, %1, %0|%0, %1, %2}" [(set_attr ("prefix") ("evex"))]) -(define_mode_iterator BF16 [V32HI (V16HI "TARGET_AVX512VL") (V8HI "TARGET_AVX512VL")]) +(define_mode_iterator VF_AVX512BF16VL + [V32BF (V16BF "TARGET_AVX512VL") (V8BF "TARGET_AVX512VL")]) ;; Converting from BF to SF (define_mode_attr bf16_cvt_2sf - [(V32HI "V16SF") (V16HI "V8SF") (V8HI "V4SF")]) + [(V32BF "V16SF") (V16BF "V8SF") (V8BF "V4SF")]) ;; Converting from SF to BF (define_mode_attr sf_cvt_bf16 - [(V4SF "V8HI") (V8SF "V8HI") (V16SF "V16HI")]) + [(V8SF "V8BF") (V16SF "V16BF")]) ;; Mapping from BF to SF (define_mode_attr sf_bf16 - [(V4SF "V8HI") (V8SF "V16HI") (V16SF "V32HI")]) + [(V4SF "V8BF") (V8SF "V16BF") (V16SF "V32BF")]) (define_expand "avx512f_cvtne2ps2bf16__maskz" - [(match_operand:BF16 0 "register_operand") + [(match_operand:VF_AVX512BF16VL 0 "register_operand") (match_operand: 1 "register_operand") - (match_operand: 2 "register_operand") + (match_operand: 2 "nonimmediate_operand") (match_operand: 3 "register_operand")] "TARGET_AVX512BF16" { - emit_insn (gen_avx512f_cvtne2ps2bf16__mask(operands[0], operands[1], - operands[2], CONST0_RTX(mode), operands[3])); + emit_insn (gen_avx512f_cvtne2ps2bf16__mask(operands[0], operands[2], + operands[1], CONST0_RTX(mode), operands[3])); DONE; }) (define_insn "avx512f_cvtne2ps2bf16_" - [(set (match_operand:BF16 0 "register_operand" "=v") - (unspec:BF16 - [(match_operand: 1 "register_operand" "v") - (match_operand: 2 "register_operand" "v")] - UNSPEC_VCVTNE2PS2BF16))] + [(set (match_operand:VF_AVX512BF16VL 0 "register_operand" "=v") + (vec_concat:VF_AVX512BF16VL + (float_truncate: + (match_operand: 2 "nonimmediate_operand" "vm")) + (float_truncate: + (match_operand: 1 "register_operand" "v"))))] "TARGET_AVX512BF16" "vcvtne2ps2bf16\t{%2, %1, %0|%0, %1, %2}") +(define_expand "avx512f_cvtneps2bf16_v4sf" + [(set (match_operand:V8BF 0 "register_operand") + (vec_concat:V8BF + (float_truncate:V4BF + (match_operand:V4SF 1 "nonimmediate_operand")) + (match_dup 2)))] + "TARGET_AVX512BF16 && TARGET_AVX512VL" + "operands[2] = CONST0_RTX (V4BFmode);") + +(define_insn "*avx512f_cvtneps2bf16_v4sf" + [(set (match_operand:V8BF 0 "register_operand" "=v") + (vec_concat:V8BF + (float_truncate:V4BF + (match_operand:V4SF 1 "nonimmediate_operand" "vm")) + (match_operand:V4BF 2 "const0_operand")))] + "TARGET_AVX512BF16 && TARGET_AVX512VL" + "vcvtneps2bf16{x}\t{%1, %0|%0, %1}") + +(define_expand "avx512f_cvtneps2bf16_v4sf_maskz" + [(match_operand:V8BF 0 "register_operand") + (match_operand:V4SF 1 "nonimmediate_operand") + (match_operand:QI 2 "register_operand")] + "TARGET_AVX512BF16 && TARGET_AVX512VL" +{ + emit_insn (gen_avx512f_cvtneps2bf16_v4sf_mask_1(operands[0], operands[1], + CONST0_RTX(V8BFmode), operands[2], CONST0_RTX(V4BFmode))); + DONE; +}) + +(define_expand "avx512f_cvtneps2bf16_v4sf_mask" + [(match_operand:V8BF 0 "register_operand") + (match_operand:V4SF 1 "nonimmediate_operand") + (match_operand:V8BF 2 "nonimm_or_0_operand") + (match_operand:QI 3 "register_operand")] + "TARGET_AVX512BF16 && TARGET_AVX512VL" +{ + emit_insn (gen_avx512f_cvtneps2bf16_v4sf_mask_1(operands[0], operands[1], + operands[2], operands[3], CONST0_RTX(V4BFmode))); + DONE; +}) + +(define_insn "avx512f_cvtneps2bf16_v4sf_mask_1" + [(set (match_operand:V8BF 0 "register_operand" "=v") + (vec_concat:V8BF + (vec_merge:V4BF + (float_truncate:V4BF + (match_operand:V4SF 1 "nonimmediate_operand" "vm")) + (vec_select:V4BF + (match_operand:V8BF 2 "nonimm_or_0_operand" "0C") + (parallel [(const_int 0) (const_int 1) + (const_int 2) (const_int 3)])) + (match_operand:QI 3 "register_operand" "Yk")) + (match_operand:V4BF 4 "const0_operand")))] + "TARGET_AVX512BF16 && TARGET_AVX512VL" + "vcvtneps2bf16{x}\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}") + +(define_mode_iterator VF1_AVX512_256 [V16SF (V8SF "TARGET_AVX512VL")]) + (define_expand "avx512f_cvtneps2bf16__maskz" [(match_operand: 0 "register_operand") - (match_operand:VF1_AVX512VL 1 "register_operand") + (match_operand:VF1_AVX512_256 1 "nonimmediate_operand") (match_operand: 2 "register_operand")] "TARGET_AVX512BF16" { @@ -28963,11 +29021,10 @@ (define_insn "avx512f_cvtneps2bf16_" [(set (match_operand: 0 "register_operand" "=v") - (unspec: - [(match_operand:VF1_AVX512VL 1 "register_operand" "v")] - UNSPEC_VCVTNEPS2BF16))] + (float_truncate: + (match_operand:VF1_AVX512_256 1 "nonimmediate_operand" "vm")))] "TARGET_AVX512BF16" - "vcvtneps2bf16\t{%1, %0|%0, %1}") + "vcvtneps2bf16\t{%1, %0|%0, %1}") (define_expand "avx512f_dpbf16ps__maskz" [(match_operand:VF1_AVX512VL 0 "register_operand") @@ -28987,7 +29044,7 @@ (unspec:VF1_AVX512VL [(match_operand:VF1_AVX512VL 1 "register_operand" "0") (match_operand: 2 "register_operand" "v") - (match_operand: 3 "register_operand" "v")] + (match_operand: 3 "nonimmediate_operand" "vm")] UNSPEC_VDPBF16PS))] "TARGET_AVX512BF16" "vdpbf16ps\t{%3, %2, %0|%0, %2, %3}") @@ -28998,7 +29055,7 @@ (unspec:VF1_AVX512VL [(match_operand:VF1_AVX512VL 1 "register_operand" "0") (match_operand: 2 "register_operand" "v") - (match_operand: 3 "register_operand" "v")] + (match_operand: 3 "nonimmediate_operand" "vm")] UNSPEC_VDPBF16PS) (match_dup 1) (match_operand: 4 "register_operand" "Yk")))] diff --git a/gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c b/gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c index 831abd3..8e929e6 100644 --- a/gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-mavx512bf16 -O2" } */ -/* { dg-additional-options "-fno-PIE" { target ia32 } } */ +/* { dg-additional-options "-fno-PIE -mfpmath=sse" { target ia32 } } */ /* { dg-final { scan-assembler-times "sall\[ \\t\]+\[^\{\n\]*16" 1 } } */ /* { dg-final { scan-assembler-times "movl" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512bf16-vdpbf16ps-2.c b/gcc/testsuite/gcc.target/i386/avx512bf16-vdpbf16ps-2.c index b64ad7b..02ebdd8 100644 --- a/gcc/testsuite/gcc.target/i386/avx512bf16-vdpbf16ps-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512bf16-vdpbf16ps-2.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-mavx512bf16 -O2" } */ -/* { dg-final { scan-assembler-times "vdpbf16ps\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vdpbf16ps\[ \\t\]+\[^\{\n\]*\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/avx512bf16vl-cvtness2sbh-1.c b/gcc/testsuite/gcc.target/i386/avx512bf16vl-cvtness2sbh-1.c index 8f21b1b..b71addd 100644 --- a/gcc/testsuite/gcc.target/i386/avx512bf16vl-cvtness2sbh-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512bf16vl-cvtness2sbh-1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-mavx512bf16 -mavx512vl -O2" } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c b/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c index 0969ae1..d3a9bdf 100644 --- a/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c @@ -1,11 +1,11 @@ /* { dg-do compile } */ /* { dg-options "-mavx512bf16 -mavx512vl -O2" } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ #include -- cgit v1.1 From 58685b939bb1738d23750fad29035f8055fd4315 Mon Sep 17 00:00:00 2001 From: konglin1 Date: Mon, 31 Oct 2022 14:39:18 +0800 Subject: Support Intel AVX-NE-CONVERT gcc/ChangeLog: * common/config/i386/i386-common.cc (OPTION_MASK_ISA2_AVXNECONVERT_SET, OPTION_MASK_ISA2_AVXNECONVERT_UNSET): New. (ix86_handle_option): Handle -mavxneconvert, unset avxneconvert when avx2 is disabled. * common/config/i386/i386-cpuinfo.h (processor_types): Add FEATURE_AVXNECONVERT. * common/config/i386/i386-isas.h: Add ISA_NAME_TABLE_ENTRY for avxneconvert. * common/config/i386/cpuinfo.h (get_available_features): Detect avxneconvert. * config.gcc: Add avxneconvertintrin.h * config/i386/avxneconvertintrin.h: New. * config/i386/avx512bf16vlintrin.h (_mm256_cvtneps_pbh): Unified builtin with avxneconvert. (_mm_cvtneps_pbh): Ditto. * config/i386/cpuid.h (bit_AVXNECONVERT): New. * config/i386/i386-builtin-types.def: Add DEF_POINTER_TYPE (PCV8HF, V8HF, CONST), DEF_POINTER_TYPE (PCV8BF, V8BF, CONST), DEF_POINTER_TYPE (PCV16HF, V16HF, CONST), DEF_POINTER_TYPE (PCV16BF, V16BF, CONST), DEF_FUNCTION_TYPE (V4SF, PCBFLOAT16), DEF_FUNCTION_TYPE (V4SF, PCFLOAT16), DEF_FUNCTION_TYPE (V8SF, PCBFLOAT16), DEF_FUNCTION_TYPE (V8SF, PCFLOAT16), DEF_FUNCTION_TYPE (V4SF, PCV8BF), DEF_FUNCTION_TYPE (V4SF, PCV8HF), DEF_FUNCTION_TYPE (V8SF, PCV16HF), DEF_FUNCTION_TYPE (V8SF, PCV16BF), * config/i386/i386-builtin.def: Add new builtins. * config/i386/i386-c.cc (ix86_target_macros_internal): Define __AVXNECONVERT__. * config/i386/i386-expand.cc (ix86_expand_special_args_builtin): Handle V4SF_FTYPE_PCBFLOAT16,V8SF_FTYPE_PCBFLOAT16, V4SF_FTYPE_PCFLOAT16, V8SF_FTYPE_PCFLOAT16,V4SF_FTYPE_PCV8BF, V4SF_FTYPE_PCV8HF,V8SF_FTYPE_PCV16BF,V8SF_FTYPE_PCV16HF. * config/i386/i386-isa.def : Add DEF_PTA(AVXNECONVERT) New. * config/i386/i386-options.cc (isa2_opts): Add -mavxneconvert. (ix86_valid_target_attribute_inner_p): Handle avxneconvert. * config/i386/i386.md: Add attr avx512bf16vl and avxneconvert. * config/i386/i386.opt: Add option -mavxneconvert. * config/i386/immintrin.h: Inculde avxneconvertintrin.h. * config/i386/sse.md (vbcstnebf162ps_): New define_insn. (vbcstnesh2ps_): Ditto. (vcvtnee2ps_):Ditto. (vcvtneo2ps_):Ditto. (vcvtneps2bf16_v4sf): Ditto. (*vcvtneps2bf16_v4sf): Ditto. (vcvtneps2bf16_v8sf): Ditto. * doc/invoke.texi: Document -mavxneconvert. * doc/extend.texi: Document avxneconvert. * doc/sourcebuild.texi: Document target avxneconvert. gcc/testsuite/ChangeLog: * gcc.target/i386/avx-check.h: Add avxneconvert check. * gcc.target/i386/funcspec-56.inc: Add new target attribute. * gcc.target/i386/sse-12.c: Add -mavxneconvert. * gcc.target/i386/sse-13.c: Ditto. * gcc.target/i386/sse-14.c: Ditto. * gcc.target/i386/sse-22.c: Ditto. * gcc.target/i386/sse-23.c: Ditto. * g++.dg/other/i386-2.C: Ditto. * g++.dg/other/i386-3.C: Ditto. * lib/target-supports.exp:add check_effective_target_avxneconvert. * gcc.target/i386/avx-ne-convert-1.c: New test. * gcc.target/i386/avx-ne-convert-vbcstnebf162ps-2.c: Ditto. * gcc.target/i386/avx-ne-convert-vbcstnesh2ps-2.c: Ditto. * gcc.target/i386/avx-ne-convert-vcvtneebf162ps-2.c: Ditto. * gcc.target/i386/avx-ne-convert-vcvtneeph2ps-2.c: Ditto. * gcc.target/i386/avx-ne-convert-vcvtneobf162ps-2.c: Ditto. * gcc.target/i386/avx-ne-convert-vcvtneoph2ps-2.c: Ditto. * gcc.target/i386/avx-ne-convert-vcvtneps2bf16-2.c: Ditto. * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c: Rename.. * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1a.c: To this. * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1b.c: New test. --- gcc/common/config/i386/cpuinfo.h | 2 + gcc/common/config/i386/i386-common.cc | 21 +++- gcc/common/config/i386/i386-cpuinfo.h | 1 + gcc/common/config/i386/i386-isas.h | 2 + gcc/config.gcc | 2 +- gcc/config/i386/avx512bf16vlintrin.h | 19 +-- gcc/config/i386/avxneconvertintrin.h | 140 +++++++++++++++++++++ gcc/config/i386/cpuid.h | 1 + gcc/config/i386/i386-builtin-types.def | 15 +++ gcc/config/i386/i386-builtin.def | 18 ++- gcc/config/i386/i386-c.cc | 2 + gcc/config/i386/i386-expand.cc | 21 ++++ gcc/config/i386/i386-isa.def | 1 + gcc/config/i386/i386-options.cc | 4 +- gcc/config/i386/i386.md | 5 +- gcc/config/i386/i386.opt | 5 + gcc/config/i386/immintrin.h | 2 + gcc/config/i386/sse.md | 108 ++++++++++++++-- gcc/doc/extend.texi | 5 + gcc/doc/invoke.texi | 9 +- gcc/doc/sourcebuild.texi | 3 + gcc/testsuite/g++.dg/other/i386-2.C | 2 +- gcc/testsuite/g++.dg/other/i386-3.C | 2 +- gcc/testsuite/gcc.target/i386/avx-check.h | 3 + gcc/testsuite/gcc.target/i386/avx-ne-convert-1.c | 45 +++++++ .../i386/avx-ne-convert-vbcstnebf162ps-2.c | 54 ++++++++ .../i386/avx-ne-convert-vbcstnesh2ps-2.c | 42 +++++++ .../i386/avx-ne-convert-vcvtneebf162ps-2.c | 73 +++++++++++ .../i386/avx-ne-convert-vcvtneeph2ps-2.c | 66 ++++++++++ .../i386/avx-ne-convert-vcvtneobf162ps-2.c | 75 +++++++++++ .../i386/avx-ne-convert-vcvtneoph2ps-2.c | 66 ++++++++++ .../i386/avx-ne-convert-vcvtneps2bf16-2.c | 58 +++++++++ .../gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c | 27 ---- .../i386/avx512bf16vl-vcvtneps2bf16-1a.c | 27 ++++ .../i386/avx512bf16vl-vcvtneps2bf16-1b.c | 27 ++++ gcc/testsuite/gcc.target/i386/funcspec-56.inc | 2 + gcc/testsuite/gcc.target/i386/sse-12.c | 2 +- gcc/testsuite/gcc.target/i386/sse-13.c | 2 +- gcc/testsuite/gcc.target/i386/sse-14.c | 2 +- gcc/testsuite/gcc.target/i386/sse-22.c | 4 +- gcc/testsuite/gcc.target/i386/sse-23.c | 2 +- gcc/testsuite/lib/target-supports.exp | 12 ++ 42 files changed, 914 insertions(+), 65 deletions(-) create mode 100644 gcc/config/i386/avxneconvertintrin.h create mode 100644 gcc/testsuite/gcc.target/i386/avx-ne-convert-1.c create mode 100644 gcc/testsuite/gcc.target/i386/avx-ne-convert-vbcstnebf162ps-2.c create mode 100644 gcc/testsuite/gcc.target/i386/avx-ne-convert-vbcstnesh2ps-2.c create mode 100644 gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneebf162ps-2.c create mode 100644 gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneeph2ps-2.c create mode 100644 gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneobf162ps-2.c create mode 100644 gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneoph2ps-2.c create mode 100644 gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneps2bf16-2.c delete mode 100644 gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c create mode 100644 gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1b.c (limited to 'gcc') diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h index 19ea713..62c3d1b 100644 --- a/gcc/common/config/i386/cpuinfo.h +++ b/gcc/common/config/i386/cpuinfo.h @@ -839,6 +839,8 @@ get_available_features (struct __processor_model *cpu_model, set_feature (FEATURE_AVXIFMA); if (edx & bit_AVXVNNIINT8) set_feature (FEATURE_AVXVNNIINT8); + if (edx & bit_AVXNECONVERT) + set_feature (FEATURE_AVXNECONVERT); } if (avx512_usable) { diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc index f66bdd5..cd6ad2c 100644 --- a/gcc/common/config/i386/i386-common.cc +++ b/gcc/common/config/i386/i386-common.cc @@ -109,6 +109,7 @@ along with GCC; see the file COPYING3. If not see #define OPTION_MASK_ISA2_AMX_INT8_SET OPTION_MASK_ISA2_AMX_INT8 #define OPTION_MASK_ISA2_AMX_BF16_SET OPTION_MASK_ISA2_AMX_BF16 #define OPTION_MASK_ISA2_AVXVNNIINT8_SET OPTION_MASK_ISA2_AVXVNNIINT8 +#define OPTION_MASK_ISA2_AVXNECONVERT_SET OPTION_MASK_ISA2_AVXNECONVERT /* SSE4 includes both SSE4.1 and SSE4.2. -msse4 should be the same as -msse4.2. */ @@ -215,7 +216,8 @@ along with GCC; see the file COPYING3. If not see (OPTION_MASK_ISA_AVX2 | OPTION_MASK_ISA_AVX512F_UNSET) #define OPTION_MASK_ISA2_AVX2_UNSET \ (OPTION_MASK_ISA2_AVXIFMA_UNSET | OPTION_MASK_ISA2_AVXVNNI_UNSET \ - | OPTION_MASK_ISA2_AVXVNNIINT8_UNSET | OPTION_MASK_ISA2_AVX512F_UNSET) + | OPTION_MASK_ISA2_AVXVNNIINT8_UNSET | OPTION_MASK_ISA2_AVXNECONVERT_UNSET \ + | OPTION_MASK_ISA2_AVX512F_UNSET) #define OPTION_MASK_ISA_AVX512F_UNSET \ (OPTION_MASK_ISA_AVX512F | OPTION_MASK_ISA_AVX512CD_UNSET \ | OPTION_MASK_ISA_AVX512PF_UNSET | OPTION_MASK_ISA_AVX512ER_UNSET \ @@ -280,6 +282,7 @@ along with GCC; see the file COPYING3. If not see (OPTION_MASK_ISA2_KL | OPTION_MASK_ISA2_WIDEKL_UNSET) #define OPTION_MASK_ISA2_WIDEKL_UNSET OPTION_MASK_ISA2_WIDEKL #define OPTION_MASK_ISA2_AVXVNNIINT8_UNSET OPTION_MASK_ISA2_AVXVNNIINT8 +#define OPTION_MASK_ISA2_AVXNECONVERT_UNSET OPTION_MASK_ISA2_AVXNECONVERT /* SSE4 includes both SSE4.1 and SSE4.2. -mno-sse4 should the same as -mno-sse4.1. */ @@ -1162,6 +1165,22 @@ ix86_handle_option (struct gcc_options *opts, } return true; + case OPT_mavxneconvert: + if (value) + { + opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AVXNECONVERT_SET; + opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVXNECONVERT_SET; + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX2_SET; + opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX2_SET; + } + else + { + opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVXNECONVERT_UNSET; + opts->x_ix86_isa_flags2_explicit + |= OPTION_MASK_ISA2_AVXNECONVERT_UNSET; + } + return true; + case OPT_mfma: if (value) { diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h index 761af27..4fbbfa5 100644 --- a/gcc/common/config/i386/i386-cpuinfo.h +++ b/gcc/common/config/i386/i386-cpuinfo.h @@ -245,6 +245,7 @@ enum processor_features FEATURE_X86_64_V4, FEATURE_AVXIFMA, FEATURE_AVXVNNIINT8, + FEATURE_AVXNECONVERT, CPU_FEATURE_MAX }; diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h index 8c1f351..bceaee5 100644 --- a/gcc/common/config/i386/i386-isas.h +++ b/gcc/common/config/i386/i386-isas.h @@ -178,4 +178,6 @@ ISA_NAMES_TABLE_START ISA_NAMES_TABLE_ENTRY("avxifma", FEATURE_AVXIFMA, P_NONE, "-mavxifma") ISA_NAMES_TABLE_ENTRY("avxvnniint8", FEATURE_AVXVNNIINT8, P_NONE, "-mavxvnniint8") + ISA_NAMES_TABLE_ENTRY("avxneconvert", FEATURE_AVXNECONVERT, + P_NONE, "-mavxneconvert") ISA_NAMES_TABLE_END diff --git a/gcc/config.gcc b/gcc/config.gcc index ac1c08f..c2f8aab 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -422,7 +422,7 @@ i[34567]86-*-* | x86_64-*-*) amxbf16intrin.h x86gprintrin.h uintrintrin.h hresetintrin.h keylockerintrin.h avxvnniintrin.h mwaitintrin.h avx512fp16intrin.h avx512fp16vlintrin.h - avxifmaintrin.h avxvnniint8intrin.h" + avxifmaintrin.h avxvnniint8intrin.h avxneconvertintrin.h" ;; ia64-*-*) extra_headers=ia64intrin.h diff --git a/gcc/config/i386/avx512bf16vlintrin.h b/gcc/config/i386/avx512bf16vlintrin.h index 56c28f1..e706903 100644 --- a/gcc/config/i386/avx512bf16vlintrin.h +++ b/gcc/config/i386/avx512bf16vlintrin.h @@ -45,6 +45,11 @@ typedef __bf16 __m128bh __attribute__ ((__vector_size__ (16), __may_alias__)); typedef __bf16 __bfloat16; +#define _mm256_cvtneps_pbh(A) \ + (__m128bh) __builtin_ia32_cvtneps2bf16_v8sf (A) +#define _mm_cvtneps_pbh(A) \ + (__m128bh) __builtin_ia32_cvtneps2bf16_v4sf (A) + /* vcvtne2ps2bf16 */ extern __inline __m256bh @@ -93,13 +98,6 @@ _mm_maskz_cvtne2ps_pbh (__mmask8 __A, __m128 __B, __m128 __C) extern __inline __m128bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm256_cvtneps_pbh (__m256 __A) -{ - return (__m128bh)__builtin_ia32_cvtneps2bf16_v8sf(__A); -} - -extern __inline __m128bh -__attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm256_mask_cvtneps_pbh (__m128bh __A, __mmask8 __B, __m256 __C) { return (__m128bh)__builtin_ia32_cvtneps2bf16_v8sf_mask(__C, __A, __B); @@ -114,13 +112,6 @@ _mm256_maskz_cvtneps_pbh (__mmask8 __A, __m256 __B) extern __inline __m128bh __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm_cvtneps_pbh (__m128 __A) -{ - return (__m128bh)__builtin_ia32_cvtneps2bf16_v4sf(__A); -} - -extern __inline __m128bh -__attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_mask_cvtneps_pbh (__m128bh __A, __mmask8 __B, __m128 __C) { return (__m128bh)__builtin_ia32_cvtneps2bf16_v4sf_mask(__C, __A, __B); diff --git a/gcc/config/i386/avxneconvertintrin.h b/gcc/config/i386/avxneconvertintrin.h new file mode 100644 index 0000000..916f00a --- /dev/null +++ b/gcc/config/i386/avxneconvertintrin.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2021 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 _IMMINTRIN_H_INCLUDED +#error "Never use directly; include instead." +#endif + +#ifndef _AVXNECONVERTINTRIN_H_INCLUDED +#define _AVXNECONVERTINTRIN_H_INCLUDED + +#ifndef __AVXNECONVERT__ +#pragma GCC push_options +#pragma GCC target ("avxneconvert") +#define __DISABLE_AVXNECONVERT__ +#endif /* __AVXNECONVERT__ */ + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bcstnebf16_ps (const void *__P) +{ + return (__m128) __builtin_ia32_vbcstnebf162ps128 ((const __bf16 *) __P); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bcstnebf16_ps (const void *__P) +{ + return (__m256) __builtin_ia32_vbcstnebf162ps256 ((const __bf16 *) __P); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bcstnesh_ps (const void *__P) +{ + return (__m128) __builtin_ia32_vbcstnesh2ps128 ((const _Float16 *) __P); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bcstnesh_ps (const void *__P) +{ + return (__m256) __builtin_ia32_vbcstnesh2ps256 ((const _Float16 *) __P); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneebf16_ps (const __m128bh *__A) +{ + return (__m128) __builtin_ia32_vcvtneebf162ps128 ((const __v8bf *) __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneebf16_ps (const __m256bh *__A) +{ + return (__m256) __builtin_ia32_vcvtneebf162ps256 ((const __v16bf *) __A); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneeph_ps (const __m128h *__A) +{ + return (__m128) __builtin_ia32_vcvtneeph2ps128 ((const __v8hf *) __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneeph_ps (const __m256h *__A) +{ + return (__m256) __builtin_ia32_vcvtneeph2ps256 ((const __v16hf *) __A); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneobf16_ps (const __m128bh *__A) +{ + return (__m128) __builtin_ia32_vcvtneobf162ps128 ((const __v8bf *) __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneobf16_ps (const __m256bh *__A) +{ + return (__m256) __builtin_ia32_vcvtneobf162ps256 ((const __v16bf *) __A); +} + +extern __inline __m128 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneoph_ps (const __m128h *__A) +{ + return (__m128) __builtin_ia32_vcvtneoph2ps128 ((const __v8hf *) __A); +} + +extern __inline __m256 +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneoph_ps (const __m256h *__A) +{ + return (__m256) __builtin_ia32_vcvtneoph2ps256 ((const __v16hf *) __A); +} + +extern __inline __m128bh +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_cvtneps_avx_pbh (__m128 __A) +{ + return (__m128bh) __builtin_ia32_cvtneps2bf16_v4sf (__A); +} + +extern __inline __m128bh +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_cvtneps_avx_pbh (__m256 __A) +{ + return (__m128bh) __builtin_ia32_cvtneps2bf16_v8sf (__A); +} + +#ifdef __DISABLE_AVXNECONVERT__ +#undef __DISABLE_AVXNECONVERT__ +#pragma GCC pop_options +#endif /* __DISABLE_AVXNECONVERT__ */ + +#endif /* _AVXNECONVERTINTRIN_H_INCLUDED */ diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h index f5fad22..18bbc0c 100644 --- a/gcc/config/i386/cpuid.h +++ b/gcc/config/i386/cpuid.h @@ -50,6 +50,7 @@ /* %edx */ #define bit_AVXVNNIINT8 (1 << 4) +#define bit_AVXNECONVERT (1 << 5) #define bit_CMPXCHG8B (1 << 8) #define bit_CMOV (1 << 15) #define bit_MMX (1 << 23) diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def index aedae2d..abbb50b 100644 --- a/gcc/config/i386/i386-builtin-types.def +++ b/gcc/config/i386/i386-builtin-types.def @@ -139,6 +139,7 @@ DEF_POINTER_TYPE (PVOID, VOID) DEF_POINTER_TYPE (PDOUBLE, DOUBLE) DEF_POINTER_TYPE (PFLOAT, FLOAT) DEF_POINTER_TYPE (PCFLOAT16, FLOAT16, CONST) +DEF_POINTER_TYPE (PCBFLOAT16, BFLOAT16, CONST) DEF_POINTER_TYPE (PSHORT, SHORT) DEF_POINTER_TYPE (PUSHORT, USHORT) DEF_POINTER_TYPE (PINT, INT) @@ -182,6 +183,10 @@ DEF_POINTER_TYPE (PCV4DF, V4DF, CONST) DEF_POINTER_TYPE (PCV4SF, V4SF, CONST) DEF_POINTER_TYPE (PCV8DF, V8DF, CONST) DEF_POINTER_TYPE (PCV8SF, V8SF, CONST) +DEF_POINTER_TYPE (PCV8HF, V8HF, CONST) +DEF_POINTER_TYPE (PCV8BF, V8BF, CONST) +DEF_POINTER_TYPE (PCV16HF, V16HF, CONST) +DEF_POINTER_TYPE (PCV16BF, V16BF, CONST) DEF_POINTER_TYPE (PCV16SF, V16SF, CONST) DEF_POINTER_TYPE (PCV2DI, V2DI, CONST) @@ -1392,3 +1397,13 @@ DEF_FUNCTION_TYPE (V32HF, V32HF) DEF_FUNCTION_TYPE_ALIAS (V8HF_FTYPE_V8HF, ROUND) DEF_FUNCTION_TYPE_ALIAS (V16HF_FTYPE_V16HF, ROUND) DEF_FUNCTION_TYPE_ALIAS (V32HF_FTYPE_V32HF, ROUND) + +# AVXNECONVERT builtins +DEF_FUNCTION_TYPE (V4SF, PCBFLOAT16) +DEF_FUNCTION_TYPE (V8SF, PCBFLOAT16) +DEF_FUNCTION_TYPE (V4SF, PCFLOAT16) +DEF_FUNCTION_TYPE (V8SF, PCFLOAT16) +DEF_FUNCTION_TYPE (V4SF, PCV8HF) +DEF_FUNCTION_TYPE (V8SF, PCV16HF) +DEF_FUNCTION_TYPE (V4SF, PCV8BF) +DEF_FUNCTION_TYPE (V8SF, PCV16BF) diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def index 5802e20..9345b8c 100644 --- a/gcc/config/i386/i386-builtin.def +++ b/gcc/config/i386/i386-builtin.def @@ -274,6 +274,20 @@ BDESC (OPTION_MASK_ISA_RTM, 0, CODE_FOR_xbegin, "__builtin_ia32_xbegin", IX86_BU BDESC (OPTION_MASK_ISA_RTM, 0, CODE_FOR_xend, "__builtin_ia32_xend", IX86_BUILTIN_XEND, UNKNOWN, (int) VOID_FTYPE_VOID) BDESC (OPTION_MASK_ISA_RTM, 0, CODE_FOR_xtest, "__builtin_ia32_xtest", IX86_BUILTIN_XTEST, UNKNOWN, (int) INT_FTYPE_VOID) +/* AVX-NE-CONVERT */ +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vbcstnebf162ps_v4sf, "__builtin_ia32_vbcstnebf162ps128", IX86_BUILTIN_VBCSTNEBF162PS128, UNKNOWN, (int) V4SF_FTYPE_PCBFLOAT16) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vbcstnebf162ps_v8sf, "__builtin_ia32_vbcstnebf162ps256", IX86_BUILTIN_VBCSTNEBF162PS256, UNKNOWN, (int) V8SF_FTYPE_PCBFLOAT16) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vbcstnesh2ps_v4sf, "__builtin_ia32_vbcstnesh2ps128", IX86_BUILTIN_VBCSTNESH2PS128, UNKNOWN, (int) V4SF_FTYPE_PCFLOAT16) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vbcstnesh2ps_v8sf, "__builtin_ia32_vbcstnesh2ps256", IX86_BUILTIN_VBCSTNESH2PS256, UNKNOWN, (int) V8SF_FTYPE_PCFLOAT16) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vcvtneebf162ps_v8bf, "__builtin_ia32_vcvtneebf162ps128", IX86_BUILTIN_VCVTNEEBF162PS128, UNKNOWN, (int) V4SF_FTYPE_PCV8BF) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vcvtneebf162ps_v16bf, "__builtin_ia32_vcvtneebf162ps256", IX86_BUILTIN_VCVTNEEBF162PS256, UNKNOWN, (int) V8SF_FTYPE_PCV16BF) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vcvtneeph2ps_v8hf, "__builtin_ia32_vcvtneeph2ps128", IX86_BUILTIN_VCVTNEEPH2PS128, UNKNOWN, (int) V4SF_FTYPE_PCV8HF) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vcvtneeph2ps_v16hf, "__builtin_ia32_vcvtneeph2ps256", IX86_BUILTIN_VCVTNEEPH2PS256, UNKNOWN, (int) V8SF_FTYPE_PCV16HF) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vcvtneobf162ps_v8bf, "__builtin_ia32_vcvtneobf162ps128", IX86_BUILTIN_VCVTNEOBF162PS128, UNKNOWN, (int) V4SF_FTYPE_PCV8BF) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vcvtneobf162ps_v16bf, "__builtin_ia32_vcvtneobf162ps256", IX86_BUILTIN_VCVTNEOBF162PS256, UNKNOWN, (int) V8SF_FTYPE_PCV16BF) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vcvtneoph2ps_v8hf, "__builtin_ia32_vcvtneoph2ps128", IX86_BUILTIN_VCVTNEOPH2PS128, UNKNOWN, (int) V4SF_FTYPE_PCV8HF) +BDESC (0, OPTION_MASK_ISA2_AVXNECONVERT, CODE_FOR_vcvtneoph2ps_v16hf, "__builtin_ia32_vcvtneoph2ps256", IX86_BUILTIN_VCVTNEOPH2PS256, UNKNOWN, (int) V8SF_FTYPE_PCV16HF) + /* AVX512BW */ BDESC (OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_avx512bw_loadv32hi_mask, "__builtin_ia32_loaddquhi512_mask", IX86_BUILTIN_LOADDQUHI512_MASK, UNKNOWN, (int) V32HI_FTYPE_PCSHORT_V32HI_USI) BDESC (OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_avx512bw_loadv64qi_mask, "__builtin_ia32_loaddquqi512_mask", IX86_BUILTIN_LOADDQUQI512_MASK, UNKNOWN, (int) V64QI_FTYPE_PCCHAR_V64QI_UDI) @@ -2791,10 +2805,10 @@ BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtne2ps2bf16_v8bf_maskz BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf, "__builtin_ia32_cvtneps2bf16_v16sf", IX86_BUILTIN_CVTNEPS2BF16_V16SF, UNKNOWN, (int) V16BF_FTYPE_V16SF) BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf_mask, "__builtin_ia32_cvtneps2bf16_v16sf_mask", IX86_BUILTIN_CVTNEPS2BF16_V16SF_MASK, UNKNOWN, (int) V16BF_FTYPE_V16SF_V16BF_UHI) BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v16sf_maskz, "__builtin_ia32_cvtneps2bf16_v16sf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V16SF_MASKZ, UNKNOWN, (int) V16BF_FTYPE_V16SF_UHI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf, "__builtin_ia32_cvtneps2bf16_v8sf", IX86_BUILTIN_CVTNEPS2BF16_V8SF, UNKNOWN, (int) V8BF_FTYPE_V8SF) +BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXNECONVERT | OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_vcvtneps2bf16_v8sf, "__builtin_ia32_cvtneps2bf16_v8sf", IX86_BUILTIN_CVTNEPS2BF16_V8SF, UNKNOWN, (int) V8BF_FTYPE_V8SF) BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf_mask, "__builtin_ia32_cvtneps2bf16_v8sf_mask", IX86_BUILTIN_CVTNEPS2BF16_V8SF_MASK, UNKNOWN, (int) V8BF_FTYPE_V8SF_V8BF_UQI) BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v8sf_maskz, "__builtin_ia32_cvtneps2bf16_v8sf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V8SF_MASKZ, UNKNOWN, (int) V8BF_FTYPE_V8SF_UQI) -BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf, "__builtin_ia32_cvtneps2bf16_v4sf", IX86_BUILTIN_CVTNEPS2BF16_V4SF, UNKNOWN, (int) V8BF_FTYPE_V4SF) +BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXNECONVERT | OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_vcvtneps2bf16_v4sf, "__builtin_ia32_cvtneps2bf16_v4sf", IX86_BUILTIN_CVTNEPS2BF16_V4SF, UNKNOWN, (int) V8BF_FTYPE_V4SF) BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf_mask, "__builtin_ia32_cvtneps2bf16_v4sf_mask", IX86_BUILTIN_CVTNEPS2BF16_V4SF_MASK, UNKNOWN, (int) V8BF_FTYPE_V4SF_V8BF_UQI) BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_cvtneps2bf16_v4sf_maskz, "__builtin_ia32_cvtneps2bf16_v4sf_maskz", IX86_BUILTIN_CVTNE2PS2BF16_V4SF_MASKZ, UNKNOWN, (int) V8BF_FTYPE_V4SF_UQI) BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v16sf, "__builtin_ia32_dpbf16ps_v16sf", IX86_BUILTIN_DPBF16PS_V16SF, UNKNOWN, (int) V16SF_FTYPE_V16SF_V32BF_V32BF) diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc index f70f891..fa195e7 100644 --- a/gcc/config/i386/i386-c.cc +++ b/gcc/config/i386/i386-c.cc @@ -644,6 +644,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag, def_or_undef (parse_in, "__AVXIFMA__"); if (isa_flag2 & OPTION_MASK_ISA2_AVXVNNIINT8) def_or_undef (parse_in, "__AVXVNNIINT8__"); + if (isa_flag2 & OPTION_MASK_ISA2_AVXNECONVERT) + def_or_undef (parse_in, "__AVXNECONVERT__"); if (TARGET_IAMCU) { def_or_undef (parse_in, "__iamcu"); diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 8e1ef0b..7d17bfe 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -11897,6 +11897,14 @@ ix86_expand_special_args_builtin (const struct builtin_description *d, case V8SF_FTYPE_PCV4SF: case V8SF_FTYPE_PCFLOAT: case V4SF_FTYPE_PCFLOAT: + case V4SF_FTYPE_PCFLOAT16: + case V4SF_FTYPE_PCBFLOAT16: + case V4SF_FTYPE_PCV8BF: + case V4SF_FTYPE_PCV8HF: + case V8SF_FTYPE_PCFLOAT16: + case V8SF_FTYPE_PCBFLOAT16: + case V8SF_FTYPE_PCV16HF: + case V8SF_FTYPE_PCV16BF: case V4DF_FTYPE_PCV2DF: case V4DF_FTYPE_PCDOUBLE: case V2DF_FTYPE_PCDOUBLE: @@ -12406,6 +12414,8 @@ ix86_check_builtin_isa_match (unsigned int fcode, OPTION_MASK_ISA2_AVXVNNI (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512IFMA) or OPTION_MASK_ISA2_AVXIFMA + (OPTION_MASK_ISA_AVXNECONVERT | OPTION_MASK_ISA2_AVX512BF16) or + OPTION_MASK_ISA2_AVXNECONVERT where for each such pair it is sufficient if either of the ISAs is enabled, plus if it is ored with other options also those others. OPTION_MASK_ISA_MMX in bisa is satisfied also if TARGET_MMX_WITH_SSE. */ @@ -12446,6 +12456,17 @@ ix86_check_builtin_isa_match (unsigned int fcode, isa2 |= OPTION_MASK_ISA2_AVXIFMA; } + if ((((bisa & OPTION_MASK_ISA_AVX512VL) != 0 + && (bisa2 & OPTION_MASK_ISA2_AVX512BF16) != 0) + && (bisa2 & OPTION_MASK_ISA2_AVXNECONVERT) != 0) + && (((isa & OPTION_MASK_ISA_AVX512VL) != 0 + && (isa2 & OPTION_MASK_ISA2_AVX512BF16) != 0) + || (isa2 & OPTION_MASK_ISA2_AVXNECONVERT) != 0)) + { + isa |= OPTION_MASK_ISA_AVX512VL; + isa2 |= OPTION_MASK_ISA2_AVXNECONVERT | OPTION_MASK_ISA2_AVX512BF16; + } + if ((bisa & OPTION_MASK_ISA_MMX) && !TARGET_MMX && TARGET_MMX_WITH_SSE /* __builtin_ia32_maskmovq requires MMX registers. */ && fcode != IX86_BUILTIN_MASKMOVQ) diff --git a/gcc/config/i386/i386-isa.def b/gcc/config/i386/i386-isa.def index c95b917..4ea3f96 100644 --- a/gcc/config/i386/i386-isa.def +++ b/gcc/config/i386/i386-isa.def @@ -111,3 +111,4 @@ DEF_PTA(AVXVNNI) DEF_PTA(AVX512FP16) DEF_PTA(AVXIFMA) DEF_PTA(AVXVNNIINT8) +DEF_PTA(AVXNECONVERT) diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index 1f14d69..ef9c888 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -229,7 +229,8 @@ static struct ix86_target_opts isa2_opts[] = { "-mavxvnni", OPTION_MASK_ISA2_AVXVNNI }, { "-mavx512fp16", OPTION_MASK_ISA2_AVX512FP16 }, { "-mavxifma", OPTION_MASK_ISA2_AVXIFMA }, - { "-mavxvnniint8", OPTION_MASK_ISA2_AVXVNNIINT8 } + { "-mavxvnniint8", OPTION_MASK_ISA2_AVXVNNIINT8 }, + { "-mavxneconvert", OPTION_MASK_ISA2_AVXNECONVERT } }; static struct ix86_target_opts isa_opts[] = { @@ -1078,6 +1079,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], IX86_ATTR_ISA ("avx512fp16", OPT_mavx512fp16), IX86_ATTR_ISA ("avxifma", OPT_mavxifma), IX86_ATTR_ISA ("avxvnniint8", OPT_mavxvnniint8), + IX86_ATTR_ISA ("avxneconvert", OPT_mavxneconvert), /* enum options */ IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_), diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 8081df7..f28c2a1 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -837,7 +837,7 @@ avx,noavx,avx2,noavx2,bmi,bmi2,fma4,fma,avx512f,noavx512f, avx512bw,noavx512bw,avx512dq,noavx512dq,fma_or_avx512vl, avx512vl,noavx512vl,avxvnni,avx512vnnivl,avx512fp16,avxifma, - avx512ifmavl" + avx512ifmavl,avxneconvert,avx512bf16vl" (const_string "base")) ;; Define instruction set of MMX instructions @@ -896,6 +896,9 @@ (eq_attr "isa" "avxifma") (symbol_ref "TARGET_AVXIFMA") (eq_attr "isa" "avx512ifmavl") (symbol_ref "TARGET_AVX512IFMA && TARGET_AVX512VL") + (eq_attr "isa" "avxneconvert") (symbol_ref "TARGET_AVXNECONVERT") + (eq_attr "isa" "avx512bf16vl") + (symbol_ref "TARGET_AVX512BF16 && TARGET_AVX512VL") (eq_attr "mmx_isa" "native") (symbol_ref "!TARGET_MMX_WITH_SSE") diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 53d534f..6e07b89 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -1224,3 +1224,8 @@ mavxvnniint8 Target Mask(ISA2_AVXVNNIINT8) Var(ix86_isa_flags2) Save Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVXVNNIINT8 built-in functions and code generation. + +mavxneconvert +Target Mask(ISA2_AVXNECONVERT) Var(ix86_isa_flags2) Save +Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, and +AVXNECONVERT build-in functions and code generation. diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h index c62d50f..8629aba 100644 --- a/gcc/config/i386/immintrin.h +++ b/gcc/config/i386/immintrin.h @@ -122,6 +122,8 @@ #include #include + +#include #endif #include diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index fba81a9..3df9e07 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -28950,23 +28950,27 @@ "TARGET_AVX512BF16" "vcvtne2ps2bf16\t{%2, %1, %0|%0, %1, %2}") -(define_expand "avx512f_cvtneps2bf16_v4sf" +(define_expand "vcvtneps2bf16_v4sf" [(set (match_operand:V8BF 0 "register_operand") (vec_concat:V8BF (float_truncate:V4BF (match_operand:V4SF 1 "nonimmediate_operand")) (match_dup 2)))] - "TARGET_AVX512BF16 && TARGET_AVX512VL" + "TARGET_AVXNECONVERT || (TARGET_AVX512BF16 && TARGET_AVX512VL)" "operands[2] = CONST0_RTX (V4BFmode);") -(define_insn "*avx512f_cvtneps2bf16_v4sf" - [(set (match_operand:V8BF 0 "register_operand" "=v") +(define_insn "*vcvtneps2bf16_v4sf" + [(set (match_operand:V8BF 0 "register_operand" "=x,v") (vec_concat:V8BF (float_truncate:V4BF - (match_operand:V4SF 1 "nonimmediate_operand" "vm")) + (match_operand:V4SF 1 "nonimmediate_operand" "xm,vm")) (match_operand:V4BF 2 "const0_operand")))] - "TARGET_AVX512BF16 && TARGET_AVX512VL" - "vcvtneps2bf16{x}\t{%1, %0|%0, %1}") + "TARGET_AVXNECONVERT || (TARGET_AVX512BF16 && TARGET_AVX512VL)" + "@ + %{vex%} vcvtneps2bf16{x}\t{%1, %0|%0, %1} + vcvtneps2bf16{x}\t{%1, %0|%0, %1}" + [(set_attr "isa" "avxneconvert,avx512bf16vl") + (set_attr "prefix" "vex,evex")]) (define_expand "avx512f_cvtneps2bf16_v4sf_maskz" [(match_operand:V8BF 0 "register_operand") @@ -29019,6 +29023,18 @@ DONE; }) +(define_insn "vcvtneps2bf16_v8sf" + [(set (match_operand:V8BF 0 "register_operand" "=x,v") + (float_truncate:V8BF + (match_operand:V8SF 1 "nonimmediate_operand" "xm,vm")))] + "TARGET_AVXNECONVERT || (TARGET_AVX512BF16 && TARGET_AVX512VL)" + "@ + %{vex%} vcvtneps2bf16{y}\t{%1, %0|%0, %1} + vcvtneps2bf16{y}\t{%1, %0|%0, %1}" + [(set_attr "isa" "avxneconvert,avx512bf16vl") + (set_attr "prefix" "vex,evex")]) + + (define_insn "avx512f_cvtneps2bf16_" [(set (match_operand: 0 "register_operand" "=v") (float_truncate: @@ -29362,3 +29378,81 @@ "TARGET_AVXVNNIINT8" "vpdp\t{%3, %2, %0|%0, %2, %3}" [(set_attr "prefix" "vex")]) + +(define_insn "vbcstnebf162ps_" + [(set (match_operand:VF1_128_256 0 "register_operand" "=x") + (vec_duplicate:VF1_128_256 + (float_extend:SF + (match_operand:BF 1 "memory_operand" "m"))))] + "TARGET_AVXNECONVERT" + "vbcstnebf162ps\t{%1, %0|%0, %1}" + [(set_attr "prefix" "vex") + (set_attr "mode" "")]) + +(define_insn "vbcstnesh2ps_" + [(set (match_operand:VF1_128_256 0 "register_operand" "=x") + (vec_duplicate:VF1_128_256 + (float_extend:SF + (match_operand:HF 1 "memory_operand" "m"))))] + "TARGET_AVXNECONVERT" + "vbcstnesh2ps\t{%1, %0|%0, %1}" + [(set_attr "prefix" "vex") + (set_attr "mode" "")]) + +(define_mode_iterator V16BFH_256 [V16HF V16BF]) + +(define_mode_attr bf16_ph + [(V8HF "ph") (V16HF "ph") + (V8BF "bf16") (V16BF "bf16")]) + +(define_insn "vcvtnee2ps_" + [(set (match_operand:V4SF 0 "register_operand" "=x") + (float_extend:V4SF + (vec_select: + (match_operand:V8BFH_128 1 "memory_operand" "m") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6)]))))] + "TARGET_AVXNECONVERT" + "vcvtnee2ps\t{%1, %0|%0, %1}" + [(set_attr "prefix" "vex") + (set_attr "mode" "")]) + +(define_insn "vcvtnee2ps_" + [(set (match_operand:V8SF 0 "register_operand" "=x") + (float_extend:V8SF + (vec_select: + (match_operand:V16BFH_256 1 "memory_operand" "m") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)]))))] + "TARGET_AVXNECONVERT" + "vcvtnee2ps\t{%1, %0|%0, %1}" + [(set_attr "prefix" "vex") + (set_attr "mode" "")]) + +(define_insn "vcvtneo2ps_" + [(set (match_operand:V4SF 0 "register_operand" "=x") + (float_extend:V4SF + (vec_select: + (match_operand:V8BFH_128 1 "memory_operand" "m") + (parallel [(const_int 1) (const_int 3) + (const_int 5) (const_int 7)]))))] + "TARGET_AVXNECONVERT" + "vcvtneo2ps\t{%1, %0|%0, %1}" + [(set_attr "prefix" "vex") + (set_attr "mode" "")]) + +(define_insn "vcvtneo2ps_" + [(set (match_operand:V8SF 0 "register_operand" "=x") + (float_extend:V8SF + (vec_select: + (match_operand:V16BFH_256 1 "memory_operand" "m") + (parallel [(const_int 1) (const_int 3) + (const_int 5) (const_int 7) + (const_int 9) (const_int 11) + (const_int 13) (const_int 15)]))))] + "TARGET_AVXNECONVERT" + "vcvtneo2ps\t{%1, %0|%0, %1}" + [(set_attr "prefix" "vex") + (set_attr "mode" "")]) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 77ea545..53478b7 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7070,6 +7070,11 @@ Enable/disable the generation of the AVXIFMA instructions. @cindex @code{target("avxvnniint8")} function attribute, x86 Enable/disable the generation of the AVXVNNIINT8 instructions. +@item avxneconvert +@itemx no-avxneconvert +@cindex @code{target("avxneconvert")} function attribute, x86 +Enable/disable the generation of the AVXNECONVERT instructions. + @item cld @itemx no-cld @cindex @code{target("cld")} function attribute, x86 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 550aec8..c6323a5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1437,7 +1437,7 @@ See RS/6000 and PowerPC Options. -mavx5124fmaps -mavx512vnni -mavx5124vnniw -mprfchw -mrdpid @gol -mrdseed -msgx -mavx512vp2intersect -mserialize -mtsxldtrk@gol -mamx-tile -mamx-int8 -mamx-bf16 -muintr -mhreset -mavxvnni@gol --mavx512fp16 -mavxifma -mavxvnniint8 @gol +-mavx512fp16 -mavxifma -mavxvnniint8 -mavxneconvert @gol -mcldemote -mms-bitfields -mno-align-stringops -minline-all-stringops @gol -minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol -mkl -mwidekl @gol @@ -32967,6 +32967,9 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @need 200 @itemx -mavxvnniint8 @opindex mavxvnniint8 +@need 200 +@itemx -mavxneconvert +@opindex mavxneconvert These switches enable the use of instructions in the MMX, SSE, SSE2, SSE3, SSSE3, SSE4, SSE4A, SSE4.1, SSE4.2, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA, @@ -32977,8 +32980,8 @@ XSAVEOPT, XSAVEC, XSAVES, RTM, HLE, TBM, MWAITX, CLZERO, PKU, AVX512VBMI2, GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16, ENQCMD, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, SERIALIZE, UINTR, HRESET, AMXTILE, AMXINT8, AMXBF16, KL, WIDEKL, AVXVNNI, AVX512FP16, -AVXIFMA, AVXVNNIINT8 or CLDEMOTE extended instruction sets. Each has a -corresponding @option{-mno-} option to disable use of these instructions. +AVXIFMA, AVXVNNIINT8, AVXNECONVERT or CLDEMOTE extended instruction sets. Each +has a corresponding @option{-mno-} option to disable use of these instructions. These extensions are also available as built-in functions: see @ref{x86 Built-in Functions}, for details of the functions enabled and diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index e21a1d3..a12175b 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2493,6 +2493,9 @@ Target supports the execution of @code{avx512vp2intersect} instructions. @item avxifma Target supports the execution of @code{avxifma} instructions. +@item avxneconvert +Target supports the execution of @code{avxneconvert} instructions. + @item avxvnniint8 Target supports the execution of @code{avxvnniint8} instructions. diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C index ebd01fe..dd3e71f 100644 --- a/gcc/testsuite/g++.dg/other/i386-2.C +++ b/gcc/testsuite/g++.dg/other/i386-2.C @@ -1,5 +1,5 @@ /* { dg-do compile { target i?86-*-* x86_64-*-* } } */ -/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8" } */ +/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8 -mavxneconvert" } */ /* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h, xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h, diff --git a/gcc/testsuite/g++.dg/other/i386-3.C b/gcc/testsuite/g++.dg/other/i386-3.C index b66498f..cd7045c 100644 --- a/gcc/testsuite/g++.dg/other/i386-3.C +++ b/gcc/testsuite/g++.dg/other/i386-3.C @@ -1,5 +1,5 @@ /* { dg-do compile { target i?86-*-* x86_64-*-* } } */ -/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8" } */ +/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8 -mavxneconvert" } */ /* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h, xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h, diff --git a/gcc/testsuite/gcc.target/i386/avx-check.h b/gcc/testsuite/gcc.target/i386/avx-check.h index 77507ca..666eff5 100644 --- a/gcc/testsuite/gcc.target/i386/avx-check.h +++ b/gcc/testsuite/gcc.target/i386/avx-check.h @@ -29,6 +29,9 @@ main () #ifdef AVXVNNIINT8 && __builtin_cpu_supports ("avxvnniint8") #endif +#ifdef AVXNECONVERT + && __builtin_cpu_supports ("avxneconvert") +#endif ) { do_test (); diff --git a/gcc/testsuite/gcc.target/i386/avx-ne-convert-1.c b/gcc/testsuite/gcc.target/i386/avx-ne-convert-1.c new file mode 100644 index 0000000..27188a6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-ne-convert-1.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-mavxneconvert -O2" } */ +/* { dg-final { scan-assembler-times "vbcstnebf162ps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vbcstnebf162ps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vbcstnesh2ps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vbcstnesh2ps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneebf162ps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneebf162ps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneeph2ps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneeph2ps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneobf162ps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneobf162ps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneoph2ps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneoph2ps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "\{vex\} vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "\{vex\} vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +#include + +volatile __m128 x1; +volatile __m256 x2; +volatile __m128bh res1, res2; +const void *a; +__m128bh *b; +__m256bh *c; +__m128h *d; +__m256h *e; + +void extern +avx_ne_convert_test (void) +{ + x1 = _mm_bcstnebf16_ps (a); + x2 = _mm256_bcstnebf16_ps (a); + x1 = _mm_bcstnesh_ps (a); + x2 = _mm256_bcstnesh_ps (a); + x1 = _mm_cvtneebf16_ps (b); + x2 = _mm256_cvtneebf16_ps (c); + x1 = _mm_cvtneeph_ps (d); + x2 = _mm256_cvtneeph_ps (e); + x1 = _mm_cvtneobf16_ps (b); + x2 = _mm256_cvtneobf16_ps (c); + x1 = _mm_cvtneoph_ps (d); + x2 = _mm256_cvtneoph_ps (e); + res1 = _mm_cvtneps_avx_pbh (x1); + res2 = _mm256_cvtneps_avx_pbh (x2); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-ne-convert-vbcstnebf162ps-2.c b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vbcstnebf162ps-2.c new file mode 100644 index 0000000..2707c58 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vbcstnebf162ps-2.c @@ -0,0 +1,54 @@ +/* { dg-do run } */ +/* { dg-options "-mavxneconvert -O2" } */ +/* { dg-require-effective-target avxneconvert } */ +#define AVXNECONVERT +#include + +#ifndef CHECK +#define CHECK "avx-check.h" +#endif + +#ifndef TEST +#define TEST avx_test +#endif + +#include CHECK + +typedef union +{ + uint32_t int32; + float flt; +} float_int_t; + +static uint16_t convert_fp32_to_bf16 (float fp) +{ + float_int_t fi; + fi.flt = fp; + return ((fi.int32 >> 16) & 0xffff); +} + +void TEST (void) +{ + union128 dst_128; + union256 dst_256; + float res_ref_128[4], res_ref_256[8], fp32; + uint16_t var; + fp32 = (float) 3 * 2 + 5.5; + for (int i = 0; i < 4; i++) + { + res_ref_128[i] = fp32; + dst_128.a[i] = 117; + } + for (int i = 0; i < 8; i++) + { + res_ref_256[i] = fp32; + dst_256.a[i] = 117; + } + var = convert_fp32_to_bf16 (fp32); + dst_128.x = _mm_bcstnebf16_ps (&var); + dst_256.x = _mm256_bcstnebf16_ps (&var); + if (check_union128 (dst_128, res_ref_128)) + abort(); + if (check_union256 (dst_256, res_ref_256)) + abort(); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-ne-convert-vbcstnesh2ps-2.c b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vbcstnesh2ps-2.c new file mode 100644 index 0000000..0e6f383 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vbcstnesh2ps-2.c @@ -0,0 +1,42 @@ +/* { dg-do run } */ +/* { dg-options "-mavxneconvert -mf16c -O2" } */ +/* { dg-require-effective-target avxneconvert } */ +#define AVXNECONVERT +#include +#include + +#ifndef CHECK +#define CHECK "avx-check.h" +#endif + +#ifndef TEST +#define TEST avx_test +#endif + +#include CHECK + +void TEST (void) +{ + union128 dst_128; + union256 dst_256; + float res_ref_128[4], res_ref_256[8], fp32; + uint16_t var; + fp32 = (float) 3 * 2 + 8.5; + for (int i = 0; i < 4; i++) + { + res_ref_128[i] = fp32; + dst_128.a[i] = 117; + } + for (int i = 0; i < 8; i++) + { + res_ref_256[i] = fp32; + dst_256.a[i] = 117; + } + var = _cvtss_sh (fp32, 0); + dst_128.x = _mm_bcstnesh_ps (&var); + dst_256.x = _mm256_bcstnesh_ps (&var); + if (check_union128 (dst_128, res_ref_128)) + abort(); + if (check_union256 (dst_256, res_ref_256)) + abort(); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneebf162ps-2.c b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneebf162ps-2.c new file mode 100644 index 0000000..bd02616 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneebf162ps-2.c @@ -0,0 +1,73 @@ +/* { dg-do run } */ +/* { dg-options "-mavxneconvert -O2" } */ +/* { dg-require-effective-target avxneconvert } */ +#define AVXNECONVERT +#include + +#ifndef CHECK +#define CHECK "avx-check.h" +#endif + +#ifndef TEST +#define TEST avx_test +#endif + +#include CHECK + +typedef union +{ + uint32_t int32; + float flt; +} float_int_t; + +typedef union +{ + __m128bh x; + uint32_t a[4]; +} union128bf16_i; + +typedef union +{ + __m256bh x; + uint32_t a[8]; +} union256bf16_i; + +static uint16_t convert_fp32_to_bf16 (float fp) +{ + float_int_t fi; + fi.flt = fp; + return ((fi.int32 >> 16) & 0xffff); +} + +void TEST (void) +{ + union128 dst_128; + union256 dst_256; + float res_ref_128[4], res_ref_256[8], fp32; + uint16_t bf16; + union128bf16_i src_128bh; + union256bf16_i src_256bh; + + for (int i = 0; i < 4; i++) + { + fp32 = (float) 3 * i + 5 + i * 0.5; + bf16 = convert_fp32_to_bf16 (fp32); + src_128bh.a[i] = bf16; // store bf16 at the lower part of the dword + res_ref_128[i] = fp32; + dst_128.a[i] = 117; + } + for (int i = 0; i < 8; i++) + { + fp32 = (float) 3 * i + 5 + i * 0.5; + bf16 = convert_fp32_to_bf16 (fp32); + src_256bh.a[i] = bf16; // store bf16 at the lower part of the dword + res_ref_256[i] = fp32; + dst_256.a[i] = 117; + } + dst_128.x = _mm_cvtneebf16_ps (&src_128bh.x); + dst_256.x = _mm256_cvtneebf16_ps (&src_256bh.x); + if (check_union128 (dst_128, res_ref_128)) + abort(); + if (check_union256 (dst_256, res_ref_256)) + abort(); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneeph2ps-2.c b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneeph2ps-2.c new file mode 100644 index 0000000..a862894 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneeph2ps-2.c @@ -0,0 +1,66 @@ +/* { dg-do run } */ +/* { dg-options "-mavxneconvert -mf16c -O2" } */ +/* { dg-require-effective-target avxneconvert } */ +#define AVXNECONVERT +#include + +#ifndef CHECK +#define CHECK "avx-check.h" +#endif + +#ifndef TEST +#define TEST avx_test +#endif + +#include CHECK + +typedef union +{ + uint32_t int32; + float flt; +} float_int_t; + +typedef union +{ + __m128h x; + uint32_t a[4]; +} union128h; + +typedef union +{ + __m256h x; + uint32_t a[8]; +} union256h; + +void TEST (void) +{ + union128 dst_128; + union256 dst_256; + float res_ref_128[4], res_ref_256[8], fp32; + uint16_t fp16; + union128h src_128h; + union256h src_256h; + + for (int i = 0; i < 4; i++) + { + fp32 = (float) 3 * i + 5 + i * 0.5; + fp16 = _cvtss_sh (fp32, 0); + src_128h.a[i] = fp16; + res_ref_128[i] = fp32; + dst_128.a[i] = 117; + } + for (int i = 0; i < 8; i++) + { + fp32 = (float) 3 * i + 5 + i * 0.5; + fp16 = _cvtss_sh (fp32, 0); + src_256h.a[i] = fp16; + res_ref_256[i] = fp32; + dst_256.a[i] = 117; + } + dst_128.x = _mm_cvtneeph_ps (&src_128h.x); + dst_256.x = _mm256_cvtneeph_ps (&src_256h.x); + if (check_union128 (dst_128, res_ref_128)) + abort(); + if (check_union256 (dst_256, res_ref_256)) + abort(); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneobf162ps-2.c b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneobf162ps-2.c new file mode 100644 index 0000000..a6f722e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneobf162ps-2.c @@ -0,0 +1,75 @@ +/* { dg-do run } */ +/* { dg-options "-mavxneconvert -O2" } */ +/* { dg-require-effective-target avxneconvert } */ +#define AVXNECONVERT +#include + +#ifndef CHECK +#define CHECK "avx-check.h" +#endif + +#ifndef TEST +#define TEST avx_test +#endif + +#include CHECK + +typedef union +{ + uint32_t int32; + float flt; +} float_int_t; + +typedef union +{ + __m128bh x; + uint32_t a[4]; +} union128bf16_i; + +typedef union +{ + __m256bh x; + uint32_t a[8]; +} union256bf16_i; + +static uint16_t convert_fp32_to_bf16 (float fp) +{ + float_int_t fi; + fi.flt = fp; + return ((fi.int32 >> 16) & 0xffff); +} + +void TEST (void) +{ + union128 dst_128; + union256 dst_256; + float res_ref_128[4], res_ref_256[8], fp32; + uint16_t bf16; + union128bf16_i src_128bh; + union256bf16_i src_256bh; + + for (int i = 0; i < 4; i++) + { + fp32 = (float) 3 * i + 5 + i * 0.5; + bf16 = convert_fp32_to_bf16 (fp32); + // store bf16 at the upper part of the dword + src_128bh.a[i] = (bf16 << 16) & 0xffff0000; + res_ref_128[i] = fp32; + dst_128.a[i] = 117; + } + for (int i = 0; i < 8; i++) + { + fp32 = (float) 3 * i + 5 + i * 0.5; + bf16 = convert_fp32_to_bf16 (fp32); + // store bf16 at the upper part of the dword + src_256bh.a[i] = (bf16 << 16) & 0xffff0000; + res_ref_256[i] = fp32; + dst_256.a[i] = 117; + } + dst_128.x = _mm_cvtneobf16_ps (&src_128bh.x); + dst_256.x = _mm256_cvtneobf16_ps (&src_256bh.x); + if (check_union128 (dst_128, res_ref_128)) + abort(); + if (check_union256 (dst_256, res_ref_256)) + abort(); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneoph2ps-2.c b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneoph2ps-2.c new file mode 100644 index 0000000..95eb5d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneoph2ps-2.c @@ -0,0 +1,66 @@ +/* { dg-do run } */ +/* { dg-options "-mavxneconvert -mf16c -O2" } */ +/* { dg-require-effective-target avxneconvert } */ +#define AVXNECONVERT +#include + +#ifndef CHECK +#define CHECK "avx-check.h" +#endif + +#ifndef TEST +#define TEST avx_test +#endif + +#include CHECK + +typedef union +{ + uint32_t int32; + float flt; +} float_int_t; + +typedef union +{ + __m128h x; + uint32_t a[4]; +} union128h; + +typedef union +{ + __m256h x; + uint32_t a[8]; +} union256h; + +void TEST (void) +{ + union128 dst_128; + union256 dst_256; + float res_ref_128[4], res_ref_256[8], fp32; + uint16_t fp16; + union128h src_128h; + union256h src_256h; + + for (int i = 0; i < 4; i++) + { + fp32 = (float) 3 * i + 5 + i * 0.5; + fp16 = _cvtss_sh (fp32, 0); + src_128h.a[i] = fp16 << 16; + res_ref_128[i] = fp32; + dst_128.a[i] = 117; + } + for (int i = 0; i < 8; i++) + { + fp32 = (float) 3 * i + 5 + i * 0.5; + fp16 = _cvtss_sh (fp32, 0); + src_256h.a[i] = fp16 << 16; + res_ref_256[i] = fp32; + dst_256.a[i] = 117; + } + dst_128.x = _mm_cvtneoph_ps (&src_128h.x); + dst_256.x = _mm256_cvtneoph_ps (&src_256h.x); + if (check_union128 (dst_128, res_ref_128)) + abort(); + if (check_union256 (dst_256, res_ref_256)) + abort(); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneps2bf16-2.c b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneps2bf16-2.c new file mode 100644 index 0000000..e673123 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-ne-convert-vcvtneps2bf16-2.c @@ -0,0 +1,58 @@ +/* { dg-do run } */ +/* { dg-options "-mavxneconvert -O2" } */ +/* { dg-require-effective-target avxneconvert } */ +#define AVXNECONVERT +#include + +#ifndef CHECK +#define CHECK "avx-check.h" +#endif + +#ifndef TEST +#define TEST avx_test +#endif + +#include CHECK + +typedef union +{ + uint32_t int32; + float flt; +} float_int_t; + +typedef union +{ + __m128bh x; + unsigned short a[8]; +} union128bf16; + +void TEST (void) +{ + union128 src_128; + union256 src_256; + union128bf16 dst_128, dst_256; + uint16_t res_ref_128[8] = {0}, res_ref_256[8]; + float_int_t fp32; + for (int i = 0; i < 4; i++) + { + fp32.flt = (float) 2 * i + 7 + i * 0.25; + src_128.a[i] = fp32.flt; + res_ref_128[i] = fp32.int32 >> 16; + dst_128.a[i] = 117; + } + + for (int i = 0; i < 8; i++) + { + fp32.flt = (float) 2 * i + 7 + i * 0.25; + src_256.a[i] = fp32.flt; + res_ref_256[i] = fp32.int32 >> 16; + dst_256.a[i] = 117; + } + dst_128.x = _mm_cvtneps_avx_pbh (src_128.x); + dst_256.x = _mm256_cvtneps_avx_pbh (src_256.x); + + if (checkVus (dst_128.a, res_ref_128, 8)) + abort(); + if (checkVus (dst_128.a, res_ref_128, 8)) + abort(); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c b/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c deleted file mode 100644 index d3a9bdf..0000000 --- a/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c +++ /dev/null @@ -1,27 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-mavx512bf16 -mavx512vl -O2" } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ - -#include - -volatile __m128bh res1, res2; -volatile __m128 x1; -volatile __m256 x2; -volatile __mmask8 m8; - -void extern -avx512bf16_test (void) -{ - res2 = _mm256_cvtneps_pbh (x2); - res2 = _mm256_mask_cvtneps_pbh (res2, m8, x2); - res2 = _mm256_maskz_cvtneps_pbh (m8, x2); - - res1 = _mm_cvtneps_pbh (x1); - res1 = _mm_mask_cvtneps_pbh (res1, m8, x1); - res1 = _mm_maskz_cvtneps_pbh (m8, x1); -} diff --git a/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1a.c b/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1a.c new file mode 100644 index 0000000..d3a9bdf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1a.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512bf16 -mavx512vl -O2" } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ + +#include + +volatile __m128bh res1, res2; +volatile __m128 x1; +volatile __m256 x2; +volatile __mmask8 m8; + +void extern +avx512bf16_test (void) +{ + res2 = _mm256_cvtneps_pbh (x2); + res2 = _mm256_mask_cvtneps_pbh (res2, m8, x2); + res2 = _mm256_maskz_cvtneps_pbh (m8, x2); + + res1 = _mm_cvtneps_pbh (x1); + res1 = _mm_mask_cvtneps_pbh (res1, m8, x1); + res1 = _mm_maskz_cvtneps_pbh (m8, x1); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1b.c b/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1b.c new file mode 100644 index 0000000..e0687fa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1b.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512bf16 -mavx512vl -mavxneconvert -O2" } */ +/* { dg-final { scan-assembler-times "\{vex\} vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16y\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "\{vex\} vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vcvtneps2bf16x\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ + +#include + +volatile __m128bh res1, res2; +volatile __m128 x1; +volatile __m256 x2; +volatile __mmask8 m8; + +void extern +avx512bf16_test (void) +{ + res2 = _mm256_cvtneps_pbh (x2); + res2 = _mm256_mask_cvtneps_pbh (res2, m8, x2); + res2 = _mm256_maskz_cvtneps_pbh (m8, x2); + + res1 = _mm_cvtneps_pbh (x1); + res1 = _mm_mask_cvtneps_pbh (res1, m8, x1); + res1 = _mm_maskz_cvtneps_pbh (m8, x1); +} diff --git a/gcc/testsuite/gcc.target/i386/funcspec-56.inc b/gcc/testsuite/gcc.target/i386/funcspec-56.inc index fada66b..5655c5b 100644 --- a/gcc/testsuite/gcc.target/i386/funcspec-56.inc +++ b/gcc/testsuite/gcc.target/i386/funcspec-56.inc @@ -82,6 +82,7 @@ extern void test_avxvnni (void) __attribute__((__target__("avxvnni"))); extern void test_avx512fp16 (void) __attribute__((__target__("avx512fp16"))); extern void test_avxifma (void) __attribute__((__target__("avxifma"))); extern void test_avxvnniint8 (void) __attribute__((__target__("avxvnniint8"))); +extern void test_avxneconvert (void) __attribute__((__target__("avxneconvert"))); extern void test_no_sgx (void) __attribute__((__target__("no-sgx"))); extern void test_no_avx5124fmaps(void) __attribute__((__target__("no-avx5124fmaps"))); @@ -165,6 +166,7 @@ extern void test_no_avxvnni (void) __attribute__((__target__("no-avxvnni"))); extern void test_no_avx512fp16 (void) __attribute__((__target__("no-avx512fp16"))); extern void test_no_avxifma (void) __attribute__((__target__("no-avxifma"))); extern void test_no_avxvnniint8 (void) __attribute__((__target__("no-avxvnniint8"))); +extern void test_no_avxneconvert (void) __attribute__((__target__("no-avxneconvert"))); extern void test_arch_nocona (void) __attribute__((__target__("arch=nocona"))); extern void test_arch_core2 (void) __attribute__((__target__("arch=core2"))); diff --git a/gcc/testsuite/gcc.target/i386/sse-12.c b/gcc/testsuite/gcc.target/i386/sse-12.c index ddde2df..3eabc49 100644 --- a/gcc/testsuite/gcc.target/i386/sse-12.c +++ b/gcc/testsuite/gcc.target/i386/sse-12.c @@ -3,7 +3,7 @@ popcntintrin.h gfniintrin.h and mm_malloc.h are usable with -O -std=c89 -pedantic-errors. */ /* { dg-do compile } */ -/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavxifma -mavxvnniint8" } */ +/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavxifma -mavxvnniint8 -mavxneconvert" } */ #include diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c index 2b29321..b9cdfb6 100644 --- a/gcc/testsuite/gcc.target/i386/sse-13.c +++ b/gcc/testsuite/gcc.target/i386/sse-13.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mavx512vp2intersect -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8" } */ +/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mavx512vp2intersect -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8 -mavxneconvert" } */ /* { dg-add-options bind_pic_locally } */ #include diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c index 78b5104..b6ee380 100644 --- a/gcc/testsuite/gcc.target/i386/sse-14.c +++ b/gcc/testsuite/gcc.target/i386/sse-14.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mpconfig -mwbnoinvd -mavx512vl -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8" } */ +/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mpconfig -mwbnoinvd -mavx512vl -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8 -mavxneconvert" } */ /* { dg-add-options bind_pic_locally } */ #include diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c index cc1c8cf..71ac0f3 100644 --- a/gcc/testsuite/gcc.target/i386/sse-22.c +++ b/gcc/testsuite/gcc.target/i386/sse-22.c @@ -103,7 +103,7 @@ #ifndef DIFFERENT_PRAGMAS -#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,avx512vl,avx512bw,avx512dq,avx512vbmi,avx512vbmi2,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16,avxifma,avxvnniint8") +#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,avx512vl,avx512bw,avx512dq,avx512vbmi,avx512vbmi2,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16,avxifma,avxvnniint8,avxneconvert") #endif /* Following intrinsics require immediate arguments. They @@ -220,7 +220,7 @@ test_4 (_mm_cmpestrz, int, __m128i, int, __m128i, int, 1) /* immintrin.h (AVX/AVX2/RDRND/FSGSBASE/F16C/RTM/AVX512F/SHA) */ #ifdef DIFFERENT_PRAGMAS -#pragma GCC target ("avx,avx2,rdrnd,fsgsbase,f16c,rtm,avx512f,avx512er,avx512cd,avx512pf,sha,avx512vl,avx512bw,avx512dq,avx512ifma,avx512vbmi,avx512vbmi2,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16,avxifma,avxvnniint8") +#pragma GCC target ("avx,avx2,rdrnd,fsgsbase,f16c,rtm,avx512f,avx512er,avx512cd,avx512pf,sha,avx512vl,avx512bw,avx512dq,avx512ifma,avx512vbmi,avx512vbmi2,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16,avxifma,avxvnniint8,avxneconvert") #endif #include test_1 (_cvtss_sh, unsigned short, float, 1) diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c index 270f448..898dde8 100644 --- a/gcc/testsuite/gcc.target/i386/sse-23.c +++ b/gcc/testsuite/gcc.target/i386/sse-23.c @@ -843,6 +843,6 @@ #define __builtin_ia32_vpclmulqdq_v2di(A, B, C) __builtin_ia32_vpclmulqdq_v2di(A, B, 1) #define __builtin_ia32_vpclmulqdq_v8di(A, B, C) __builtin_ia32_vpclmulqdq_v8di(A, B, 1) -#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16,enqcmd,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16,avxifma,avxvnniint8") +#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16,enqcmd,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16,avxifma,avxvnniint8,avxneconvert") #include diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index ccbbee8..750897d 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -9549,6 +9549,18 @@ proc check_effective_target_avxvnniint8 { } { } "-O0 -mavxvnniint8" ] } +# Return 1 if avxneconvert instructions can be compiled. +proc check_effective_target_avxneconvert { } { + return [check_no_compiler_messages avxneconvert object { + typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__)); + __m128 + _mm_bcstnebf16_ps (const void *__P) + { + return (__m128) __builtin_ia32_vbcstnebf162ps128 ((const __bf16 *) __P); + } + } "-O0 -mavxneconvert" ] +} + # Return 1 if sse instructions can be compiled. proc check_effective_target_sse { } { return [check_no_compiler_messages sse object { -- cgit v1.1 From 7f940822816917fea276654514eccdc8eacd5e93 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 31 Oct 2022 09:05:02 +0100 Subject: builtins: Add various __builtin_*f{16,32,64,128,32x,64x,128x} builtins When working on libstdc++ extended float support in , I found that we need various builtins for the _Float{16,32,64,128,32x,64x,128x} types. Glibc 2.26 and later provides the underlying libm routines (except for _Float16 and _Float128x for the time being) and in libstdc++ I think we need at least the _Float128 builtins on x86_64, i?86, powerpc64le and ia64 (when long double is IEEE quad, we can handle it by using __builtin_*l instead), because without the builtins the overloads couldn't be constexpr (say when it would declare the *f128 extern "C" routines itself and call them). The testcase covers just types of those builtins and their constant folding, so doesn't need actual libm support. 2022-10-31 Jakub Jelinek * builtin-types.def (BT_FLOAT16_PTR, BT_FLOAT32_PTR, BT_FLOAT64_PTR, BT_FLOAT128_PTR, BT_FLOAT32X_PTR, BT_FLOAT64X_PTR, BT_FLOAT128X_PTR): New DEF_PRIMITIVE_TYPE. (BT_FN_INT_FLOAT16, BT_FN_INT_FLOAT32, BT_FN_INT_FLOAT64, BT_FN_INT_FLOAT128, BT_FN_INT_FLOAT32X, BT_FN_INT_FLOAT64X, BT_FN_INT_FLOAT128X, BT_FN_LONG_FLOAT16, BT_FN_LONG_FLOAT32, BT_FN_LONG_FLOAT64, BT_FN_LONG_FLOAT128, BT_FN_LONG_FLOAT32X, BT_FN_LONG_FLOAT64X, BT_FN_LONG_FLOAT128X, BT_FN_LONGLONG_FLOAT16, BT_FN_LONGLONG_FLOAT32, BT_FN_LONGLONG_FLOAT64, BT_FN_LONGLONG_FLOAT128, BT_FN_LONGLONG_FLOAT32X, BT_FN_LONGLONG_FLOAT64X, BT_FN_LONGLONG_FLOAT128X): New DEF_FUNCTION_TYPE_1. (BT_FN_FLOAT16_FLOAT16_FLOAT16PTR, BT_FN_FLOAT32_FLOAT32_FLOAT32PTR, BT_FN_FLOAT64_FLOAT64_FLOAT64PTR, BT_FN_FLOAT128_FLOAT128_FLOAT128PTR, BT_FN_FLOAT32X_FLOAT32X_FLOAT32XPTR, BT_FN_FLOAT64X_FLOAT64X_FLOAT64XPTR, BT_FN_FLOAT128X_FLOAT128X_FLOAT128XPTR, BT_FN_FLOAT16_FLOAT16_INT, BT_FN_FLOAT32_FLOAT32_INT, BT_FN_FLOAT64_FLOAT64_INT, BT_FN_FLOAT128_FLOAT128_INT, BT_FN_FLOAT32X_FLOAT32X_INT, BT_FN_FLOAT64X_FLOAT64X_INT, BT_FN_FLOAT128X_FLOAT128X_INT, BT_FN_FLOAT16_FLOAT16_INTPTR, BT_FN_FLOAT32_FLOAT32_INTPTR, BT_FN_FLOAT64_FLOAT64_INTPTR, BT_FN_FLOAT128_FLOAT128_INTPTR, BT_FN_FLOAT32X_FLOAT32X_INTPTR, BT_FN_FLOAT64X_FLOAT64X_INTPTR, BT_FN_FLOAT128X_FLOAT128X_INTPTR, BT_FN_FLOAT16_FLOAT16_LONG, BT_FN_FLOAT32_FLOAT32_LONG, BT_FN_FLOAT64_FLOAT64_LONG, BT_FN_FLOAT128_FLOAT128_LONG, BT_FN_FLOAT32X_FLOAT32X_LONG, BT_FN_FLOAT64X_FLOAT64X_LONG, BT_FN_FLOAT128X_FLOAT128X_LONG): New DEF_FUNCTION_TYPE_2. (BT_FN_FLOAT16_FLOAT16_FLOAT16_INTPTR, BT_FN_FLOAT32_FLOAT32_FLOAT32_INTPTR, BT_FN_FLOAT64_FLOAT64_FLOAT64_INTPTR, BT_FN_FLOAT128_FLOAT128_FLOAT128_INTPTR, BT_FN_FLOAT32X_FLOAT32X_FLOAT32X_INTPTR, BT_FN_FLOAT64X_FLOAT64X_FLOAT64X_INTPTR, BT_FN_FLOAT128X_FLOAT128X_FLOAT128X_INTPTR): New DEF_FUNCTION_TYPE_3. * builtins.def (ACOSH_TYPE, ATAN2_TYPE, ATANH_TYPE, COSH_TYPE, FDIM_TYPE, HUGE_VAL_TYPE, HYPOT_TYPE, ILOGB_TYPE, LDEXP_TYPE, LGAMMA_TYPE, LLRINT_TYPE, LOG10_TYPE, LRINT_TYPE, MODF_TYPE, NEXTAFTER_TYPE, REMQUO_TYPE, SCALBLN_TYPE, SCALBN_TYPE, SINH_TYPE): Define and undefine later. (FMIN_TYPE, SQRT_TYPE): Undefine at a later line. (INF_TYPE): Define at a later line. (BUILT_IN_ACOSH, BUILT_IN_ACOS, BUILT_IN_ASINH, BUILT_IN_ASIN, BUILT_IN_ATAN2, BUILT_IN_ATANH, BUILT_IN_ATAN, BUILT_IN_CBRT, BUILT_IN_COSH, BUILT_IN_COS, BUILT_IN_ERFC, BUILT_IN_ERF, BUILT_IN_EXP2, BUILT_IN_EXP, BUILT_IN_EXPM1, BUILT_IN_FDIM, BUILT_IN_FMOD, BUILT_IN_FREXP, BUILT_IN_HYPOT, BUILT_IN_ILOGB, BUILT_IN_LDEXP, BUILT_IN_LGAMMA, BUILT_IN_LLRINT, BUILT_IN_LLROUND, BUILT_IN_LOG10, BUILT_IN_LOG1P, BUILT_IN_LOG2, BUILT_IN_LOGB, BUILT_IN_LOG, BUILT_IN_LRINT, BUILT_IN_LROUND, BUILT_IN_MODF, BUILT_IN_NEXTAFTER, BUILT_IN_POW, BUILT_IN_REMAINDER, BUILT_IN_REMQUO, BUILT_IN_SCALBLN, BUILT_IN_SCALBN, BUILT_IN_SINH, BUILT_IN_SIN, BUILT_IN_TANH, BUILT_IN_TAN, BUILT_IN_TGAMMA): Add DEF_EXT_LIB_FLOATN_NX_BUILTINS. (BUILT_IN_HUGE_VAL): Use HUGE_VAL_TYPE instead of INF_TYPE in DEF_GCC_FLOATN_NX_BUILTINS. * fold-const-call.cc (fold_const_call_ss): Add various CASE_CFN_*_FN: cases when CASE_CFN_* is present. (fold_const_call_sss): Likewise. * builtins.cc (mathfn_built_in_2): Use CASE_MATHFN_FLOATN instead of CASE_MATHFN for various builtins in SEQ_OF_CASE_MATHFN macro. (builtin_with_linkage_p): Add CASE_FLT_FN_FLOATN_NX for various builtins next to CASE_FLT_FN. * fold-const.cc (tree_call_nonnegative_warnv_p): Add CASE_CFN_*_FN: next to CASE_CFN_*: for various builtins. * tree-call-cdce.cc (can_test_argument_range): Add CASE_FLT_FN_FLOATN_NX next to CASE_FLT_FN for various builtins. (edom_only_function): Likewise. * gcc.dg/torture/floatn-builtin.h: Add tests for newly added builtins. --- gcc/builtin-types.def | 112 +++++++++++++++++++ gcc/builtins.cc | 140 +++++++++++++++-------- gcc/builtins.def | 91 ++++++++++++++- gcc/fold-const-call.cc | 39 +++++++ gcc/fold-const.cc | 27 +++++ gcc/testsuite/gcc.dg/torture/floatn-builtin.h | 154 ++++++++++++++++++++++++++ gcc/tree-call-cdce.cc | 20 ++++ 7 files changed, 531 insertions(+), 52 deletions(-) (limited to 'gcc') diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index df3a88f2..2dbed8a 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -135,6 +135,27 @@ DEF_PRIMITIVE_TYPE (BT_CONST_DOUBLE_PTR, (build_qualified_type (double_type_node, TYPE_QUAL_CONST))) DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE_PTR, long_double_ptr_type_node) +DEF_PRIMITIVE_TYPE (BT_FLOAT16_PTR, (float16_type_node + ? build_pointer_type (float16_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_FLOAT32_PTR, (float32_type_node + ? build_pointer_type (float32_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_FLOAT64_PTR, (float64_type_node + ? build_pointer_type (float64_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_FLOAT128_PTR, (float128_type_node + ? build_pointer_type (float128_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_FLOAT32X_PTR, (float32x_type_node + ? build_pointer_type (float32x_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_FLOAT64X_PTR, (float64x_type_node + ? build_pointer_type (float64x_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_FLOAT128X_PTR, (float128x_type_node + ? build_pointer_type (float128x_type_node) + : error_mark_node)) DEF_PRIMITIVE_TYPE (BT_PID, pid_type_node) DEF_PRIMITIVE_TYPE (BT_SIZE, size_type_node) DEF_PRIMITIVE_TYPE (BT_CONST_SIZE, @@ -247,15 +268,36 @@ DEF_FUNCTION_TYPE_1 (BT_FN_INT_PTR, BT_INT, BT_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT, BT_INT, BT_FLOAT) DEF_FUNCTION_TYPE_1 (BT_FN_INT_DOUBLE, BT_INT, BT_DOUBLE) DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONGDOUBLE, BT_INT, BT_LONGDOUBLE) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT16, BT_INT, BT_FLOAT16) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT32, BT_INT, BT_FLOAT32) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT64, BT_INT, BT_FLOAT64) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT128, BT_INT, BT_FLOAT128) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT32X, BT_INT, BT_FLOAT32X) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT64X, BT_INT, BT_FLOAT64X) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT128X, BT_INT, BT_FLOAT128X) DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT32, BT_INT, BT_DFLOAT32) DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT64, BT_INT, BT_DFLOAT64) DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT128, BT_INT, BT_DFLOAT128) DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT, BT_LONG, BT_FLOAT) DEF_FUNCTION_TYPE_1 (BT_FN_LONG_DOUBLE, BT_LONG, BT_DOUBLE) DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONGDOUBLE, BT_LONG, BT_LONGDOUBLE) +DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT16, BT_LONG, BT_FLOAT16) +DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT32, BT_LONG, BT_FLOAT32) +DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT64, BT_LONG, BT_FLOAT64) +DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT128, BT_LONG, BT_FLOAT128) +DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT32X, BT_LONG, BT_FLOAT32X) +DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT64X, BT_LONG, BT_FLOAT64X) +DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT128X, BT_LONG, BT_FLOAT128X) DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT, BT_LONGLONG, BT_FLOAT) DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_DOUBLE, BT_LONGLONG, BT_DOUBLE) DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_LONGDOUBLE, BT_LONGLONG, BT_LONGDOUBLE) +DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT16, BT_LONGLONG, BT_FLOAT16) +DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT32, BT_LONGLONG, BT_FLOAT32) +DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT64, BT_LONGLONG, BT_FLOAT64) +DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT128, BT_LONGLONG, BT_FLOAT128) +DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT32X, BT_LONGLONG, BT_FLOAT32X) +DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT64X, BT_LONGLONG, BT_FLOAT64X) +DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT128X, BT_LONGLONG, BT_FLOAT128X) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTR, BT_VOID, BT_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_SIZE_CONST_STRING, BT_SIZE, BT_CONST_STRING) DEF_FUNCTION_TYPE_1 (BT_FN_INT_CONST_STRING, BT_INT, BT_CONST_STRING) @@ -425,6 +467,20 @@ DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_DOUBLEPTR, BT_DOUBLE, BT_DOUBLE, BT_DOUBLE_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLEPTR, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT16_FLOAT16_FLOAT16PTR, + BT_FLOAT16, BT_FLOAT16, BT_FLOAT16_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32_FLOAT32_FLOAT32PTR, + BT_FLOAT32, BT_FLOAT32, BT_FLOAT32_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64_FLOAT64_FLOAT64PTR, + BT_FLOAT64, BT_FLOAT64, BT_FLOAT64_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128_FLOAT128_FLOAT128PTR, + BT_FLOAT128, BT_FLOAT128, BT_FLOAT128_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32X_FLOAT32X_FLOAT32XPTR, + BT_FLOAT32X, BT_FLOAT32X, BT_FLOAT32X_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64X_FLOAT64X_FLOAT64XPTR, + BT_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128X_FLOAT128X_FLOAT128XPTR, + BT_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_LONGDOUBLE, BT_FLOAT, BT_FLOAT, BT_LONGDOUBLE) DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_LONGDOUBLE, @@ -435,12 +491,40 @@ DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_INT, BT_DOUBLE, BT_DOUBLE, BT_INT) DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_INT, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_INT) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT16_FLOAT16_INT, + BT_FLOAT16, BT_FLOAT16, BT_INT) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32_FLOAT32_INT, + BT_FLOAT32, BT_FLOAT32, BT_INT) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64_FLOAT64_INT, + BT_FLOAT64, BT_FLOAT64, BT_INT) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128_FLOAT128_INT, + BT_FLOAT128, BT_FLOAT128, BT_INT) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32X_FLOAT32X_INT, + BT_FLOAT32X, BT_FLOAT32X, BT_INT) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64X_FLOAT64X_INT, + BT_FLOAT64X, BT_FLOAT64X, BT_INT) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128X_FLOAT128X_INT, + BT_FLOAT128X, BT_FLOAT128X, BT_INT) DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_INTPTR, BT_FLOAT, BT_FLOAT, BT_INT_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_INTPTR, BT_DOUBLE, BT_DOUBLE, BT_INT_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_INTPTR, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_INT_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT16_FLOAT16_INTPTR, + BT_FLOAT16, BT_FLOAT16, BT_INT_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32_FLOAT32_INTPTR, + BT_FLOAT32, BT_FLOAT32, BT_INT_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64_FLOAT64_INTPTR, + BT_FLOAT64, BT_FLOAT64, BT_INT_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128_FLOAT128_INTPTR, + BT_FLOAT128, BT_FLOAT128, BT_INT_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32X_FLOAT32X_INTPTR, + BT_FLOAT32X, BT_FLOAT32X, BT_INT_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64X_FLOAT64X_INTPTR, + BT_FLOAT64X, BT_FLOAT64X, BT_INT_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128X_FLOAT128X_INTPTR, + BT_FLOAT128X, BT_FLOAT128X, BT_INT_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_INT_FLOAT, BT_FLOAT, BT_INT, BT_FLOAT) DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_INT_DOUBLE, @@ -453,6 +537,20 @@ DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_LONG, BT_DOUBLE, BT_DOUBLE, BT_LONG) DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONG, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONG) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT16_FLOAT16_LONG, + BT_FLOAT16, BT_FLOAT16, BT_LONG) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32_FLOAT32_LONG, + BT_FLOAT32, BT_FLOAT32, BT_LONG) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64_FLOAT64_LONG, + BT_FLOAT64, BT_FLOAT64, BT_LONG) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128_FLOAT128_LONG, + BT_FLOAT128, BT_FLOAT128, BT_LONG) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32X_FLOAT32X_LONG, + BT_FLOAT32X, BT_FLOAT32X, BT_LONG) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64X_FLOAT64X_LONG, + BT_FLOAT64X, BT_FLOAT64X, BT_LONG) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128X_FLOAT128X_LONG, + BT_FLOAT128X, BT_FLOAT128X, BT_LONG) DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_VALIST_ARG, BT_INT, BT_CONST_STRING, BT_VALIST_ARG) DEF_FUNCTION_TYPE_2 (BT_FN_PTR_SIZE_SIZE, @@ -578,6 +676,20 @@ DEF_FUNCTION_TYPE_3 (BT_FN_DOUBLE_DOUBLE_DOUBLE_INTPTR, BT_DOUBLE, BT_DOUBLE, BT_DOUBLE, BT_INT_PTR) DEF_FUNCTION_TYPE_3 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_INTPTR, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_INT_PTR) +DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT16_FLOAT16_FLOAT16_INTPTR, + BT_FLOAT16, BT_FLOAT16, BT_FLOAT16, BT_INT_PTR) +DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT32_FLOAT32_FLOAT32_INTPTR, + BT_FLOAT32, BT_FLOAT32, BT_FLOAT32, BT_INT_PTR) +DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT64_FLOAT64_FLOAT64_INTPTR, + BT_FLOAT64, BT_FLOAT64, BT_FLOAT64, BT_INT_PTR) +DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT128_FLOAT128_FLOAT128_INTPTR, + BT_FLOAT128, BT_FLOAT128, BT_FLOAT128, BT_INT_PTR) +DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT32X_FLOAT32X_FLOAT32X_INTPTR, + BT_FLOAT32X, BT_FLOAT32X, BT_FLOAT32X, BT_INT_PTR) +DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT64X_FLOAT64X_FLOAT64X_INTPTR, + BT_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X, BT_INT_PTR) +DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT128X_FLOAT128X_FLOAT128X_INTPTR, + BT_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X, BT_INT_PTR) DEF_FUNCTION_TYPE_3 (BT_FN_VOID_FLOAT_FLOATPTR_FLOATPTR, BT_VOID, BT_FLOAT, BT_FLOAT_PTR, BT_FLOAT_PTR) DEF_FUNCTION_TYPE_3 (BT_FN_VOID_DOUBLE_DOUBLEPTR_DOUBLEPTR, diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 26898d7..80415df 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -1934,42 +1934,42 @@ mathfn_built_in_2 (tree type, combined_fn fn) switch (fn) { #define SEQ_OF_CASE_MATHFN \ - CASE_MATHFN (ACOS) \ - CASE_MATHFN (ACOSH) \ - CASE_MATHFN (ASIN) \ - CASE_MATHFN (ASINH) \ - CASE_MATHFN (ATAN) \ - CASE_MATHFN (ATAN2) \ - CASE_MATHFN (ATANH) \ - CASE_MATHFN (CBRT) \ + CASE_MATHFN_FLOATN (ACOS) \ + CASE_MATHFN_FLOATN (ACOSH) \ + CASE_MATHFN_FLOATN (ASIN) \ + CASE_MATHFN_FLOATN (ASINH) \ + CASE_MATHFN_FLOATN (ATAN) \ + CASE_MATHFN_FLOATN (ATAN2) \ + CASE_MATHFN_FLOATN (ATANH) \ + CASE_MATHFN_FLOATN (CBRT) \ CASE_MATHFN_FLOATN (CEIL) \ CASE_MATHFN (CEXPI) \ CASE_MATHFN_FLOATN (COPYSIGN) \ - CASE_MATHFN (COS) \ - CASE_MATHFN (COSH) \ + CASE_MATHFN_FLOATN (COS) \ + CASE_MATHFN_FLOATN (COSH) \ CASE_MATHFN (DREM) \ - CASE_MATHFN (ERF) \ - CASE_MATHFN (ERFC) \ - CASE_MATHFN (EXP) \ + CASE_MATHFN_FLOATN (ERF) \ + CASE_MATHFN_FLOATN (ERFC) \ + CASE_MATHFN_FLOATN (EXP) \ CASE_MATHFN (EXP10) \ - CASE_MATHFN (EXP2) \ - CASE_MATHFN (EXPM1) \ - CASE_MATHFN (FABS) \ - CASE_MATHFN (FDIM) \ + CASE_MATHFN_FLOATN (EXP2) \ + CASE_MATHFN_FLOATN (EXPM1) \ + CASE_MATHFN_FLOATN (FABS) \ + CASE_MATHFN_FLOATN (FDIM) \ CASE_MATHFN_FLOATN (FLOOR) \ CASE_MATHFN_FLOATN (FMA) \ CASE_MATHFN_FLOATN (FMAX) \ CASE_MATHFN_FLOATN (FMIN) \ - CASE_MATHFN (FMOD) \ - CASE_MATHFN (FREXP) \ + CASE_MATHFN_FLOATN (FMOD) \ + CASE_MATHFN_FLOATN (FREXP) \ CASE_MATHFN (GAMMA) \ CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */ \ - CASE_MATHFN (HUGE_VAL) \ - CASE_MATHFN (HYPOT) \ - CASE_MATHFN (ILOGB) \ + CASE_MATHFN_FLOATN (HUGE_VAL) \ + CASE_MATHFN_FLOATN (HYPOT) \ + CASE_MATHFN_FLOATN (ILOGB) \ CASE_MATHFN (ICEIL) \ CASE_MATHFN (IFLOOR) \ - CASE_MATHFN (INF) \ + CASE_MATHFN_FLOATN (INF) \ CASE_MATHFN (IRINT) \ CASE_MATHFN (IROUND) \ CASE_MATHFN (ISINF) \ @@ -1977,47 +1977,47 @@ mathfn_built_in_2 (tree type, combined_fn fn) CASE_MATHFN (J1) \ CASE_MATHFN (JN) \ CASE_MATHFN (LCEIL) \ - CASE_MATHFN (LDEXP) \ + CASE_MATHFN_FLOATN (LDEXP) \ CASE_MATHFN (LFLOOR) \ - CASE_MATHFN (LGAMMA) \ + CASE_MATHFN_FLOATN (LGAMMA) \ CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */ \ CASE_MATHFN (LLCEIL) \ CASE_MATHFN (LLFLOOR) \ - CASE_MATHFN (LLRINT) \ - CASE_MATHFN (LLROUND) \ - CASE_MATHFN (LOG) \ - CASE_MATHFN (LOG10) \ - CASE_MATHFN (LOG1P) \ - CASE_MATHFN (LOG2) \ - CASE_MATHFN (LOGB) \ - CASE_MATHFN (LRINT) \ - CASE_MATHFN (LROUND) \ - CASE_MATHFN (MODF) \ - CASE_MATHFN (NAN) \ - CASE_MATHFN (NANS) \ + CASE_MATHFN_FLOATN (LLRINT) \ + CASE_MATHFN_FLOATN (LLROUND) \ + CASE_MATHFN_FLOATN (LOG) \ + CASE_MATHFN_FLOATN (LOG10) \ + CASE_MATHFN_FLOATN (LOG1P) \ + CASE_MATHFN_FLOATN (LOG2) \ + CASE_MATHFN_FLOATN (LOGB) \ + CASE_MATHFN_FLOATN (LRINT) \ + CASE_MATHFN_FLOATN (LROUND) \ + CASE_MATHFN_FLOATN (MODF) \ + CASE_MATHFN_FLOATN (NAN) \ + CASE_MATHFN_FLOATN (NANS) \ CASE_MATHFN_FLOATN (NEARBYINT) \ - CASE_MATHFN (NEXTAFTER) \ + CASE_MATHFN_FLOATN (NEXTAFTER) \ CASE_MATHFN (NEXTTOWARD) \ - CASE_MATHFN (POW) \ + CASE_MATHFN_FLOATN (POW) \ CASE_MATHFN (POWI) \ CASE_MATHFN (POW10) \ - CASE_MATHFN (REMAINDER) \ - CASE_MATHFN (REMQUO) \ + CASE_MATHFN_FLOATN (REMAINDER) \ + CASE_MATHFN_FLOATN (REMQUO) \ CASE_MATHFN_FLOATN (RINT) \ CASE_MATHFN_FLOATN (ROUND) \ CASE_MATHFN_FLOATN (ROUNDEVEN) \ CASE_MATHFN (SCALB) \ - CASE_MATHFN (SCALBLN) \ - CASE_MATHFN (SCALBN) \ + CASE_MATHFN_FLOATN (SCALBLN) \ + CASE_MATHFN_FLOATN (SCALBN) \ CASE_MATHFN (SIGNBIT) \ CASE_MATHFN (SIGNIFICAND) \ - CASE_MATHFN (SIN) \ + CASE_MATHFN_FLOATN (SIN) \ CASE_MATHFN (SINCOS) \ - CASE_MATHFN (SINH) \ + CASE_MATHFN_FLOATN (SINH) \ CASE_MATHFN_FLOATN (SQRT) \ - CASE_MATHFN (TAN) \ - CASE_MATHFN (TANH) \ - CASE_MATHFN (TGAMMA) \ + CASE_MATHFN_FLOATN (TAN) \ + CASE_MATHFN_FLOATN (TANH) \ + CASE_MATHFN_FLOATN (TGAMMA) \ CASE_MATHFN_FLOATN (TRUNC) \ CASE_MATHFN (Y0) \ CASE_MATHFN (Y1) \ @@ -11350,27 +11350,43 @@ builtin_with_linkage_p (tree decl) switch (DECL_FUNCTION_CODE (decl)) { CASE_FLT_FN (BUILT_IN_ACOS): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS): CASE_FLT_FN (BUILT_IN_ACOSH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH): CASE_FLT_FN (BUILT_IN_ASIN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN): CASE_FLT_FN (BUILT_IN_ASINH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINH): CASE_FLT_FN (BUILT_IN_ATAN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN): CASE_FLT_FN (BUILT_IN_ATANH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH): CASE_FLT_FN (BUILT_IN_ATAN2): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2): CASE_FLT_FN (BUILT_IN_CBRT): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_CBRT): CASE_FLT_FN (BUILT_IN_CEIL): CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL): CASE_FLT_FN (BUILT_IN_COPYSIGN): CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN): CASE_FLT_FN (BUILT_IN_COS): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS): CASE_FLT_FN (BUILT_IN_COSH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH): CASE_FLT_FN (BUILT_IN_ERF): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERF): CASE_FLT_FN (BUILT_IN_ERFC): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERFC): CASE_FLT_FN (BUILT_IN_EXP): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP): CASE_FLT_FN (BUILT_IN_EXP2): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2): CASE_FLT_FN (BUILT_IN_EXPM1): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1): CASE_FLT_FN (BUILT_IN_FABS): CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS): CASE_FLT_FN (BUILT_IN_FDIM): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_FDIM): CASE_FLT_FN (BUILT_IN_FLOOR): CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR): CASE_FLT_FN (BUILT_IN_FMA): @@ -11380,43 +11396,71 @@ builtin_with_linkage_p (tree decl) CASE_FLT_FN (BUILT_IN_FMIN): CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMIN): CASE_FLT_FN (BUILT_IN_FMOD): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD): CASE_FLT_FN (BUILT_IN_FREXP): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_FREXP): CASE_FLT_FN (BUILT_IN_HYPOT): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_HYPOT): CASE_FLT_FN (BUILT_IN_ILOGB): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ILOGB): CASE_FLT_FN (BUILT_IN_LDEXP): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LDEXP): CASE_FLT_FN (BUILT_IN_LGAMMA): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LGAMMA): CASE_FLT_FN (BUILT_IN_LLRINT): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLRINT): CASE_FLT_FN (BUILT_IN_LLROUND): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLROUND): CASE_FLT_FN (BUILT_IN_LOG): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG): CASE_FLT_FN (BUILT_IN_LOG10): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10): CASE_FLT_FN (BUILT_IN_LOG1P): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P): CASE_FLT_FN (BUILT_IN_LOG2): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2): CASE_FLT_FN (BUILT_IN_LOGB): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOGB): CASE_FLT_FN (BUILT_IN_LRINT): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LRINT): CASE_FLT_FN (BUILT_IN_LROUND): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LROUND): CASE_FLT_FN (BUILT_IN_MODF): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_MODF): CASE_FLT_FN (BUILT_IN_NAN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_NAN): CASE_FLT_FN (BUILT_IN_NEARBYINT): CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEARBYINT): CASE_FLT_FN (BUILT_IN_NEXTAFTER): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEXTAFTER): CASE_FLT_FN (BUILT_IN_NEXTTOWARD): CASE_FLT_FN (BUILT_IN_POW): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_POW): CASE_FLT_FN (BUILT_IN_REMAINDER): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER): CASE_FLT_FN (BUILT_IN_REMQUO): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMQUO): CASE_FLT_FN (BUILT_IN_RINT): CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT): CASE_FLT_FN (BUILT_IN_ROUND): CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND): CASE_FLT_FN (BUILT_IN_SCALBLN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBLN): CASE_FLT_FN (BUILT_IN_SCALBN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBN): CASE_FLT_FN (BUILT_IN_SIN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN): CASE_FLT_FN (BUILT_IN_SINH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH): CASE_FLT_FN (BUILT_IN_SINCOS): CASE_FLT_FN (BUILT_IN_SQRT): CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT): CASE_FLT_FN (BUILT_IN_TAN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_TAN): CASE_FLT_FN (BUILT_IN_TANH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANH): CASE_FLT_FN (BUILT_IN_TGAMMA): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_TGAMMA): CASE_FLT_FN (BUILT_IN_TRUNC): CASE_FLT_FN_FLOATN_NX (BUILT_IN_TRUNC): return true; diff --git a/gcc/builtins.def b/gcc/builtins.def index 5f2e627..42c005a 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -292,26 +292,40 @@ DEF_C99_C90RES_BUILTIN (BUILT_IN_ACOSF, "acosf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_ DEF_C99_BUILTIN (BUILT_IN_ACOSH, "acosh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ACOSHF, "acoshf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ACOSHL, "acoshl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define ACOSH_TYPE(F) BT_FN_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ACOSH, "acosh", ACOSH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_ACOSL, "acosl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ACOS, "acos", ACOSH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C11_BUILTIN (BUILT_IN_ALIGNED_ALLOC, "aligned_alloc", BT_FN_PTR_SIZE_SIZE, ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST) DEF_LIB_BUILTIN (BUILT_IN_ASIN, "asin", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_ASINF, "asinf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ASINH, "asinh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_ASINHF, "asinhf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_ASINHL, "asinhl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ASINH, "asinh", ACOSH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_C90RES_BUILTIN (BUILT_IN_ASINL, "asinl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ASIN, "asin", ACOSH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef ACOSH_TYPE DEF_LIB_BUILTIN (BUILT_IN_ATAN, "atan", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_LIB_BUILTIN (BUILT_IN_ATAN2, "atan2", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_ATAN2F, "atan2f", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_ATAN2L, "atan2l", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define ATAN2_TYPE(F) BT_FN_##F##_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ATAN2, "atan2", ATAN2_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef ATAN2_TYPE DEF_C99_C90RES_BUILTIN (BUILT_IN_ATANF, "atanf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_ATANH, "atanh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ATANHF, "atanhf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ATANHL, "atanhl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define ATANH_TYPE(F) BT_FN_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ATANH, "atanh", ATANH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_ATANL, "atanl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ATAN, "atan", ATANH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_CBRT, "cbrt", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_CBRTF, "cbrtf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_CBRTL, "cbrtl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CBRT, "cbrt", ATANH_TYPE, ATTR_MATHFN_FPROUNDING) +#undef ATANH_TYPE DEF_LIB_BUILTIN (BUILT_IN_CEIL, "ceil", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILF, "ceilf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILL, "ceill", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -329,7 +343,10 @@ DEF_C99_C90RES_BUILTIN (BUILT_IN_COSF, "cosf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FP DEF_LIB_BUILTIN (BUILT_IN_COSH, "cosh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_COSHF, "coshf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_COSHL, "coshl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define COSH_TYPE(F) BT_FN_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_COSH, "cosh", COSH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_COSL, "cosl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_COS, "cos", COSH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_EXT_LIB_BUILTIN (BUILT_IN_DREM, "drem", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_EXT_LIB_BUILTIN (BUILT_IN_DREMF, "dremf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_EXT_LIB_BUILTIN (BUILT_IN_DREML, "dreml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) @@ -337,8 +354,10 @@ DEF_C99_BUILTIN (BUILT_IN_ERF, "erf", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FP DEF_C99_BUILTIN (BUILT_IN_ERFC, "erfc", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ERFCF, "erfcf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ERFCL, "erfcl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ERFC, "erfc", COSH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ERFF, "erff", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_ERFL, "erfl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ERF, "erf", COSH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_LIB_BUILTIN (BUILT_IN_EXP, "exp", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C2X_BUILTIN (BUILT_IN_EXP10, "exp10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C2X_BUILTIN (BUILT_IN_EXP10F, "exp10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) @@ -346,9 +365,13 @@ DEF_C2X_BUILTIN (BUILT_IN_EXP10L, "exp10l", BT_FN_LONGDOUBLE_LONGDOUBLE, DEF_C99_BUILTIN (BUILT_IN_EXP2, "exp2", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_EXP2F, "exp2f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_EXP2L, "exp2l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_EXP2, "exp2", COSH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_EXPF, "expf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_EXPL, "expl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_EXP, "exp", COSH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_EXPM1, "expm1", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_EXPM1, "expm1", COSH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef COSH_TYPE DEF_C99_BUILTIN (BUILT_IN_EXPM1F, "expm1f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_EXPM1L, "expm1l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_LIB_BUILTIN (BUILT_IN_FABS, "fabs", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -363,6 +386,9 @@ DEF_C2X_BUILTIN (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128 DEF_C99_BUILTIN (BUILT_IN_FDIM, "fdim", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_FDIMF, "fdimf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_FDIML, "fdiml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define FDIM_TYPE(F) BT_FN_##F##_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FDIM, "fdim", FDIM_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef FDIM_TYPE DEF_C99_BUILTIN (BUILT_IN_FECLEAREXCEPT, "feclearexcept", BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_FEGETENV, "fegetenv", BT_FN_INT_FENV_T_PTR, ATTR_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_FEGETEXCEPTFLAG, "fegetexceptflag", BT_FN_INT_FEXCEPT_T_PTR_INT, ATTR_NOTHROW_LEAF_LIST) @@ -397,13 +423,17 @@ DEF_C99_BUILTIN (BUILT_IN_FMINF, "fminf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_C DEF_C99_BUILTIN (BUILT_IN_FMINL, "fminl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) #define FMIN_TYPE(F) BT_FN_##F##_##F##_##F DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FMIN, "fmin", FMIN_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST) -#undef FMIN_TYPE DEF_LIB_BUILTIN (BUILT_IN_FMOD, "fmod", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_FMODF, "fmodf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_FMODL, "fmodl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FMOD, "fmod", FMIN_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef FMIN_TYPE DEF_LIB_BUILTIN (BUILT_IN_FREXP, "frexp", BT_FN_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_C90RES_BUILTIN (BUILT_IN_FREXPF, "frexpf", BT_FN_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_C90RES_BUILTIN (BUILT_IN_FREXPL, "frexpl", BT_FN_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) +#define FREXP_TYPE(F) BT_FN_##F##_##F##_INTPTR +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FREXP, "frexp", FREXP_TYPE, ATTR_MATHFN_FPROUNDING_STORE) +#undef FREXP_TYPE DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMA, "gamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_STORE) DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAF, "gammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_STORE) DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAL, "gammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_STORE) @@ -413,11 +443,15 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAL_R, "gammal_r", BT_FN_LONGDOUBLE_LONGDOUB DEF_GCC_BUILTIN (BUILT_IN_HUGE_VAL, "huge_val", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_HUGE_VALF, "huge_valf", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_HUGE_VALL, "huge_vall", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) -#define INF_TYPE(F) BT_FN_##F -DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_HUGE_VAL, "huge_val", INF_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST) +#define HUGE_VAL_TYPE(F) BT_FN_##F +DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_HUGE_VAL, "huge_val", HUGE_VAL_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST) +#undef HUGE_VAL_TYPE DEF_C99_BUILTIN (BUILT_IN_HYPOT, "hypot", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_HYPOTF, "hypotf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_HYPOTL, "hypotl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define HYPOT_TYPE(F) BT_FN_##F##_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_HYPOT, "hypot", HYPOT_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef HYPOT_TYPE DEF_GCC_BUILTIN (BUILT_IN_ICEIL, "iceil", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_ICEILF, "iceilf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_ICEILL, "iceill", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -427,9 +461,13 @@ DEF_GCC_BUILTIN (BUILT_IN_IFLOORL, "ifloorl", BT_FN_INT_LONGDOUBLE, ATTR_ DEF_C99_BUILTIN (BUILT_IN_ILOGB, "ilogb", BT_FN_INT_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ILOGBF, "ilogbf", BT_FN_INT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_ILOGBL, "ilogbl", BT_FN_INT_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define ILOGB_TYPE(F) BT_FN_INT_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ILOGB, "ilogb", ILOGB_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef ILOGB_TYPE DEF_GCC_BUILTIN (BUILT_IN_INF, "inf", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_INFF, "inff", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_INFL, "infl", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) +#define INF_TYPE(F) BT_FN_##F DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_INF, "inf", INF_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST) #undef INF_TYPE DEF_GCC_BUILTIN (BUILT_IN_INFD32, "infd32", BT_FN_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -456,12 +494,18 @@ DEF_GCC_BUILTIN (BUILT_IN_LCEILL, "lceill", BT_FN_LONG_LONGDOUBLE, ATTR_C DEF_LIB_BUILTIN (BUILT_IN_LDEXP, "ldexp", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPF, "ldexpf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPL, "ldexpl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO) +#define LDEXP_TYPE(F) BT_FN_##F##_##F##_INT +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LDEXP, "ldexp", LDEXP_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef LDEXP_TYPE DEF_GCC_BUILTIN (BUILT_IN_LFLOOR, "lfloor", BT_FN_LONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_LFLOORF, "lfloorf", BT_FN_LONG_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_LFLOORL, "lfloorl", BT_FN_LONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_LGAMMA, "lgamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_BUILTIN (BUILT_IN_LGAMMAF, "lgammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_BUILTIN (BUILT_IN_LGAMMAL, "lgammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_STORE) +#define LGAMMA_TYPE(F) BT_FN_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LGAMMA, "lgamma", LGAMMA_TYPE, ATTR_MATHFN_FPROUNDING_STORE) +#undef LGAMMA_TYPE DEF_EXT_LIB_BUILTIN (BUILT_IN_LGAMMA_R, "lgamma_r", BT_FN_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_EXT_LIB_BUILTIN (BUILT_IN_LGAMMAF_R, "lgammaf_r", BT_FN_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_EXT_LIB_BUILTIN (BUILT_IN_LGAMMAL_R, "lgammal_r", BT_FN_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) @@ -474,33 +518,51 @@ DEF_GCC_BUILTIN (BUILT_IN_LLFLOORL, "llfloorl", BT_FN_LONGLONG_LONGDOUBLE DEF_C99_BUILTIN (BUILT_IN_LLRINT, "llrint", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LLRINTF, "llrintf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LLRINTL, "llrintl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define LLRINT_TYPE(F) BT_FN_LONGLONG_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LLRINT, "llrint", LLRINT_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LLROUND, "llround", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LLROUNDF, "llroundf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LLROUNDL, "llroundl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LLROUND, "llround", LLRINT_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef LLRINT_TYPE DEF_LIB_BUILTIN (BUILT_IN_LOG, "log", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_LIB_BUILTIN (BUILT_IN_LOG10, "log10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_LOG10F, "log10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_LOG10L, "log10l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define LOG10_TYPE(F) BT_FN_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LOG10, "log10", LOG10_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOG1P, "log1p", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOG1PF, "log1pf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOG1PL, "log1pl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LOG1P, "log1p", LOG10_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOG2, "log2", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOG2F, "log2f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOG2L, "log2l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LOG2, "log2", LOG10_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOGB, "logb", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOGBF, "logbf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LOGBL, "logbl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LOGB, "logb", LOG10_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_LOGF, "logf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_LOGL, "logl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LOG, "log", LOG10_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef LOG10_TYPE DEF_C99_BUILTIN (BUILT_IN_LRINT, "lrint", BT_FN_LONG_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LRINTF, "lrintf", BT_FN_LONG_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LRINTL, "lrintl", BT_FN_LONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define LRINT_TYPE(F) BT_FN_LONG_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LRINT, "lrint", LRINT_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LROUND, "lround", BT_FN_LONG_DOUBLE, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LROUNDF, "lroundf", BT_FN_LONG_FLOAT, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LROUNDL, "lroundl", BT_FN_LONG_LONGDOUBLE, ATTR_MATHFN_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_LROUND, "lround", LRINT_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef LRINT_TYPE DEF_LIB_BUILTIN (BUILT_IN_MODF, "modf", BT_FN_DOUBLE_DOUBLE_DOUBLEPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_C90RES_BUILTIN (BUILT_IN_MODFF, "modff", BT_FN_FLOAT_FLOAT_FLOATPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_C90RES_BUILTIN (BUILT_IN_MODFL, "modfl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLEPTR, ATTR_MATHFN_FPROUNDING_STORE) +#define MODF_TYPE(F) BT_FN_##F##_##F##_##F##PTR +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_MODF, "modf", MODF_TYPE, ATTR_MATHFN_FPROUNDING_STORE) +#undef MODF_TYPE DEF_C99_BUILTIN (BUILT_IN_NAN, "nan", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_C99_BUILTIN (BUILT_IN_NANF, "nanf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_C99_BUILTIN (BUILT_IN_NANL, "nanl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) @@ -527,6 +589,8 @@ DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_NEARBYINT, "nearbyint", NEARBYINT_TYPE, DEF_C99_BUILTIN (BUILT_IN_NEXTAFTER, "nextafter", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_NEXTAFTERF, "nextafterf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_NEXTAFTERL, "nextafterl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO) +#define NEXTAFTER_TYPE(F) BT_FN_##F##_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_NEXTAFTER, "nextafter", NEXTAFTER_TYPE, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARD, "nexttoward", BT_FN_DOUBLE_DOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARDF, "nexttowardf", BT_FN_FLOAT_FLOAT_LONGDOUBLE, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARDL, "nexttowardl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO) @@ -539,12 +603,18 @@ DEF_GCC_BUILTIN (BUILT_IN_POWI, "powi", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MAT DEF_GCC_BUILTIN (BUILT_IN_POWIF, "powif", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING) DEF_GCC_BUILTIN (BUILT_IN_POWIL, "powil", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING) DEF_C99_C90RES_BUILTIN (BUILT_IN_POWL, "powl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_POW, "pow", NEXTAFTER_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_REMAINDER, "remainder", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_REMAINDERF, "remainderf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_REMAINDERL, "remainderl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_REMAINDER, "remainder", NEXTAFTER_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef NEXTAFTER_TYPE DEF_C99_BUILTIN (BUILT_IN_REMQUO, "remquo", BT_FN_DOUBLE_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_BUILTIN (BUILT_IN_REMQUOF, "remquof", BT_FN_FLOAT_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_BUILTIN (BUILT_IN_REMQUOL, "remquol", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) +#define REMQUO_TYPE(F) BT_FN_##F##_##F##_##F##_INTPTR +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_REMQUO, "remquo", REMQUO_TYPE, ATTR_MATHFN_FPROUNDING_STORE) +#undef REMQUO_TYPE DEF_C99_BUILTIN (BUILT_IN_RINT, "rint", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_RINTF, "rintf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_RINTL, "rintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) @@ -569,9 +639,15 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_SCALBL, "scalbl", BT_FN_LONGDOUBLE_LONGDOUBLE_L DEF_C99_BUILTIN (BUILT_IN_SCALBLN, "scalbln", BT_FN_DOUBLE_DOUBLE_LONG, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_SCALBLNF, "scalblnf", BT_FN_FLOAT_FLOAT_LONG, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_SCALBLNL, "scalblnl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONG, ATTR_MATHFN_FPROUNDING_ERRNO) +#define SCALBLN_TYPE(F) BT_FN_##F##_##F##_LONG +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_SCALBLN, "scalbln", SCALBLN_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef SCALBLN_TYPE DEF_C99_BUILTIN (BUILT_IN_SCALBN, "scalbn", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_SCALBNF, "scalbnf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_SCALBNL, "scalbnl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO) +#define SCALBN_TYPE(F) BT_FN_##F##_##F##_INT +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_SCALBN, "scalbn", SCALBN_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef SCALBN_TYPE DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBIT, "signbit", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITF, "signbitf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITL, "signbitl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -589,22 +665,29 @@ DEF_C99_C90RES_BUILTIN (BUILT_IN_SINF, "sinf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FP DEF_LIB_BUILTIN (BUILT_IN_SINH, "sinh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_SINHF, "sinhf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_SINHL, "sinhl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +#define SINH_TYPE(F) BT_FN_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_SINH, "sinh", SINH_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_SINL, "sinl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_SIN, "sin", SINH_TYPE, ATTR_MATHFN_FPROUNDING) +#undef SINH_TYPE DEF_LIB_BUILTIN (BUILT_IN_SQRT, "sqrt", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_SQRTF, "sqrtf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_SQRTL, "sqrtl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) #define SQRT_TYPE(F) BT_FN_##F##_##F DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_SQRT, "sqrt", SQRT_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) -#undef SQRT_TYPE DEF_LIB_BUILTIN (BUILT_IN_TAN, "tan", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_C90RES_BUILTIN (BUILT_IN_TANF, "tanf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_LIB_BUILTIN (BUILT_IN_TANH, "tanh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_C90RES_BUILTIN (BUILT_IN_TANHF, "tanhf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_C90RES_BUILTIN (BUILT_IN_TANHL, "tanhl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_TANH, "tanh", SQRT_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_C90RES_BUILTIN (BUILT_IN_TANL, "tanl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_TAN, "tan", SQRT_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_TGAMMA, "tgamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_TGAMMAF, "tgammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_TGAMMAL, "tgammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_TGAMMA, "tgamma", SQRT_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO) +#undef SQRT_TYPE DEF_C99_BUILTIN (BUILT_IN_TRUNC, "trunc", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_TRUNCF, "truncf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_TRUNCL, "truncl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc index 7e0d671..5f15815 100644 --- a/gcc/fold-const-call.cc +++ b/gcc/fold-const-call.cc @@ -734,64 +734,82 @@ fold_const_call_ss (real_value *result, combined_fn fn, && do_mpfr_arg1 (result, mpfr_sqrt, arg, format)); CASE_CFN_CBRT: + CASE_CFN_CBRT_FN: return do_mpfr_arg1 (result, mpfr_cbrt, arg, format); CASE_CFN_ASIN: + CASE_CFN_ASIN_FN: return (real_compare (GE_EXPR, arg, &dconstm1) && real_compare (LE_EXPR, arg, &dconst1) && do_mpfr_arg1 (result, mpfr_asin, arg, format)); CASE_CFN_ACOS: + CASE_CFN_ACOS_FN: return (real_compare (GE_EXPR, arg, &dconstm1) && real_compare (LE_EXPR, arg, &dconst1) && do_mpfr_arg1 (result, mpfr_acos, arg, format)); CASE_CFN_ATAN: + CASE_CFN_ATAN_FN: return do_mpfr_arg1 (result, mpfr_atan, arg, format); CASE_CFN_ASINH: + CASE_CFN_ASINH_FN: return do_mpfr_arg1 (result, mpfr_asinh, arg, format); CASE_CFN_ACOSH: + CASE_CFN_ACOSH_FN: return (real_compare (GE_EXPR, arg, &dconst1) && do_mpfr_arg1 (result, mpfr_acosh, arg, format)); CASE_CFN_ATANH: + CASE_CFN_ATANH_FN: return (real_compare (GE_EXPR, arg, &dconstm1) && real_compare (LE_EXPR, arg, &dconst1) && do_mpfr_arg1 (result, mpfr_atanh, arg, format)); CASE_CFN_SIN: + CASE_CFN_SIN_FN: return do_mpfr_arg1 (result, mpfr_sin, arg, format); CASE_CFN_COS: + CASE_CFN_COS_FN: return do_mpfr_arg1 (result, mpfr_cos, arg, format); CASE_CFN_TAN: + CASE_CFN_TAN_FN: return do_mpfr_arg1 (result, mpfr_tan, arg, format); CASE_CFN_SINH: + CASE_CFN_SINH_FN: return do_mpfr_arg1 (result, mpfr_sinh, arg, format); CASE_CFN_COSH: + CASE_CFN_COSH_FN: return do_mpfr_arg1 (result, mpfr_cosh, arg, format); CASE_CFN_TANH: + CASE_CFN_TANH_FN: return do_mpfr_arg1 (result, mpfr_tanh, arg, format); CASE_CFN_ERF: + CASE_CFN_ERF_FN: return do_mpfr_arg1 (result, mpfr_erf, arg, format); CASE_CFN_ERFC: + CASE_CFN_ERFC_FN: return do_mpfr_arg1 (result, mpfr_erfc, arg, format); CASE_CFN_TGAMMA: + CASE_CFN_TGAMMA_FN: return do_mpfr_arg1 (result, mpfr_gamma, arg, format); CASE_CFN_EXP: + CASE_CFN_EXP_FN: return do_mpfr_arg1 (result, mpfr_exp, arg, format); CASE_CFN_EXP2: + CASE_CFN_EXP2_FN: return do_mpfr_arg1 (result, mpfr_exp2, arg, format); CASE_CFN_EXP10: @@ -799,21 +817,26 @@ fold_const_call_ss (real_value *result, combined_fn fn, return do_mpfr_arg1 (result, mpfr_exp10, arg, format); CASE_CFN_EXPM1: + CASE_CFN_EXPM1_FN: return do_mpfr_arg1 (result, mpfr_expm1, arg, format); CASE_CFN_LOG: + CASE_CFN_LOG_FN: return (real_compare (GT_EXPR, arg, &dconst0) && do_mpfr_arg1 (result, mpfr_log, arg, format)); CASE_CFN_LOG2: + CASE_CFN_LOG2_FN: return (real_compare (GT_EXPR, arg, &dconst0) && do_mpfr_arg1 (result, mpfr_log2, arg, format)); CASE_CFN_LOG10: + CASE_CFN_LOG10_FN: return (real_compare (GT_EXPR, arg, &dconst0) && do_mpfr_arg1 (result, mpfr_log10, arg, format)); CASE_CFN_LOG1P: + CASE_CFN_LOG1P_FN: return (real_compare (GT_EXPR, arg, &dconstm1) && do_mpfr_arg1 (result, mpfr_log1p, arg, format)); @@ -877,6 +900,7 @@ fold_const_call_ss (real_value *result, combined_fn fn, return false; CASE_CFN_LOGB: + CASE_CFN_LOGB_FN: return fold_const_logb (result, arg, format); CASE_CFN_SIGNIFICAND: @@ -909,6 +933,7 @@ fold_const_call_ss (wide_int *result, combined_fn fn, return true; CASE_CFN_ILOGB: + CASE_CFN_ILOGB_FN: /* For ilogb we don't know FP_ILOGB0, so only handle normal values. Proceed iff radix == 2. In GCC, normalized significands are in the range [0.5, 1.0). We want the exponent as if they were @@ -934,13 +959,17 @@ fold_const_call_ss (wide_int *result, combined_fn fn, CASE_CFN_IROUND: CASE_CFN_LROUND: + CASE_CFN_LROUND_FN: CASE_CFN_LLROUND: + CASE_CFN_LLROUND_FN: return fold_const_conversion (result, real_round, arg, precision, format); CASE_CFN_IRINT: CASE_CFN_LRINT: + CASE_CFN_LRINT_FN: CASE_CFN_LLRINT: + CASE_CFN_LLRINT_FN: /* Not yet folded to a constant. */ return false; @@ -1370,18 +1399,23 @@ fold_const_call_sss (real_value *result, combined_fn fn, { CASE_CFN_DREM: CASE_CFN_REMAINDER: + CASE_CFN_REMAINDER_FN: return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format); CASE_CFN_ATAN2: + CASE_CFN_ATAN2_FN: return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format); CASE_CFN_FDIM: + CASE_CFN_FDIM_FN: return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format); CASE_CFN_FMOD: + CASE_CFN_FMOD_FN: return do_mpfr_arg2 (result, mpfr_fmod, arg0, arg1, format); CASE_CFN_HYPOT: + CASE_CFN_HYPOT_FN: return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format); CASE_CFN_COPYSIGN: @@ -1399,9 +1433,11 @@ fold_const_call_sss (real_value *result, combined_fn fn, return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format); CASE_CFN_POW: + CASE_CFN_POW_FN: return fold_const_pow (result, arg0, arg1, format); CASE_CFN_NEXTAFTER: + CASE_CFN_NEXTAFTER_FN: CASE_CFN_NEXTTOWARD: return fold_const_nextafter (result, arg0, arg1, format); @@ -1425,10 +1461,13 @@ fold_const_call_sss (real_value *result, combined_fn fn, switch (fn) { CASE_CFN_LDEXP: + CASE_CFN_LDEXP_FN: return fold_const_builtin_load_exponent (result, arg0, arg1, format); CASE_CFN_SCALBN: + CASE_CFN_SCALBN_FN: CASE_CFN_SCALBLN: + CASE_CFN_SCALBLN_FN: return (format->b == 2 && fold_const_builtin_load_exponent (result, arg0, arg1, format)); diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 9f7beae..16384a8 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -14797,16 +14797,25 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, switch (fn) { CASE_CFN_ACOS: + CASE_CFN_ACOS_FN: CASE_CFN_ACOSH: + CASE_CFN_ACOSH_FN: CASE_CFN_CABS: CASE_CFN_COSH: + CASE_CFN_COSH_FN: CASE_CFN_ERFC: + CASE_CFN_ERFC_FN: CASE_CFN_EXP: + CASE_CFN_EXP_FN: CASE_CFN_EXP10: CASE_CFN_EXP2: + CASE_CFN_EXP2_FN: CASE_CFN_FABS: + CASE_CFN_FABS_FN: CASE_CFN_FDIM: + CASE_CFN_FDIM_FN: CASE_CFN_HYPOT: + CASE_CFN_HYPOT_FN: CASE_CFN_POW10: CASE_CFN_FFS: CASE_CFN_PARITY: @@ -14828,17 +14837,25 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, return RECURSE (arg0); CASE_CFN_ASINH: + CASE_CFN_ASINH_FN: CASE_CFN_ATAN: + CASE_CFN_ATAN_FN: CASE_CFN_ATANH: + CASE_CFN_ATANH_FN: CASE_CFN_CBRT: + CASE_CFN_CBRT_FN: CASE_CFN_CEIL: CASE_CFN_CEIL_FN: CASE_CFN_ERF: + CASE_CFN_ERF_FN: CASE_CFN_EXPM1: + CASE_CFN_EXPM1_FN: CASE_CFN_FLOOR: CASE_CFN_FLOOR_FN: CASE_CFN_FMOD: + CASE_CFN_FMOD_FN: CASE_CFN_FREXP: + CASE_CFN_FREXP_FN: CASE_CFN_ICEIL: CASE_CFN_IFLOOR: CASE_CFN_IRINT: @@ -14849,10 +14866,15 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_LLCEIL: CASE_CFN_LLFLOOR: CASE_CFN_LLRINT: + CASE_CFN_LLRINT_FN: CASE_CFN_LLROUND: + CASE_CFN_LLROUND_FN: CASE_CFN_LRINT: + CASE_CFN_LRINT_FN: CASE_CFN_LROUND: + CASE_CFN_LROUND_FN: CASE_CFN_MODF: + CASE_CFN_MODF_FN: CASE_CFN_NEARBYINT: CASE_CFN_NEARBYINT_FN: CASE_CFN_RINT: @@ -14863,11 +14885,15 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_ROUNDEVEN_FN: CASE_CFN_SCALB: CASE_CFN_SCALBLN: + CASE_CFN_SCALBLN_FN: CASE_CFN_SCALBN: + CASE_CFN_SCALBN_FN: CASE_CFN_SIGNBIT: CASE_CFN_SIGNIFICAND: CASE_CFN_SINH: + CASE_CFN_SINH_FN: CASE_CFN_TANH: + CASE_CFN_TANH_FN: CASE_CFN_TRUNC: CASE_CFN_TRUNC_FN: /* True if the 1st argument is nonnegative. */ @@ -14907,6 +14933,7 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, return RECURSE (arg0); CASE_CFN_POW: + CASE_CFN_POW_FN: /* True if the 1st argument is nonnegative or the second argument is an even integer valued real. */ if (TREE_CODE (arg1) == REAL_CST) diff --git a/gcc/testsuite/gcc.dg/torture/floatn-builtin.h b/gcc/testsuite/gcc.dg/torture/floatn-builtin.h index c562812..304a459 100644 --- a/gcc/testsuite/gcc.dg/torture/floatn-builtin.h +++ b/gcc/testsuite/gcc.dg/torture/floatn-builtin.h @@ -20,6 +20,9 @@ extern void exit (int); extern void abort (void); +extern int test_i; +extern long int test_l; +extern long long int test_ll; extern TYPE test_type; extern __typeof (FN (__builtin_inf) ()) test_type; extern __typeof (FN (__builtin_huge_val) ()) test_type; @@ -27,12 +30,91 @@ extern __typeof (FN (__builtin_nan) ("")) test_type; extern __typeof (FN (__builtin_nans) ("")) test_type; extern __typeof (FN (__builtin_fabs) (0)) test_type; extern __typeof (FN (__builtin_copysign) (0, 0)) test_type; +extern __typeof (FN (__builtin_acosh) (0)) test_type; +extern __typeof (FN (__builtin_acos) (0)) test_type; +extern __typeof (FN (__builtin_asinh) (0)) test_type; +extern __typeof (FN (__builtin_asin) (0)) test_type; +extern __typeof (FN (__builtin_atanh) (0)) test_type; +extern __typeof (FN (__builtin_atan) (0)) test_type; +extern __typeof (FN (__builtin_cbrt) (0)) test_type; +extern __typeof (FN (__builtin_cosh) (0)) test_type; +extern __typeof (FN (__builtin_cos) (0)) test_type; +extern __typeof (FN (__builtin_erfc) (0)) test_type; +extern __typeof (FN (__builtin_erf) (0)) test_type; +extern __typeof (FN (__builtin_exp2) (0)) test_type; +extern __typeof (FN (__builtin_exp) (0)) test_type; +extern __typeof (FN (__builtin_expm1) (0)) test_type; +extern __typeof (FN (__builtin_lgamma) (0)) test_type; +extern __typeof (FN (__builtin_log10) (0)) test_type; +extern __typeof (FN (__builtin_log1p) (0)) test_type; +extern __typeof (FN (__builtin_log2) (0)) test_type; +extern __typeof (FN (__builtin_logb) (0)) test_type; +extern __typeof (FN (__builtin_log) (0)) test_type; +extern __typeof (FN (__builtin_nextafter) (0, 0)) test_type; +extern __typeof (FN (__builtin_sinh) (0)) test_type; +extern __typeof (FN (__builtin_sin) (0)) test_type; +extern __typeof (FN (__builtin_tanh) (0)) test_type; +extern __typeof (FN (__builtin_tan) (0)) test_type; +extern __typeof (FN (__builtin_tgamma) (0)) test_type; +extern __typeof (FN (__builtin_atan2) (0, 0)) test_type; +extern __typeof (FN (__builtin_fdim) (0, 0)) test_type; +extern __typeof (FN (__builtin_fmod) (0, 0)) test_type; +extern __typeof (FN (__builtin_frexp) (0, &test_i)) test_type; +extern __typeof (FN (__builtin_ldexp) (0, 0)) test_type; +extern __typeof (FN (__builtin_hypot) (0, 0)) test_type; +extern __typeof (FN (__builtin_ilogb) (0)) test_i; +extern __typeof (FN (__builtin_llrint) (0)) test_ll; +extern __typeof (FN (__builtin_llround) (0)) test_ll; +extern __typeof (FN (__builtin_lrint) (0)) test_l; +extern __typeof (FN (__builtin_lround) (0)) test_l; +extern __typeof (FN (__builtin_modf) (0, &test_type)) test_type; +extern __typeof (FN (__builtin_pow) (0, 0)) test_type; +extern __typeof (FN (__builtin_remainder) (0, 0)) test_type; +extern __typeof (FN (__builtin_remquo) (0, 0, &test_i)) test_type; +extern __typeof (FN (__builtin_scalbln) (0, 0L)) test_type; +extern __typeof (FN (__builtin_scalbn) (0, 0)) test_type; volatile TYPE inf_cst = FN (__builtin_inf) (); volatile TYPE huge_val_cst = FN (__builtin_huge_val) (); volatile TYPE nan_cst = FN (__builtin_nan) (""); volatile TYPE nans_cst = FN (__builtin_nans) (""); volatile TYPE neg0 = -CST (0.0), neg1 = -CST (1.0), one = 1.0; +volatile TYPE t1 = FN (__builtin_acosh) (CST (1.0)); +volatile TYPE t2 = FN (__builtin_acos) (CST (1.0)); +volatile TYPE t3 = FN (__builtin_asinh) (CST (0.0)); +volatile TYPE t4 = FN (__builtin_asin) (CST (0.0)); +volatile TYPE t5 = FN (__builtin_atanh) (CST (0.0)); +volatile TYPE t6 = FN (__builtin_atan) (CST (0.0)); +volatile TYPE t7 = FN (__builtin_cbrt) (CST (27.0)); +volatile TYPE t8 = FN (__builtin_cosh) (CST (0.0)); +volatile TYPE t9 = FN (__builtin_cos) (CST (0.0)); +volatile TYPE t10 = FN (__builtin_erfc) (CST (0.0)); +volatile TYPE t11 = FN (__builtin_erf) (CST (0.0)); +volatile TYPE t12 = FN (__builtin_exp2) (CST (1.0)); +volatile TYPE t13 = FN (__builtin_exp) (CST (0.0)); +volatile TYPE t14 = FN (__builtin_expm1) (CST (0.0)); +volatile TYPE t15 = FN (__builtin_log10) (CST (1.0)); +volatile TYPE t16 = FN (__builtin_log1p) (CST (0.0)); +volatile TYPE t17 = FN (__builtin_log2) (CST (1.0)); +volatile TYPE t18 = FN (__builtin_logb) (CST (1.0)); +volatile TYPE t19 = FN (__builtin_log) (CST (1.0)); +volatile TYPE t20 = FN (__builtin_nextafter) (CST (0.0), CST (0.0)); +volatile TYPE t21 = FN (__builtin_sinh) (CST (0.0)); +volatile TYPE t22 = FN (__builtin_sin) (CST (0.0)); +volatile TYPE t23 = FN (__builtin_tanh) (CST (0.0)); +volatile TYPE t24 = FN (__builtin_tan) (CST (0.0)); +volatile TYPE t25 = FN (__builtin_atan2) (CST (0.0), CST (1.0)); +volatile TYPE t26 = FN (__builtin_fdim) (CST (0.0), CST (0.0)); +volatile TYPE t27 = FN (__builtin_fmod) (CST (0.0), CST (1.0)); +volatile TYPE t28 = FN (__builtin_ldexp) (CST (1.0), 1); +volatile TYPE t29 = FN (__builtin_hypot) (CST (3.0), CST (4.0)); +volatile int t30 = FN (__builtin_ilogb) (CST (1.0)); +volatile long long int t31 = FN (__builtin_llround) (CST (42.25)); +volatile long int t32 = FN (__builtin_lround) (CST (42.25)); +volatile TYPE t33 = FN (__builtin_pow) (CST (1.0), CST (2.0)); +volatile TYPE t34 = FN (__builtin_remainder) (CST (7.0), CST (4.0)); +volatile TYPE t35 = FN (__builtin_scalbln) (CST (1.0), 1L); +volatile TYPE t36 = FN (__builtin_scalbn) (CST (1.0), 1); int main (void) @@ -60,5 +142,77 @@ main (void) r = FN (__builtin_copysign) (-inf_cst, one); if (r != huge_val_cst) abort (); + if (t1 != CST (0.0)) + abort (); + if (t2 != CST (0.0)) + abort (); + if (t3 != CST (0.0)) + abort (); + if (t4 != CST (0.0)) + abort (); + if (t5 != CST (0.0)) + abort (); + if (t6 != CST (0.0)) + abort (); + if (t7 != CST (3.0)) + abort (); + if (t8 != CST (1.0)) + abort (); + if (t9 != CST (1.0)) + abort (); + if (t10 != CST (1.0)) + abort (); + if (t11 != CST (0.0)) + abort (); + if (t12 != CST (2.0)) + abort (); + if (t13 != CST (1.0)) + abort (); + if (t14 != CST (0.0)) + abort (); + if (t15 != CST (0.0)) + abort (); + if (t16 != CST (0.0)) + abort (); + if (t17 != CST (0.0)) + abort (); + if (t18 != CST (0.0)) + abort (); + if (t19 != CST (0.0)) + abort (); + if (t20 != CST (0.0)) + abort (); + if (t21 != CST (0.0)) + abort (); + if (t22 != CST (0.0)) + abort (); + if (t23 != CST (0.0)) + abort (); + if (t24 != CST (0.0)) + abort (); + if (t25 != CST (0.0)) + abort (); + if (t26 != CST (0.0)) + abort (); + if (t27 != CST (0.0)) + abort (); + if (t28 != CST (2.0)) + abort (); + if (t29 != CST (5.0)) + abort (); + if (t30 != 0) + abort (); + if (t31 != 42) + abort (); + if (t32 != 42) + abort (); + if (t33 != CST (1.0)) + abort (); + if (t34 != -CST (1.0)) + abort (); + if (t35 != CST (2.0)) + abort (); + if (t36 != CST (2.0)) + abort (); exit (0); } diff --git a/gcc/tree-call-cdce.cc b/gcc/tree-call-cdce.cc index feb61f3..b4b14a0 100644 --- a/gcc/tree-call-cdce.cc +++ b/gcc/tree-call-cdce.cc @@ -295,22 +295,35 @@ can_test_argument_range (gcall *call) { /* Trig functions. */ CASE_FLT_FN (BUILT_IN_ACOS): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS): CASE_FLT_FN (BUILT_IN_ASIN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN): /* Hyperbolic functions. */ CASE_FLT_FN (BUILT_IN_ACOSH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH): CASE_FLT_FN (BUILT_IN_ATANH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH): CASE_FLT_FN (BUILT_IN_COSH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH): CASE_FLT_FN (BUILT_IN_SINH): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH): /* Log functions. */ CASE_FLT_FN (BUILT_IN_LOG): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG): CASE_FLT_FN (BUILT_IN_LOG2): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2): CASE_FLT_FN (BUILT_IN_LOG10): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10): CASE_FLT_FN (BUILT_IN_LOG1P): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P): /* Exp functions. */ CASE_FLT_FN (BUILT_IN_EXP): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP): CASE_FLT_FN (BUILT_IN_EXP2): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2): CASE_FLT_FN (BUILT_IN_EXP10): CASE_FLT_FN (BUILT_IN_EXPM1): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1): CASE_FLT_FN (BUILT_IN_POW10): /* Sqrt. */ CASE_FLT_FN (BUILT_IN_SQRT): @@ -337,15 +350,22 @@ edom_only_function (gcall *call) switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call))) { CASE_FLT_FN (BUILT_IN_ACOS): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS): CASE_FLT_FN (BUILT_IN_ASIN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN): CASE_FLT_FN (BUILT_IN_ATAN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN): CASE_FLT_FN (BUILT_IN_COS): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS): CASE_FLT_FN (BUILT_IN_SIGNIFICAND): CASE_FLT_FN (BUILT_IN_SIN): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN): CASE_FLT_FN (BUILT_IN_SQRT): CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT): CASE_FLT_FN (BUILT_IN_FMOD): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD): CASE_FLT_FN (BUILT_IN_REMAINDER): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER): return true; default: -- cgit v1.1 From 29490c2a1dc00944f2420eb59374705f180a2e53 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 31 Oct 2022 09:07:04 +0100 Subject: builtins: Add __builtin_nextafterf16b builtin The following patch adds another needed builtin. The earlier patch adds among other things __builtin_nextafterf16 builtin which we need in order to constexpr evaluate std::nextafter(_Float16) overload (patch for that has been posted already). While there is inline implementation of the overload, it isn't constant evaluation friendly, and the builtin doesn't need libm implementation because it will be used only during constant expression evaluation. We need the same thing also for std::nextafter(__gnu_cxx::__bfloat16_t) though and this patch does that. 2022-10-31 Jakub Jelinek * builtin-types.def (BT_FN_BFLOAT16_BFLOAT16_BFLOAT16): New. * builtins.def (BUILT_IN_NEXTAFTERF16B): New builtin. * fold-const-call.cc (fold_const_call_sss): Handle CFN_BUILT_IN_NEXTAFTERF16B. --- gcc/builtin-types.def | 2 ++ gcc/builtins.def | 1 + gcc/fold-const-call.cc | 1 + 3 files changed, 4 insertions(+) (limited to 'gcc') diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index 2dbed8a..81460e1 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -461,6 +461,8 @@ DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64X_FLOAT64X_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X) DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128X_FLOAT128X_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X) +DEF_FUNCTION_TYPE_2 (BT_FN_BFLOAT16_BFLOAT16_BFLOAT16, + BT_BFLOAT16, BT_BFLOAT16, BT_BFLOAT16) DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_FLOATPTR, BT_FLOAT, BT_FLOAT, BT_FLOAT_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_DOUBLEPTR, diff --git a/gcc/builtins.def b/gcc/builtins.def index 42c005a..4997315 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -591,6 +591,7 @@ DEF_C99_BUILTIN (BUILT_IN_NEXTAFTERF, "nextafterf", BT_FN_FLOAT_FLOAT_FLO DEF_C99_BUILTIN (BUILT_IN_NEXTAFTERL, "nextafterl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO) #define NEXTAFTER_TYPE(F) BT_FN_##F##_##F##_##F DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_NEXTAFTER, "nextafter", NEXTAFTER_TYPE, ATTR_MATHFN_ERRNO) +DEF_GCC_BUILTIN (BUILT_IN_NEXTAFTERF16B, "nextafterf16b", BT_FN_BFLOAT16_BFLOAT16_BFLOAT16, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARD, "nexttoward", BT_FN_DOUBLE_DOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARDF, "nexttowardf", BT_FN_FLOAT_FLOAT_LONGDOUBLE, ATTR_MATHFN_ERRNO) DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARDL, "nexttowardl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO) diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc index 5f15815..ab1b098 100644 --- a/gcc/fold-const-call.cc +++ b/gcc/fold-const-call.cc @@ -1438,6 +1438,7 @@ fold_const_call_sss (real_value *result, combined_fn fn, CASE_CFN_NEXTAFTER: CASE_CFN_NEXTAFTER_FN: + case CFN_BUILT_IN_NEXTAFTERF16B: CASE_CFN_NEXTTOWARD: return fold_const_nextafter (result, arg0, arg1, format); -- cgit v1.1 From 259a11555c90783e53c046c310080407ee54a31e Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 31 Oct 2022 09:09:48 +0100 Subject: builtins: Add various complex builtins for _Float{16,32,64,128,32x,64x,128x} The following patch adds some complex builtins which have libm implementation in glibc 2.26 and later on various arches. It is needed for libstdc++ _Float128 support when long double is not IEEE quad. 2022-10-31 Jakub Jelinek * builtin-types.def (BT_COMPLEX_FLOAT16, BT_COMPLEX_FLOAT32, BT_COMPLEX_FLOAT64, BT_COMPLEX_FLOAT128, BT_COMPLEX_FLOAT32X, BT_COMPLEX_FLOAT64X, BT_COMPLEX_FLOAT128X, BT_FN_COMPLEX_FLOAT16_COMPLEX_FLOAT16, BT_FN_COMPLEX_FLOAT32_COMPLEX_FLOAT32, BT_FN_COMPLEX_FLOAT64_COMPLEX_FLOAT64, BT_FN_COMPLEX_FLOAT128_COMPLEX_FLOAT128, BT_FN_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X, BT_FN_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X, BT_FN_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X, BT_FN_FLOAT16_COMPLEX_FLOAT16, BT_FN_FLOAT32_COMPLEX_FLOAT32, BT_FN_FLOAT64_COMPLEX_FLOAT64, BT_FN_FLOAT128_COMPLEX_FLOAT128, BT_FN_FLOAT32X_COMPLEX_FLOAT32X, BT_FN_FLOAT64X_COMPLEX_FLOAT64X, BT_FN_FLOAT128X_COMPLEX_FLOAT128X, BT_FN_COMPLEX_FLOAT16_COMPLEX_FLOAT16_COMPLEX_FLOAT16, BT_FN_COMPLEX_FLOAT32_COMPLEX_FLOAT32_COMPLEX_FLOAT32, BT_FN_COMPLEX_FLOAT64_COMPLEX_FLOAT64_COMPLEX_FLOAT64, BT_FN_COMPLEX_FLOAT128_COMPLEX_FLOAT128_COMPLEX_FLOAT128, BT_FN_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X, BT_FN_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X, BT_FN_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X): New. * builtins.def (CABS_TYPE, CACOSH_TYPE, CARG_TYPE, CASINH_TYPE, CPOW_TYPE, CPROJ_TYPE): Define and undefine later. (BUILT_IN_CABS, BUILT_IN_CACOSH, BUILT_IN_CACOS, BUILT_IN_CARG, BUILT_IN_CASINH, BUILT_IN_CASIN, BUILT_IN_CATANH, BUILT_IN_CATAN, BUILT_IN_CCOSH, BUILT_IN_CCOS, BUILT_IN_CEXP, BUILT_IN_CLOG, BUILT_IN_CPOW, BUILT_IN_CPROJ, BUILT_IN_CSINH, BUILT_IN_CSIN, BUILT_IN_CSQRT, BUILT_IN_CTANH, BUILT_IN_CTAN): Add DEF_EXT_LIB_FLOATN_NX_BUILTINS. * fold-const-call.cc (fold_const_call_sc, fold_const_call_cc, fold_const_call_ccc): Add various CASE_CFN_*_FN: cases when CASE_CFN_* is present. * gimple-ssa-backprop.cc (backprop::process_builtin_call_use): Likewise. * builtins.cc (expand_builtin, fold_builtin_1): Likewise. * fold-const.cc (negate_mathfn_p, tree_expr_finite_p, tree_expr_maybe_signaling_nan_p, tree_expr_maybe_nan_p, tree_expr_maybe_real_minus_zero_p, tree_call_nonnegative_warnv_p): Likewise. --- gcc/builtin-types.def | 70 ++++++++++++++++++++++++++++++++++++++++++++++ gcc/builtins.cc | 2 ++ gcc/builtins.def | 31 ++++++++++++++++++++ gcc/fold-const-call.cc | 18 ++++++++++++ gcc/fold-const.cc | 37 ++++++++++++++++++++++++ gcc/gimple-ssa-backprop.cc | 6 ++++ 6 files changed, 164 insertions(+) (limited to 'gcc') diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index 81460e1..e1e25e9 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -109,6 +109,34 @@ DEF_PRIMITIVE_TYPE (BT_FLOAT128X, (float128x_type_node DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT, complex_float_type_node) DEF_PRIMITIVE_TYPE (BT_COMPLEX_DOUBLE, complex_double_type_node) DEF_PRIMITIVE_TYPE (BT_COMPLEX_LONGDOUBLE, complex_long_double_type_node) +DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT16, (float16_type_node + ? build_complex_type + (float16_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT32, (float32_type_node + ? build_complex_type + (float32_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT64, (float64_type_node + ? build_complex_type + (float64_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT128, (float128_type_node + ? build_complex_type + (float128_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT32X, (float32x_type_node + ? build_complex_type + (float32x_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT64X, (float64x_type_node + ? build_complex_type + (float64x_type_node) + : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT128X, (float128x_type_node + ? build_complex_type + (float128x_type_node) + : error_mark_node)) DEF_PRIMITIVE_TYPE (BT_PTR, ptr_type_node) DEF_PRIMITIVE_TYPE (BT_FILEPTR, fileptr_type_node) @@ -242,12 +270,40 @@ DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE) DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE) +DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT16_COMPLEX_FLOAT16, + BT_COMPLEX_FLOAT16, BT_COMPLEX_FLOAT16) +DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT32_COMPLEX_FLOAT32, + BT_COMPLEX_FLOAT32, BT_COMPLEX_FLOAT32) +DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT64_COMPLEX_FLOAT64, + BT_COMPLEX_FLOAT64, BT_COMPLEX_FLOAT64) +DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT128_COMPLEX_FLOAT128, + BT_COMPLEX_FLOAT128, BT_COMPLEX_FLOAT128) +DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X, + BT_COMPLEX_FLOAT32X, BT_COMPLEX_FLOAT32X) +DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X, + BT_COMPLEX_FLOAT64X, BT_COMPLEX_FLOAT64X) +DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X, + BT_COMPLEX_FLOAT128X, BT_COMPLEX_FLOAT128X) DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_COMPLEX_FLOAT, BT_FLOAT, BT_COMPLEX_FLOAT) DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_COMPLEX_DOUBLE, BT_DOUBLE, BT_COMPLEX_DOUBLE) DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, BT_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE) +DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT16_COMPLEX_FLOAT16, + BT_FLOAT16, BT_COMPLEX_FLOAT16) +DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32_COMPLEX_FLOAT32, + BT_FLOAT32, BT_COMPLEX_FLOAT32) +DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64_COMPLEX_FLOAT64, + BT_FLOAT64, BT_COMPLEX_FLOAT64) +DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128_COMPLEX_FLOAT128, + BT_FLOAT128, BT_COMPLEX_FLOAT128) +DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32X_COMPLEX_FLOAT32X, + BT_FLOAT32X, BT_COMPLEX_FLOAT32X) +DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64X_COMPLEX_FLOAT64X, + BT_FLOAT64X, BT_COMPLEX_FLOAT64X) +DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128X_COMPLEX_FLOAT128X, + BT_FLOAT128X, BT_COMPLEX_FLOAT128X) DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT_FLOAT, BT_COMPLEX_FLOAT, BT_FLOAT) DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_DOUBLE_DOUBLE, @@ -565,6 +621,20 @@ DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE) DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE) +DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT16_COMPLEX_FLOAT16_COMPLEX_FLOAT16, + BT_COMPLEX_FLOAT16, BT_COMPLEX_FLOAT16, BT_COMPLEX_FLOAT16) +DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT32_COMPLEX_FLOAT32_COMPLEX_FLOAT32, + BT_COMPLEX_FLOAT32, BT_COMPLEX_FLOAT32, BT_COMPLEX_FLOAT32) +DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT64_COMPLEX_FLOAT64_COMPLEX_FLOAT64, + BT_COMPLEX_FLOAT64, BT_COMPLEX_FLOAT64, BT_COMPLEX_FLOAT64) +DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT128_COMPLEX_FLOAT128_COMPLEX_FLOAT128, + BT_COMPLEX_FLOAT128, BT_COMPLEX_FLOAT128, BT_COMPLEX_FLOAT128) +DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X, + BT_COMPLEX_FLOAT32X, BT_COMPLEX_FLOAT32X, BT_COMPLEX_FLOAT32X) +DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X, + BT_COMPLEX_FLOAT64X, BT_COMPLEX_FLOAT64X, BT_COMPLEX_FLOAT64X) +DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X, + BT_COMPLEX_FLOAT128X, BT_COMPLEX_FLOAT128X, BT_COMPLEX_FLOAT128X) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTR, BT_VOID, BT_PTR, BT_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_PTR_CONST_STRING, BT_INT, BT_CONST_STRING, BT_PTR_CONST_STRING) diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 80415df..b359ce2 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -7393,6 +7393,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, /* Just do a normal library call if we were unable to fold the values. */ CASE_FLT_FN (BUILT_IN_CABS): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_CABS): break; CASE_FLT_FN (BUILT_IN_FMA): @@ -9661,6 +9662,7 @@ fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0) break; CASE_FLT_FN (BUILT_IN_CARG): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_CARG): return fold_builtin_carg (loc, arg0, type); case BUILT_IN_ISASCII: diff --git a/gcc/builtins.def b/gcc/builtins.def index 4997315..0ea8a2b 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -709,36 +709,54 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_YNL, "ynl", BT_FN_LONGDOUBLE_INT_LONGDOUBLE, AT DEF_C99_COMPL_BUILTIN (BUILT_IN_CABS, "cabs", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CABSF, "cabsf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CABSL, "cabsl", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +#define CABS_TYPE(F) BT_FN_##F##_COMPLEX_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CABS, "cabs", CABS_TYPE, ATTR_MATHFN_FPROUNDING) +#undef CABS_TYPE DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOS, "cacos", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSF, "cacosf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSH, "cacosh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSHF, "cacoshf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSHL, "cacoshl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +#define CACOSH_TYPE(F) BT_FN_COMPLEX_##F##_COMPLEX_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CACOSH, "cacosh", CACOSH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSL, "cacosl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CACOS, "cacos", CACOSH_TYPE, ATTR_MATHFN_FPROUNDING) +#undef CACOSH_TYPE DEF_C99_COMPL_BUILTIN (BUILT_IN_CARG, "carg", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CARGF, "cargf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CARGL, "cargl", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +#define CARG_TYPE(F) BT_FN_##F##_COMPLEX_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CARG, "carg", CARG_TYPE, ATTR_MATHFN_FPROUNDING) +#undef CARG_TYPE DEF_C99_COMPL_BUILTIN (BUILT_IN_CASIN, "casin", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINF, "casinf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINH, "casinh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINHF, "casinhf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINHL, "casinhl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +#define CASINH_TYPE(F) BT_FN_COMPLEX_##F##_COMPLEX_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CASINH, "casinh", CASINH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINL, "casinl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CASIN, "casin", CASINH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CATAN, "catan", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANF, "catanf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANH, "catanh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANHF, "catanhf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANHL, "catanhl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CATANH, "catanh", CASINH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANL, "catanl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CATAN, "catan", CASINH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOS, "ccos", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSF, "ccosf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSH, "ccosh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSHF, "ccoshf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSHL, "ccoshl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CCOSH, "ccosh", CASINH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSL, "ccosl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CCOS, "ccos", CASINH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CEXP, "cexp", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CEXPF, "cexpf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CEXPL, "cexpl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CEXP, "cexp", CASINH_TYPE, ATTR_MATHFN_FPROUNDING) DEF_GCC_BUILTIN (BUILT_IN_CEXPI, "cexpi", BT_FN_COMPLEX_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_GCC_BUILTIN (BUILT_IN_CEXPIF, "cexpif", BT_FN_COMPLEX_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_GCC_BUILTIN (BUILT_IN_CEXPIL, "cexpil", BT_FN_COMPLEX_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) @@ -748,6 +766,8 @@ DEF_C99_COMPL_BUILTIN (BUILT_IN_CIMAGL, "cimagl", BT_FN_LONGDOUBLE_COMPLE DEF_C99_COMPL_BUILTIN (BUILT_IN_CLOG, "clog", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CLOGF, "clogf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CLOGL, "clogl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CLOG, "clog", CASINH_TYPE, ATTR_MATHFN_FPROUNDING) +#undef CASINH_TYPE DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10, "clog10", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10F, "clog10f", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10L, "clog10l", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) @@ -757,9 +777,14 @@ DEF_C99_COMPL_BUILTIN (BUILT_IN_CONJL, "conjl", BT_FN_COMPLEX_LONGDOUBLE_ DEF_C99_COMPL_BUILTIN (BUILT_IN_CPOW, "cpow", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CPOWF, "cpowf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CPOWL, "cpowl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +#define CPOW_TYPE(F) BT_FN_COMPLEX_##F##_COMPLEX_##F##_COMPLEX_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CPOW, "cpow", CPOW_TYPE, ATTR_MATHFN_FPROUNDING) +#undef CPOW_TYPE DEF_C99_COMPL_BUILTIN (BUILT_IN_CPROJ, "cproj", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_COMPL_BUILTIN (BUILT_IN_CPROJF, "cprojf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_COMPL_BUILTIN (BUILT_IN_CPROJL, "cprojl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) +#define CPROJ_TYPE(F) BT_FN_COMPLEX_##F##_COMPLEX_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CPROJ, "cproj", CPROJ_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_COMPL_BUILTIN (BUILT_IN_CREAL, "creal", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_COMPL_BUILTIN (BUILT_IN_CREALF, "crealf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_COMPL_BUILTIN (BUILT_IN_CREALL, "creall", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -768,16 +793,22 @@ DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINF, "csinf", BT_FN_COMPLEX_FLOAT_COMPL DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINH, "csinh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINHF, "csinhf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINHL, "csinhl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CSINH, "csinh", CPROJ_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINL, "csinl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CSIN, "csin", CPROJ_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CSQRT, "csqrt", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CSQRTF, "csqrtf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CSQRTL, "csqrtl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CSQRT, "csqrt", CPROJ_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CTAN, "ctan", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANF, "ctanf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANH, "ctanh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANHF, "ctanhf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANHL, "ctanhl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CTANH, "ctanh", CPROJ_TYPE, ATTR_MATHFN_FPROUNDING) DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANL, "ctanl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CTAN, "ctan", CPROJ_TYPE, ATTR_MATHFN_FPROUNDING) +#undef CPROJ_TYPE /* Category: string/memory builtins. */ DEF_EXT_LIB_BUILTIN (BUILT_IN_BCMP, "bcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF) diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc index ab1b098..8ceed8f 100644 --- a/gcc/fold-const-call.cc +++ b/gcc/fold-const-call.cc @@ -1112,6 +1112,7 @@ fold_const_call_sc (real_value *result, combined_fn fn, switch (fn) { CASE_CFN_CABS: + CASE_CFN_CABS_FN: return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format); default: @@ -1135,14 +1136,17 @@ fold_const_call_cc (real_value *result_real, real_value *result_imag, switch (fn) { CASE_CFN_CCOS: + CASE_CFN_CCOS_FN: return do_mpc_arg1 (result_real, result_imag, mpc_cos, arg_real, arg_imag, format); CASE_CFN_CCOSH: + CASE_CFN_CCOSH_FN: return do_mpc_arg1 (result_real, result_imag, mpc_cosh, arg_real, arg_imag, format); CASE_CFN_CPROJ: + CASE_CFN_CPROJ_FN: if (real_isinf (arg_real) || real_isinf (arg_imag)) { *result_real = dconstinf; @@ -1157,54 +1161,67 @@ fold_const_call_cc (real_value *result_real, real_value *result_imag, return true; CASE_CFN_CSIN: + CASE_CFN_CSIN_FN: return do_mpc_arg1 (result_real, result_imag, mpc_sin, arg_real, arg_imag, format); CASE_CFN_CSINH: + CASE_CFN_CSINH_FN: return do_mpc_arg1 (result_real, result_imag, mpc_sinh, arg_real, arg_imag, format); CASE_CFN_CTAN: + CASE_CFN_CTAN_FN: return do_mpc_arg1 (result_real, result_imag, mpc_tan, arg_real, arg_imag, format); CASE_CFN_CTANH: + CASE_CFN_CTANH_FN: return do_mpc_arg1 (result_real, result_imag, mpc_tanh, arg_real, arg_imag, format); CASE_CFN_CLOG: + CASE_CFN_CLOG_FN: return do_mpc_arg1 (result_real, result_imag, mpc_log, arg_real, arg_imag, format); CASE_CFN_CSQRT: + CASE_CFN_CSQRT_FN: return do_mpc_arg1 (result_real, result_imag, mpc_sqrt, arg_real, arg_imag, format); CASE_CFN_CASIN: + CASE_CFN_CASIN_FN: return do_mpc_arg1 (result_real, result_imag, mpc_asin, arg_real, arg_imag, format); CASE_CFN_CACOS: + CASE_CFN_CACOS_FN: return do_mpc_arg1 (result_real, result_imag, mpc_acos, arg_real, arg_imag, format); CASE_CFN_CATAN: + CASE_CFN_CATAN_FN: return do_mpc_arg1 (result_real, result_imag, mpc_atan, arg_real, arg_imag, format); CASE_CFN_CASINH: + CASE_CFN_CASINH_FN: return do_mpc_arg1 (result_real, result_imag, mpc_asinh, arg_real, arg_imag, format); CASE_CFN_CACOSH: + CASE_CFN_CACOSH_FN: return do_mpc_arg1 (result_real, result_imag, mpc_acosh, arg_real, arg_imag, format); CASE_CFN_CATANH: + CASE_CFN_CATANH_FN: return do_mpc_arg1 (result_real, result_imag, mpc_atanh, arg_real, arg_imag, format); CASE_CFN_CEXP: + CASE_CFN_CEXP_FN: return do_mpc_arg1 (result_real, result_imag, mpc_exp, arg_real, arg_imag, format); @@ -1532,6 +1549,7 @@ fold_const_call_ccc (real_value *result_real, real_value *result_imag, switch (fn) { CASE_CFN_CPOW: + CASE_CFN_CPOW_FN: return do_mpc_arg2 (result_real, result_imag, mpc_pow, arg0_real, arg0_imag, arg1_real, arg1_imag, format); diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 16384a8..7e1ea58 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -322,36 +322,62 @@ negate_mathfn_p (combined_fn fn) switch (fn) { CASE_CFN_ASIN: + CASE_CFN_ASIN_FN: CASE_CFN_ASINH: + CASE_CFN_ASINH_FN: CASE_CFN_ATAN: + CASE_CFN_ATAN_FN: CASE_CFN_ATANH: + CASE_CFN_ATANH_FN: CASE_CFN_CASIN: + CASE_CFN_CASIN_FN: CASE_CFN_CASINH: + CASE_CFN_CASINH_FN: CASE_CFN_CATAN: + CASE_CFN_CATAN_FN: CASE_CFN_CATANH: + CASE_CFN_CATANH_FN: CASE_CFN_CBRT: + CASE_CFN_CBRT_FN: CASE_CFN_CPROJ: + CASE_CFN_CPROJ_FN: CASE_CFN_CSIN: + CASE_CFN_CSIN_FN: CASE_CFN_CSINH: + CASE_CFN_CSINH_FN: CASE_CFN_CTAN: + CASE_CFN_CTAN_FN: CASE_CFN_CTANH: + CASE_CFN_CTANH_FN: CASE_CFN_ERF: + CASE_CFN_ERF_FN: CASE_CFN_LLROUND: + CASE_CFN_LLROUND_FN: CASE_CFN_LROUND: + CASE_CFN_LROUND_FN: CASE_CFN_ROUND: CASE_CFN_ROUNDEVEN: CASE_CFN_ROUNDEVEN_FN: CASE_CFN_SIN: + CASE_CFN_SIN_FN: CASE_CFN_SINH: + CASE_CFN_SINH_FN: CASE_CFN_TAN: + CASE_CFN_TAN_FN: CASE_CFN_TANH: + CASE_CFN_TANH_FN: CASE_CFN_TRUNC: + CASE_CFN_TRUNC_FN: return true; CASE_CFN_LLRINT: + CASE_CFN_LLRINT_FN: CASE_CFN_LRINT: + CASE_CFN_LRINT_FN: CASE_CFN_NEARBYINT: + CASE_CFN_NEARBYINT_FN: CASE_CFN_RINT: + CASE_CFN_RINT_FN: return !flag_rounding_math; default: @@ -14288,9 +14314,12 @@ tree_expr_finite_p (const_tree x) switch (get_call_combined_fn (x)) { CASE_CFN_FABS: + CASE_CFN_FABS_FN: return tree_expr_finite_p (CALL_EXPR_ARG (x, 0)); CASE_CFN_FMAX: + CASE_CFN_FMAX_FN: CASE_CFN_FMIN: + CASE_CFN_FMIN_FN: return tree_expr_finite_p (CALL_EXPR_ARG (x, 0)) && tree_expr_finite_p (CALL_EXPR_ARG (x, 1)); default: @@ -14408,9 +14437,12 @@ tree_expr_maybe_signaling_nan_p (const_tree x) switch (get_call_combined_fn (x)) { CASE_CFN_FABS: + CASE_CFN_FABS_FN: return tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 0)); CASE_CFN_FMAX: + CASE_CFN_FMAX_FN: CASE_CFN_FMIN: + CASE_CFN_FMIN_FN: return tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 0)) || tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 1)); default: @@ -14481,9 +14513,12 @@ tree_expr_maybe_nan_p (const_tree x) switch (get_call_combined_fn (x)) { CASE_CFN_FABS: + CASE_CFN_FABS_FN: return tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 0)); CASE_CFN_FMAX: + CASE_CFN_FMAX_FN: CASE_CFN_FMIN: + CASE_CFN_FMIN_FN: return tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 0)) || tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 1)); default: @@ -14520,6 +14555,7 @@ tree_expr_maybe_real_minus_zero_p (const_tree x) switch (get_call_combined_fn (x)) { CASE_CFN_FABS: + CASE_CFN_FABS_FN: return false; default: break; @@ -14801,6 +14837,7 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_ACOSH: CASE_CFN_ACOSH_FN: CASE_CFN_CABS: + CASE_CFN_CABS_FN: CASE_CFN_COSH: CASE_CFN_COSH_FN: CASE_CFN_ERFC: diff --git a/gcc/gimple-ssa-backprop.cc b/gcc/gimple-ssa-backprop.cc index 55986dd..7de6e78 100644 --- a/gcc/gimple-ssa-backprop.cc +++ b/gcc/gimple-ssa-backprop.cc @@ -351,10 +351,15 @@ backprop::process_builtin_call_use (gcall *call, tree rhs, usage_info *info) break; CASE_CFN_COS: + CASE_CFN_COS_FN: CASE_CFN_COSH: + CASE_CFN_COSH_FN: CASE_CFN_CCOS: + CASE_CFN_CCOS_FN: CASE_CFN_CCOSH: + CASE_CFN_CCOSH_FN: CASE_CFN_HYPOT: + CASE_CFN_HYPOT_FN: /* The signs of all inputs are ignored. */ info->flags.ignore_sign = true; break; @@ -367,6 +372,7 @@ backprop::process_builtin_call_use (gcall *call, tree rhs, usage_info *info) break; CASE_CFN_POW: + CASE_CFN_POW_FN: { /* The sign of the first input is ignored as long as the second input is an even real. */ -- cgit v1.1 From 12a1085644c6c5446eece41d255ca1fd569149d4 Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Mon, 24 Oct 2022 14:05:03 +0100 Subject: amdgcn: Silence unused parameter warning gcc/ChangeLog: * config/gcn/gcn.cc (gcn_simd_clone_compute_vecsize_and_simdlen): Set base_type as ARG_UNUSED. --- gcc/config/gcn/gcn.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc index a9ef5c3..a561976 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -5026,7 +5026,7 @@ gcn_vectorization_cost (enum vect_cost_for_stmt ARG_UNUSED (type_of_cost), static int gcn_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *ARG_UNUSED (node), struct cgraph_simd_clone *clonei, - tree base_type, + tree ARG_UNUSED (base_type), int ARG_UNUSED (num)) { if (known_eq (clonei->simdlen, 0U)) -- cgit v1.1 From f539029c1ce6fb9163422d1a8b6ac12a2554eaa2 Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Fri, 28 Oct 2022 12:38:43 +0100 Subject: amdgcn: multi-size vector reductions Add support for vector reductions for any vector width by switching iterators and generalising the code slightly. There's no one-instruction way to move an item from lane 31 to lane 0 (63, 15, 7, 3, and 1 are all fine though), and vec_extract is probably fewer cycles anyway, so now we always reduce to an SGPR. gcc/ChangeLog: * config/gcn/gcn-valu.md (V64_SI): Delete iterator. (V64_DI): Likewise. (V64_1REG): Likewise. (V64_INT_1REG): Likewise. (V64_2REG): Likewise. (V64_ALL): Likewise. (V64_FP): Likewise. (reduc__scal_): Use V_ALL. Use gen_vec_extract. (fold_left_plus_): Use V_FP. (*_dpp_shr_): Use V_1REG. (*_dpp_shr_): Use V_DI. (*plus_carry_dpp_shr_): Use V_INT_1REG. (*plus_carry_in_dpp_shr_): Use V_SI. (*plus_carry_dpp_shr_): Use V_DI. (mov_from_lane63_): Delete. (mov_from_lane63_): Delete. * config/gcn/gcn.cc (gcn_expand_reduc_scalar): Support partial vectors. * config/gcn/gcn.md (unspec): Remove UNSPEC_MOV_FROM_LANE63. --- gcc/config/gcn/gcn-valu.md | 111 ++++++++++++--------------------------------- gcc/config/gcn/gcn.cc | 27 ++++++----- gcc/config/gcn/gcn.md | 1 - 3 files changed, 45 insertions(+), 94 deletions(-) (limited to 'gcc') diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md index 00c0e3b..6274d2e 100644 --- a/gcc/config/gcn/gcn-valu.md +++ b/gcc/config/gcn/gcn-valu.md @@ -32,11 +32,6 @@ (define_mode_iterator V_DF [V2DF V4DF V8DF V16DF V32DF V64DF]) -(define_mode_iterator V64_SI - [V64SI]) -(define_mode_iterator V64_DI - [V64DI]) - ; Vector modes for sub-dword modes (define_mode_iterator V_QIHI [V2QI V2HI @@ -77,13 +72,6 @@ V32HF V32SF V64HF V64SF]) -; V64_* modes are for where more general support is unimplemented -; (e.g. reductions) -(define_mode_iterator V64_1REG - [V64QI V64HI V64SI V64HF V64SF]) -(define_mode_iterator V64_INT_1REG - [V64QI V64HI V64SI]) - ; Vector modes for two vector registers (define_mode_iterator V_2REG [V2DI V2DF @@ -93,9 +81,6 @@ V32DI V32DF V64DI V64DF]) -(define_mode_iterator V64_2REG - [V64DI V64DF]) - ; Vector modes with native support (define_mode_iterator V_noQI [V2HI V2HF V2SI V2SF V2DI V2DF @@ -158,11 +143,6 @@ V32HF V32SF V32DF V64HF V64SF V64DF]) -(define_mode_iterator V64_ALL - [V64QI V64HI V64HF V64SI V64SF V64DI V64DF]) -(define_mode_iterator V64_FP - [V64HF V64SF V64DF]) - (define_mode_attr scalar_mode [(V2QI "qi") (V2HI "hi") (V2SI "si") (V2HF "hf") (V2SF "sf") (V2DI "di") (V2DF "df") @@ -3528,15 +3508,16 @@ (define_expand "reduc__scal_" [(set (match_operand: 0 "register_operand") (unspec: - [(match_operand:V64_ALL 1 "register_operand")] + [(match_operand:V_ALL 1 "register_operand")] REDUC_UNSPEC))] "" { rtx tmp = gcn_expand_reduc_scalar (mode, operands[1], ); - /* The result of the reduction is in lane 63 of tmp. */ - emit_insn (gen_mov_from_lane63_ (operands[0], tmp)); + rtx last_lane = GEN_INT (GET_MODE_NUNITS (mode) - 1); + emit_insn (gen_vec_extract (operands[0], tmp, + last_lane)); DONE; }) @@ -3547,7 +3528,7 @@ (define_expand "fold_left_plus_" [(match_operand: 0 "register_operand") (match_operand: 1 "gcn_alu_operand") - (match_operand:V64_FP 2 "gcn_alu_operand")] + (match_operand:V_FP 2 "gcn_alu_operand")] "can_create_pseudo_p () && (flag_openacc || flag_openmp || flag_associative_math)" @@ -3563,11 +3544,11 @@ }) (define_insn "*_dpp_shr_" - [(set (match_operand:V64_1REG 0 "register_operand" "=v") - (unspec:V64_1REG - [(match_operand:V64_1REG 1 "register_operand" "v") - (match_operand:V64_1REG 2 "register_operand" "v") - (match_operand:SI 3 "const_int_operand" "n")] + [(set (match_operand:V_1REG 0 "register_operand" "=v") + (unspec:V_1REG + [(match_operand:V_1REG 1 "register_operand" "v") + (match_operand:V_1REG 2 "register_operand" "v") + (match_operand:SI 3 "const_int_operand" "n")] REDUC_UNSPEC))] ; GCN3 requires a carry out, GCN5 not "!(TARGET_GCN3 && SCALAR_INT_MODE_P (mode) @@ -3580,11 +3561,11 @@ (set_attr "length" "8")]) (define_insn_and_split "*_dpp_shr_" - [(set (match_operand:V64_DI 0 "register_operand" "=v") - (unspec:V64_DI - [(match_operand:V64_DI 1 "register_operand" "v") - (match_operand:V64_DI 2 "register_operand" "v") - (match_operand:SI 3 "const_int_operand" "n")] + [(set (match_operand:V_DI 0 "register_operand" "=v") + (unspec:V_DI + [(match_operand:V_DI 1 "register_operand" "v") + (match_operand:V_DI 2 "register_operand" "v") + (match_operand:SI 3 "const_int_operand" "n")] REDUC_2REG_UNSPEC))] "" "#" @@ -3609,10 +3590,10 @@ ; Special cases for addition. (define_insn "*plus_carry_dpp_shr_" - [(set (match_operand:V64_INT_1REG 0 "register_operand" "=v") - (unspec:V64_INT_1REG - [(match_operand:V64_INT_1REG 1 "register_operand" "v") - (match_operand:V64_INT_1REG 2 "register_operand" "v") + [(set (match_operand:V_INT_1REG 0 "register_operand" "=v") + (unspec:V_INT_1REG + [(match_operand:V_INT_1REG 1 "register_operand" "v") + (match_operand:V_INT_1REG 2 "register_operand" "v") (match_operand:SI 3 "const_int_operand" "n")] UNSPEC_PLUS_CARRY_DPP_SHR)) (clobber (reg:DI VCC_REG))] @@ -3626,12 +3607,12 @@ (set_attr "length" "8")]) (define_insn "*plus_carry_in_dpp_shr_" - [(set (match_operand:V64_SI 0 "register_operand" "=v") - (unspec:V64_SI - [(match_operand:V64_SI 1 "register_operand" "v") - (match_operand:V64_SI 2 "register_operand" "v") - (match_operand:SI 3 "const_int_operand" "n") - (match_operand:DI 4 "register_operand" "cV")] + [(set (match_operand:V_SI 0 "register_operand" "=v") + (unspec:V_SI + [(match_operand:V_SI 1 "register_operand" "v") + (match_operand:V_SI 2 "register_operand" "v") + (match_operand:SI 3 "const_int_operand" "n") + (match_operand:DI 4 "register_operand" "cV")] UNSPEC_PLUS_CARRY_IN_DPP_SHR)) (clobber (reg:DI VCC_REG))] "" @@ -3644,11 +3625,11 @@ (set_attr "length" "8")]) (define_insn_and_split "*plus_carry_dpp_shr_" - [(set (match_operand:V64_DI 0 "register_operand" "=v") - (unspec:V64_DI - [(match_operand:V64_DI 1 "register_operand" "v") - (match_operand:V64_DI 2 "register_operand" "v") - (match_operand:SI 3 "const_int_operand" "n")] + [(set (match_operand:V_DI 0 "register_operand" "=v") + (unspec:V_DI + [(match_operand:V_DI 1 "register_operand" "v") + (match_operand:V_DI 2 "register_operand" "v") + (match_operand:SI 3 "const_int_operand" "n")] UNSPEC_PLUS_CARRY_DPP_SHR)) (clobber (reg:DI VCC_REG))] "" @@ -3675,38 +3656,6 @@ [(set_attr "type" "vmult") (set_attr "length" "16")]) -; Instructions to move a scalar value from lane 63 of a vector register. -(define_insn "mov_from_lane63_" - [(set (match_operand: 0 "register_operand" "=Sg,v") - (unspec: - [(match_operand:V64_1REG 1 "register_operand" " v,v")] - UNSPEC_MOV_FROM_LANE63))] - "" - "@ - v_readlane_b32\t%0, %1, 63 - v_mov_b32\t%0, %1 wave_ror:1" - [(set_attr "type" "vop3a,vop_dpp") - (set_attr "exec" "none,*") - (set_attr "length" "8")]) - -(define_insn "mov_from_lane63_" - [(set (match_operand: 0 "register_operand" "=Sg,v") - (unspec: - [(match_operand:V64_2REG 1 "register_operand" " v,v")] - UNSPEC_MOV_FROM_LANE63))] - "" - "@ - v_readlane_b32\t%L0, %L1, 63\;v_readlane_b32\t%H0, %H1, 63 - * if (REGNO (operands[0]) <= REGNO (operands[1])) \ - return \"v_mov_b32\t%L0, %L1 wave_ror:1\;\" \ - \"v_mov_b32\t%H0, %H1 wave_ror:1\"; \ - else \ - return \"v_mov_b32\t%H0, %H1 wave_ror:1\;\" \ - \"v_mov_b32\t%L0, %L1 wave_ror:1\";" - [(set_attr "type" "vop3a,vop_dpp") - (set_attr "exec" "none,*") - (set_attr "length" "8")]) - ;; }}} ;; {{{ Miscellaneous diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc index a561976..b9d9170 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -4918,23 +4918,25 @@ gcn_expand_dpp_shr_insn (machine_mode mode, const char *insn, The vector register SRC of mode MODE is reduced using the operation given by UNSPEC, and the scalar result is returned in lane 63 of a vector - register. */ -/* FIXME: Implement reductions for sizes other than V64. - (They're currently disabled in the machine description.) */ + register (or lane 31, 15, 7, 3, 1 for partial vectors). */ rtx gcn_expand_reduc_scalar (machine_mode mode, rtx src, int unspec) { machine_mode orig_mode = mode; + machine_mode scalar_mode = GET_MODE_INNER (mode); + int vf = GET_MODE_NUNITS (mode); bool use_moves = (((unspec == UNSPEC_SMIN_DPP_SHR + || unspec == UNSPEC_SMIN_DPP_SHR || unspec == UNSPEC_SMAX_DPP_SHR || unspec == UNSPEC_UMIN_DPP_SHR || unspec == UNSPEC_UMAX_DPP_SHR) - && (mode == V64DImode - || mode == V64DFmode)) + && (scalar_mode == DImode + || scalar_mode == DFmode)) || (unspec == UNSPEC_PLUS_DPP_SHR - && mode == V64DFmode)); + && scalar_mode == DFmode)); rtx_code code = (unspec == UNSPEC_SMIN_DPP_SHR ? SMIN + : unspec == UNSPEC_SMIN_DPP_SHR ? SMIN : unspec == UNSPEC_SMAX_DPP_SHR ? SMAX : unspec == UNSPEC_UMIN_DPP_SHR ? UMIN : unspec == UNSPEC_UMAX_DPP_SHR ? UMAX @@ -4944,23 +4946,23 @@ gcn_expand_reduc_scalar (machine_mode mode, rtx src, int unspec) || unspec == UNSPEC_SMAX_DPP_SHR || unspec == UNSPEC_UMIN_DPP_SHR || unspec == UNSPEC_UMAX_DPP_SHR) - && (mode == V64QImode - || mode == V64HImode)); + && (scalar_mode == QImode + || scalar_mode == HImode)); bool unsignedp = (unspec == UNSPEC_UMIN_DPP_SHR || unspec == UNSPEC_UMAX_DPP_SHR); bool use_plus_carry = unspec == UNSPEC_PLUS_DPP_SHR && GET_MODE_CLASS (mode) == MODE_VECTOR_INT - && (TARGET_GCN3 || mode == V64DImode); + && (TARGET_GCN3 || scalar_mode == DImode); if (use_plus_carry) unspec = UNSPEC_PLUS_CARRY_DPP_SHR; if (use_extends) { - rtx tmp = gen_reg_rtx (V64SImode); + mode = VnMODE (vf, SImode); + rtx tmp = gen_reg_rtx (mode); convert_move (tmp, src, unsignedp); src = tmp; - mode = V64SImode; } /* Perform reduction by first performing the reduction operation on every @@ -4968,7 +4970,8 @@ gcn_expand_reduc_scalar (machine_mode mode, rtx src, int unspec) iteration (thereby effectively reducing every 4 lanes) and so on until all lanes are reduced. */ rtx in, out = force_reg (mode, src); - for (int i = 0, shift = 1; i < 6; i++, shift <<= 1) + int iterations = exact_log2 (vf); + for (int i = 0, shift = 1; i < iterations; i++, shift <<= 1) { rtx shift_val = gen_rtx_CONST_INT (VOIDmode, shift); in = out; diff --git a/gcc/config/gcn/gcn.md b/gcc/config/gcn/gcn.md index a3c9523..6c1a438 100644 --- a/gcc/config/gcn/gcn.md +++ b/gcc/config/gcn/gcn.md @@ -78,7 +78,6 @@ UNSPEC_PLUS_CARRY_DPP_SHR UNSPEC_PLUS_CARRY_IN_DPP_SHR UNSPEC_AND_DPP_SHR UNSPEC_IOR_DPP_SHR UNSPEC_XOR_DPP_SHR UNSPEC_MOV_DPP_SHR - UNSPEC_MOV_FROM_LANE63 UNSPEC_GATHER UNSPEC_SCATTER UNSPEC_RCP -- cgit v1.1 From 10aa0356118f44e5f4d720a2a4c731b173baa298 Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Fri, 28 Oct 2022 13:09:20 +0100 Subject: amdgcn: add fmin/fmax patterns Add fmin/fmax for scalar, vector, and reductions. The smin/smax patterns are already using the IEEE compliant hardware instructions anyway, so we can just expand to use those insns. gcc/ChangeLog: * config/gcn/gcn-valu.md (fminmaxop): New iterator. (3): New define_expand. (3): Likewise. (reduc__scal_): Likewise. * config/gcn/gcn.md (fexpander): New attribute. --- gcc/config/gcn/gcn-valu.md | 28 ++++++++++++++++++++++++++++ gcc/config/gcn/gcn.md | 4 ++++ 2 files changed, 32 insertions(+) (limited to 'gcc') diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md index 6274d2e..3b61951 100644 --- a/gcc/config/gcn/gcn-valu.md +++ b/gcc/config/gcn/gcn-valu.md @@ -2466,6 +2466,23 @@ [(set_attr "type" "vop2") (set_attr "length" "8,8")]) +(define_code_iterator fminmaxop [smin smax]) +(define_expand "3" + [(set (match_operand:FP 0 "gcn_valu_dst_operand") + (fminmaxop:FP + (match_operand:FP 1 "gcn_valu_src0_operand") + (match_operand:FP 2 "gcn_valu_src1_operand")))] + "" + {}) + +(define_expand "3" + [(set (match_operand:V_FP 0 "gcn_valu_dst_operand") + (fminmaxop:V_FP + (match_operand:V_FP 1 "gcn_valu_src0_operand") + (match_operand:V_FP 2 "gcn_valu_src1_operand")))] + "" + {}) + ;; }}} ;; {{{ FP unops @@ -3522,6 +3539,17 @@ DONE; }) +(define_expand "reduc__scal_" + [(match_operand: 0 "register_operand") + (fminmaxop:V_FP + (match_operand:V_FP 1 "register_operand"))] + "" + { + /* fmin/fmax are identical to smin/smax. */ + emit_insn (gen_reduc__scal_ (operands[0], operands[1])); + DONE; + }) + ;; Warning: This "-ffast-math" implementation converts in-order reductions ;; into associative reductions. It's also used where OpenMP or ;; OpenACC paralellization has already broken the in-order semantics. diff --git a/gcc/config/gcn/gcn.md b/gcc/config/gcn/gcn.md index 6c1a438..987b763 100644 --- a/gcc/config/gcn/gcn.md +++ b/gcc/config/gcn/gcn.md @@ -372,6 +372,10 @@ (sign_extend "extend") (zero_extend "zero_extend")]) +(define_code_attr fexpander + [(smin "fmin") + (smax "fmax")]) + ;; }}} ;; {{{ Miscellaneous instructions -- cgit v1.1 From 1b07d374765dd811cbb8b3e05764aef3b1754ff2 Mon Sep 17 00:00:00 2001 From: Ju-Zhe Zhong Date: Thu, 27 Oct 2022 22:41:52 +0800 Subject: RISC-V: Change constexpr back to CONSTEXPR According to https://github.com/gcc-mirror/gcc/commit/f95d3d5de72a1c43e8d529bad3ef59afc3214705. Since GCC 4.8.6 doesn't support constexpr, we should change it back to CONSTEXPR. gcc/ChangeLog: * config/riscv/riscv-vector-builtins-bases.cc: Change constexpr back to CONSTEXPR. * config/riscv/riscv-vector-builtins-shapes.cc (SHAPE): Ditto. * config/riscv/riscv-vector-builtins.cc (struct registered_function_hasher): Ditto. * config/riscv/riscv-vector-builtins.h (struct rvv_arg_type_info): Ditto. --- gcc/config/riscv/riscv-vector-builtins-bases.cc | 4 ++-- gcc/config/riscv/riscv-vector-builtins-shapes.cc | 2 +- gcc/config/riscv/riscv-vector-builtins.cc | 14 +++++++------- gcc/config/riscv/riscv-vector-builtins.h | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc index 713a756..231b63a 100644 --- a/gcc/config/riscv/riscv-vector-builtins-bases.cc +++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc @@ -84,8 +84,8 @@ public: } }; -static constexpr const vsetvl vsetvl_obj; -static constexpr const vsetvl vsetvlmax_obj; +static CONSTEXPR const vsetvl vsetvl_obj; +static CONSTEXPR const vsetvl vsetvlmax_obj; namespace bases { const function_base *const vsetvl = &vsetvl_obj; const function_base *const vsetvlmax = &vsetvlmax_obj; diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc index 14c5969..24fc1c0 100644 --- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc +++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc @@ -71,7 +71,7 @@ build_all (function_builder &b, const function_group_info &group) /* Declare the function shape NAME, pointing it to an instance of class _def. */ #define SHAPE(DEF, VAR) \ - static constexpr const DEF##_def VAR##_obj; \ + static CONSTEXPR const DEF##_def VAR##_obj; \ namespace shapes { const function_shape *const VAR = &VAR##_obj; } /* Base class for for build. */ diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc index 06a4a85..43150aa 100644 --- a/gcc/config/riscv/riscv-vector-builtins.cc +++ b/gcc/config/riscv/riscv-vector-builtins.cc @@ -88,7 +88,7 @@ struct registered_function_hasher : nofree_ptr_hash }; /* Static information about each RVV type. */ -static constexpr const vector_type_info vector_types[] = { +static CONSTEXPR const vector_type_info vector_types[] = { #define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, ARGS...) \ {#NAME, #ABI_NAME, "u" #NCHARS #ABI_NAME}, #include "riscv-vector-builtins.def" @@ -123,23 +123,23 @@ static const rvv_type_info i_ops[] = { #include "riscv-vector-builtins-types.def" {NUM_VECTOR_TYPES, 0}}; -static constexpr const rvv_arg_type_info rvv_arg_type_info_end +static CONSTEXPR const rvv_arg_type_info rvv_arg_type_info_end = rvv_arg_type_info (NUM_BASE_TYPES); /* A list of args for size_t func (void) function. */ -static constexpr const rvv_arg_type_info void_args[] +static CONSTEXPR const rvv_arg_type_info void_args[] = {rvv_arg_type_info (RVV_BASE_void), rvv_arg_type_info_end}; /* A list of args for size_t func (size_t) function. */ -static constexpr const rvv_arg_type_info size_args[] +static CONSTEXPR const rvv_arg_type_info size_args[] = {rvv_arg_type_info (RVV_BASE_size), rvv_arg_type_info_end}; /* A list of none preds that will be registered for intrinsic functions. */ -static constexpr const predication_type_index none_preds[] +static CONSTEXPR const predication_type_index none_preds[] = {PRED_TYPE_none, NUM_PRED_TYPES}; /* A static operand information for size_t func (void) function registration. */ -static constexpr const rvv_op_info i_none_size_void_ops +static CONSTEXPR const rvv_op_info i_none_size_void_ops = {i_ops, /* Types */ OP_TYPE_none, /* Suffix */ rvv_arg_type_info (RVV_BASE_size), /* Return type */ @@ -147,7 +147,7 @@ static constexpr const rvv_op_info i_none_size_void_ops /* A static operand information for size_t func (size_t) function registration. */ -static constexpr const rvv_op_info i_none_size_size_ops +static CONSTEXPR const rvv_op_info i_none_size_size_ops = {i_ops, /* Types */ OP_TYPE_none, /* Suffix */ rvv_arg_type_info (RVV_BASE_size), /* Return type */ diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h index e5636e2..425da12 100644 --- a/gcc/config/riscv/riscv-vector-builtins.h +++ b/gcc/config/riscv/riscv-vector-builtins.h @@ -171,7 +171,7 @@ struct rvv_builtin_suffixes /* RVV Builtin argument information. */ struct rvv_arg_type_info { - constexpr rvv_arg_type_info (rvv_base_type base_type_in) + CONSTEXPR rvv_arg_type_info (rvv_base_type base_type_in) : base_type (base_type_in) {} enum rvv_base_type base_type; -- cgit v1.1 From 8422861bddc7c4fd202cd59c8487d4bc6b807dc3 Mon Sep 17 00:00:00 2001 From: "Guillermo E. Martinez" Date: Mon, 31 Oct 2022 09:32:50 -0700 Subject: btf: Add support to BTF_KIND_ENUM64 type BTF supports 64-bits enumerators with following encoding: struct btf_type: name_off: 0 or offset to a valid C identifier info.kind_flag: 0 for unsigned, 1 for signed info.kind: BTF_KIND_ENUM64 info.vlen: number of enum values size: 1/2/4/8 The btf_type is followed by info.vlen number of: struct btf_enum64 { uint32_t name_off; /* Offset in string section of enumerator name. */ uint32_t val_lo32; /* lower 32-bit value for a 64-bit value Enumerator */ uint32_t val_hi32; /* high 32-bit value for a 64-bit value Enumerator */ }; So, a new btf_enum64 structure was added to represent BTF_KIND_ENUM64 and a new field dtd_enum_unsigned in ctf_dtdef structure to distinguish when CTF enum is a signed or unsigned type, later that information is used to encode the BTF enum type. gcc/ChangeLog: * btfout.cc (btf_calc_num_vbytes): Compute enumeration size depending of enumerator type btf_enum{,64}. (btf_asm_type): Update btf_kflag according to enumeration type sign using dtd_enum_unsigned field for both: BTF_KIND_ENUM{,64}. (btf_asm_enum_const): New argument to represent the size of the BTF enum type, writing the enumerator constant value for 32 bits, if it's 64 bits then explicitly writes lower 32-bits value and higher 32-bits value. (output_asm_btf_enum_list): Add enumeration size argument. * ctfc.cc (ctf_add_enum): New argument to represent CTF enum basic information. (ctf_add_generic): Use of ei_{name. size, unsigned} to build the dtd structure containing enumeration information. (ctf_add_enumerator): Update comment mention support for BTF enumeration in 64-bits. * dwarf2ctf.cc (gen_ctf_enumeration_type): Extract signedness for enumeration type and use it in ctf_add_enum. * ctfc.h (ctf_dmdef): Update dmd_value to HOST_WIDE_INT to allow use 32/64 bits enumerators. information. (ctf_dtdef): New field to describe enum signedness. include/ * btf.h (btf_enum64): Add new definition and new symbolic constant to BTF_KIND_ENUM64 and BTF_KF_ENUM_{UN,}SIGNED. gcc/testsuite/ChangeLog: * gcc.dg/debug/btf/btf-enum-1.c: Update testcase, with correct info.kflags encoding. * gcc.dg/debug/btf/btf-enum64-1.c: New testcase. --- gcc/btfout.cc | 30 ++++++++++++++---- gcc/ctfc.cc | 13 +++++--- gcc/ctfc.h | 5 +-- gcc/dwarf2ctf.cc | 5 ++- gcc/testsuite/gcc.dg/debug/btf/btf-enum-1.c | 2 +- gcc/testsuite/gcc.dg/debug/btf/btf-enum64-1.c | 44 +++++++++++++++++++++++++++ 6 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-enum64-1.c (limited to 'gcc') diff --git a/gcc/btfout.cc b/gcc/btfout.cc index 997a33f..aef9fd7 100644 --- a/gcc/btfout.cc +++ b/gcc/btfout.cc @@ -223,7 +223,9 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd) break; case BTF_KIND_ENUM: - vlen_bytes += vlen * sizeof (struct btf_enum); + vlen_bytes += (dtd->dtd_data.ctti_size == 0x8) + ? vlen * sizeof (struct btf_enum64) + : vlen * sizeof (struct btf_enum); break; case BTF_KIND_FUNC_PROTO: @@ -622,6 +624,15 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) btf_size_type = 0; } + if (btf_kind == BTF_KIND_ENUM) + { + btf_kflag = dtd->dtd_enum_unsigned + ? BTF_KF_ENUM_UNSIGNED + : BTF_KF_ENUM_SIGNED; + if (dtd->dtd_data.ctti_size == 0x8) + btf_kind = BTF_KIND_ENUM64; + } + dw2_asm_output_data (4, dtd->dtd_data.ctti_name, "btt_name"); dw2_asm_output_data (4, BTF_TYPE_INFO (btf_kind, btf_kflag, btf_vlen), "btt_info: kind=%u, kflag=%u, vlen=%u", @@ -634,6 +645,7 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) case BTF_KIND_UNION: case BTF_KIND_ENUM: case BTF_KIND_DATASEC: + case BTF_KIND_ENUM64: dw2_asm_output_data (4, dtd->dtd_data.ctti_size, "btt_size: %uB", dtd->dtd_data.ctti_size); return; @@ -707,13 +719,19 @@ btf_asm_sou_member (ctf_container_ref ctfc, ctf_dmdef_t * dmd) } } -/* Asm'out an enum constant following a BTF_KIND_ENUM. */ +/* Asm'out an enum constant following a BTF_KIND_ENUM{,64}. */ static void -btf_asm_enum_const (ctf_dmdef_t * dmd) +btf_asm_enum_const (unsigned int size, ctf_dmdef_t * dmd) { dw2_asm_output_data (4, dmd->dmd_name_offset, "bte_name"); - dw2_asm_output_data (4, dmd->dmd_value, "bte_value"); + if (size == 4) + dw2_asm_output_data (size, dmd->dmd_value, "bte_value"); + else + { + dw2_asm_output_data (4, dmd->dmd_value & 0xffffffff, "bte_value_lo32"); + dw2_asm_output_data (4, (dmd->dmd_value >> 32) & 0xffffffff, "bte_value_hi32"); + } } /* Asm'out a function parameter description following a BTF_KIND_FUNC_PROTO. */ @@ -871,7 +889,7 @@ output_asm_btf_sou_fields (ctf_container_ref ctfc, ctf_dtdef_ref dtd) btf_asm_sou_member (ctfc, dmd); } -/* Output all enumerator constants following a BTF_KIND_ENUM. */ +/* Output all enumerator constants following a BTF_KIND_ENUM{,64}. */ static void output_asm_btf_enum_list (ctf_container_ref ARG_UNUSED (ctfc), @@ -881,7 +899,7 @@ output_asm_btf_enum_list (ctf_container_ref ARG_UNUSED (ctfc), for (dmd = dtd->dtd_u.dtu_members; dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) - btf_asm_enum_const (dmd); + btf_asm_enum_const (dtd->dtd_data.ctti_size, dmd); } /* Output all function arguments following a BTF_KIND_FUNC_PROTO. */ diff --git a/gcc/ctfc.cc b/gcc/ctfc.cc index 0964543..11ec1f9 100644 --- a/gcc/ctfc.cc +++ b/gcc/ctfc.cc @@ -577,7 +577,7 @@ ctf_add_array (ctf_container_ref ctfc, uint32_t flag, const ctf_arinfo_t * arp, ctf_id_t ctf_add_enum (ctf_container_ref ctfc, uint32_t flag, const char * name, - HOST_WIDE_INT size, dw_die_ref die) + HOST_WIDE_INT size, bool eunsigned, dw_die_ref die) { ctf_dtdef_ref dtd; ctf_id_t type; @@ -604,6 +604,7 @@ ctf_add_enum (ctf_container_ref ctfc, uint32_t flag, const char * name, gcc_assert (size <= CTF_MAX_SIZE); dtd->dtd_data.ctti_size = size; + dtd->dtd_enum_unsigned = eunsigned; ctfc->ctfc_num_stypes++; @@ -630,10 +631,12 @@ ctf_add_enumerator (ctf_container_ref ctfc, ctf_id_t enid, const char * name, gcc_assert (kind == CTF_K_ENUM && vlen < CTF_MAX_VLEN); - /* Enum value is of type HOST_WIDE_INT in the compiler, dmd_value is int32_t - on the other hand. Check bounds and skip adding this enum value if out of - bounds. */ - if ((value > INT_MAX) || (value < INT_MIN)) + /* Enum value is of type HOST_WIDE_INT in the compiler, CTF enumerators + values in ctf_enum_t is limited to int32_t, BTF supports signed and + unsigned enumerators values of 32 and 64 bits, for both debug formats + we use ctf_dmdef_t.dmd_value entry of HOST_WIDE_INT type. So check + CTF bounds and skip adding this enum value if out of bounds. */ + if (!btf_debuginfo_p() && ((value > INT_MAX) || (value < INT_MIN))) { /* FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT. */ return (1); diff --git a/gcc/ctfc.h b/gcc/ctfc.h index bcf3a43..48c381a 100644 --- a/gcc/ctfc.h +++ b/gcc/ctfc.h @@ -133,7 +133,7 @@ typedef struct GTY ((chain_next ("%h.dmd_next"))) ctf_dmdef ctf_id_t dmd_type; /* Type of this member (for sou). */ uint32_t dmd_name_offset; /* Offset of the name in str table. */ uint64_t dmd_offset; /* Offset of this member in bits (for sou). */ - int dmd_value; /* Value of this member (for enum). */ + HOST_WIDE_INT dmd_value; /* Value of this member (for enum). */ struct ctf_dmdef * dmd_next; /* A list node. */ } ctf_dmdef_t; @@ -162,6 +162,7 @@ struct GTY ((for_user)) ctf_dtdef bool from_global_func; /* Whether this type was added from a global function. */ uint32_t linkage; /* Used in function types. 0=local, 1=global. */ + bool dtd_enum_unsigned; /* Enum signedness. */ union GTY ((desc ("ctf_dtu_d_union_selector (&%1)"))) { /* struct, union, or enum. */ @@ -406,7 +407,7 @@ extern const char * ctf_add_string (ctf_container_ref, const char *, extern ctf_id_t ctf_add_reftype (ctf_container_ref, uint32_t, ctf_id_t, uint32_t, dw_die_ref); extern ctf_id_t ctf_add_enum (ctf_container_ref, uint32_t, const char *, - HOST_WIDE_INT, dw_die_ref); + HOST_WIDE_INT, bool, dw_die_ref); extern ctf_id_t ctf_add_slice (ctf_container_ref, uint32_t, ctf_id_t, uint32_t, uint32_t, dw_die_ref); extern ctf_id_t ctf_add_float (ctf_container_ref, uint32_t, const char *, diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc index 3971000..748dd0c 100644 --- a/gcc/dwarf2ctf.cc +++ b/gcc/dwarf2ctf.cc @@ -736,6 +736,7 @@ gen_ctf_enumeration_type (ctf_container_ref ctfc, dw_die_ref enumeration) { const char *enum_name = get_AT_string (enumeration, DW_AT_name); unsigned int bit_size = ctf_die_bitsize (enumeration); + unsigned int signedness = get_AT_unsigned (enumeration, DW_AT_encoding); int declaration_p = get_AT_flag (enumeration, DW_AT_declaration); ctf_id_t enumeration_type_id; @@ -759,7 +760,9 @@ gen_ctf_enumeration_type (ctf_container_ref ctfc, dw_die_ref enumeration) /* Generate a CTF type for the enumeration. */ enumeration_type_id = ctf_add_enum (ctfc, CTF_ADD_ROOT, - enum_name, bit_size / 8, enumeration); + enum_name, bit_size / 8, + (signedness == DW_ATE_unsigned), + enumeration); /* Process the enumerators. */ { diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-enum-1.c b/gcc/testsuite/gcc.dg/debug/btf/btf-enum-1.c index 728493b..7e94052 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-enum-1.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-enum-1.c @@ -4,7 +4,7 @@ /* { dg-options "-O0 -gbtf -dA" } */ /* { dg-final { scan-assembler-times "\[\t \]0x6000004\[\t \]+\[^\n\]*btt_info" 1 } } */ -/* { dg-final { scan-assembler-times "\[\t \]0x6000003\[\t \]+\[^\n\]*btt_info" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x86000003\[\t \]+\[^\n\]*btt_info" 1 } } */ /* { dg-final { scan-assembler-times "ascii \"QAD.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ /* { dg-final { scan-assembler-times "ascii \"QED.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ /* { dg-final { scan-assembler-times "ascii \"QOD.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-enum64-1.c b/gcc/testsuite/gcc.dg/debug/btf/btf-enum64-1.c new file mode 100644 index 0000000..e443d4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-enum64-1.c @@ -0,0 +1,44 @@ +/* Test BTF generation for 64 bits enums. */ + +/* { dg-do compile } */ +/* { dg-options "-O0 -gbtf -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \].size\[\t \]myenum1,\[\t \]8" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \].size\[\t \]myenum2,\[\t \]8" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \].size\[\t \]myenum3,\[\t \]8" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x13000003\[\t \]+\[^\n\]*btt_info" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x93000003\[\t \]+\[^\n\]*btt_info" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0xffffffaa\[\t \]+\[^\n\]*bte_value_lo32" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0xff\[\t \]+\[^\n\]*bte_value_hi32" 3 } } */ +/* { dg-final { scan-assembler-times "ascii \"B1.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"B2.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"B3.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"C1.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"C2.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"C3.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"D1.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"D2.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"D3.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "bte_value_lo32" 9 } } */ +/* { dg-final { scan-assembler-times "bte_value_hi32" 9 } } */ + +enum default_enum +{ + B1 = 0xffffffffaa, + B2 = 0xbbbbbbbb, + B3 = 0xaabbccdd, +} myenum1 = B1; + +enum explicit_unsigned +{ + C1 = 0xffffffffbbUL, + C2 = 0xbbbbbbbb, + C3 = 0xaabbccdd, +} myenum2 = C1; + +enum signed64 +{ + D1 = 0xffffffffaa, + D2 = 0xbbbbbbbb, + D3 = -0x1, +} myenum3 = D1; -- cgit v1.1 From db55f1dda2692c3f778ae783bc7121891c79aec4 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 31 Oct 2022 20:13:02 +0100 Subject: libstdc++-v3: support for extended floating point types The following patch adds support for extended floating point types. C++23 removes the float/double/long double specializations from the spec and instead adds explicit(bool) specifier on the converting constructor. The patch uses that for converting constructor of the base template as well as the float/double/long double specializations's converting constructors (e.g. so that it handles convertion construction also from complex of extended floating point types). Copy ctor was already defaulted as the spec now requires. The patch also adds partial specialization for the _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t types because the base template doesn't use __complex__ but a pair of floating point values. The g++.dg/cpp23/ testcase verifies explicit(bool) works correctly. 2022-10-31 Jakub Jelinek gcc/testsuite/ * g++.dg/cpp23/ext-floating12.C: New test. libstdc++-v3/ * include/std/complex (complex::complex converting ctor): For C++23 use explicit specifier with constant expression. Explicitly cast both parts to _Tp. (__complex_abs, __complex_arg, __complex_cos, __complex_cosh, __complex_exp, __complex_log, __complex_sin, __complex_sinh, __complex_sqrt, __complex_tan, __complex_tanh, __complex_pow): Add __complex__ _Float{16,32,64,128} and __complex__ decltype(0.0bf16) overloads. (complex::complex converting ctor, complex::complex converting ctor, complex::complex converting ctor): For C++23 implement as template with explicit specifier with constant expression and explicit casts. (__complex_type): New template. (complex): New partial specialization for types with extended floating point types. (__complex_acos, __complex_asin, __complex_atan, __complex_acosh, __complex_asinh, __complex_atanh): Add __complex__ _Float{16,32,64,128} and __complex__ decltype(0.0bf16) overloads. (__complex_proj): Likewise. Add template for complex of extended floating point types. * include/bits/cpp_type_traits.h (__is_floating): Specialize for _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t. * testsuite/26_numerics/complex/ext_c++23.cc: New test. --- gcc/testsuite/g++.dg/cpp23/ext-floating12.C | 182 ++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp23/ext-floating12.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating12.C b/gcc/testsuite/g++.dg/cpp23/ext-floating12.C new file mode 100644 index 0000000..77ee4c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/ext-floating12.C @@ -0,0 +1,182 @@ +// P1467R9 - Extended floating-point types and standard names. +// { dg-do compile { target { c++23 && { i?86-*-linux* x86_64-*-linux* } } } } +// { dg-options "" } + +#include +#include + +#if !defined(__STDCPP_FLOAT32_T__) \ + || !defined(__STDCPP_FLOAT64_T__) || !defined(__STDCPP_FLOAT128_T__) \ + || __FLT_MAX_EXP__ != __FLT32_MAX_EXP__ || __FLT_MANT_DIG__ != __FLT32_MANT_DIG__ \ + || __DBL_MAX_EXP__ != __FLT64_MAX_EXP__ || __DBL_MANT_DIG__ != __FLT64_MANT_DIG__ \ + || __LDBL_MAX_EXP__ != __FLT128_MAX_EXP__ || __LDBL_MANT_DIG__ >= __FLT128_MANT_DIG__ \ + || !defined(__SIZEOF_FLOAT128__) +#error Unexpected set of floating point types +#endif + +using namespace std; + +int +main() +{ + complex a01(complex(1.0f, 2.0f)); + complex a02 = complex(1.0f, 2.0f); + complex a03(complex(1.0, 2.0)); + complex a04 = complex(1.0, 2.0); // { dg-error "conversion from 'complex' to non-scalar type 'complex' requested" } + complex a05(complex(1.0L, 2.0L)); + complex a06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex' requested" } + complex a07(complex(1.0f32, 2.0f32)); + complex a08 = complex(1.0f32, 2.0f32); + complex a09(complex(1.0f64, 2.0f64)); + complex a10 = complex(1.0f64, 2.0f64); // { dg-error "conversion from 'complex<_Float64>' to non-scalar type 'complex' requested" } + complex a11(complex(1.0f128, 2.0f128)); + complex a12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex a13(complex(1.0f16, 2.0f16)); + complex a14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex a15(complex(1.0bf16, 2.0bf16)); + complex a16 = complex(1.0bf16, 2.0bf16); +#endif + complex b01(complex(1.0f, 2.0f)); + complex b02 = complex(1.0f, 2.0f); + complex b03(complex(1.0, 2.0)); + complex b04 = complex(1.0, 2.0); + complex b05(complex(1.0L, 2.0L)); + complex b06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex' requested" } + complex b07(complex(1.0f32, 2.0f32)); + complex b08 = complex(1.0f32, 2.0f32); + complex b09(complex(1.0f64, 2.0f64)); + complex b10 = complex(1.0f64, 2.0f64); + complex b11(complex(1.0f128, 2.0f128)); + complex b12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex b13(complex(1.0f16, 2.0f16)); + complex b14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex b15(complex(1.0bf16, 2.0bf16)); + complex b16 = complex(1.0bf16, 2.0bf16); +#endif + complex c01(complex(1.0f, 2.0f)); + complex c02 = complex(1.0f, 2.0f); + complex c03(complex(1.0, 2.0)); + complex c04 = complex(1.0, 2.0); + complex c05(complex(1.0L, 2.0L)); + complex c06 = complex(1.0L, 2.0L); + complex c07(complex(1.0f32, 2.0f32)); + complex c08 = complex(1.0f32, 2.0f32); + complex c09(complex(1.0f64, 2.0f64)); + complex c10 = complex(1.0f64, 2.0f64); + complex c11(complex(1.0f128, 2.0f128)); + complex c12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex c13(complex(1.0f16, 2.0f16)); + complex c14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex c15(complex(1.0bf16, 2.0bf16)); + complex c16 = complex(1.0bf16, 2.0bf16); +#endif + complex d01(complex(1.0f, 2.0f)); + complex d02 = complex(1.0f, 2.0f); + complex d03(complex(1.0, 2.0)); + complex d04 = complex(1.0, 2.0); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float32>' requested" } + complex d05(complex(1.0L, 2.0L)); + complex d06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float32>' requested" } + complex d07(complex(1.0f32, 2.0f32)); + complex d08 = complex(1.0f32, 2.0f32); + complex d09(complex(1.0f64, 2.0f64)); + complex d10 = complex(1.0f64, 2.0f64); // { dg-error "conversion from 'complex<_Float64>' to non-scalar type 'complex<_Float32>' requested" } + complex d11(complex(1.0f128, 2.0f128)); + complex d12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex<_Float32>' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex d13(complex(1.0f16, 2.0f16)); + complex d14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex d15(complex(1.0bf16, 2.0bf16)); + complex d16 = complex(1.0bf16, 2.0bf16); +#endif + complex e01(complex(1.0f, 2.0f)); + complex e02 = complex(1.0f, 2.0f); + complex e03(complex(1.0, 2.0)); + complex e04 = complex(1.0, 2.0); + complex e05(complex(1.0L, 2.0L)); + complex e06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float64>' requested" } + complex e07(complex(1.0f32, 2.0f32)); + complex e08 = complex(1.0f32, 2.0f32); + complex e09(complex(1.0f64, 2.0f64)); + complex e10 = complex(1.0f64, 2.0f64); + complex e11(complex(1.0f128, 2.0f128)); + complex e12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex<_Float64>' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex e13(complex(1.0f16, 2.0f16)); + complex e14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex e15(complex(1.0bf16, 2.0bf16)); + complex e16 = complex(1.0bf16, 2.0bf16); +#endif + complex f01(complex(1.0f, 2.0f)); + complex f02 = complex(1.0f, 2.0f); + complex f03(complex(1.0, 2.0)); + complex f04 = complex(1.0, 2.0); + complex f05(complex(1.0L, 2.0L)); + complex f06 = complex(1.0L, 2.0L); + complex f07(complex(1.0f32, 2.0f32)); + complex f08 = complex(1.0f32, 2.0f32); + complex f09(complex(1.0f64, 2.0f64)); + complex f10 = complex(1.0f64, 2.0f64); + complex f11(complex(1.0f128, 2.0f128)); + complex f12 = complex(1.0f128, 2.0f128); +#ifdef __STDCPP_FLOAT16_T__ + complex f13(complex(1.0f16, 2.0f16)); + complex f14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex f15(complex(1.0bf16, 2.0bf16)); + complex f16 = complex(1.0bf16, 2.0bf16); +#endif +#ifdef __STDCPP_FLOAT16_T__ + complex g01(complex(1.0f, 2.0f)); + complex g02 = complex(1.0f, 2.0f); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g03(complex(1.0, 2.0)); + complex g04 = complex(1.0, 2.0); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g05(complex(1.0L, 2.0L)); + complex g06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g07(complex(1.0f32, 2.0f32)); + complex g08 = complex(1.0f32, 2.0f32); // { dg-error "conversion from 'complex<_Float32>' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g09(complex(1.0f64, 2.0f64)); + complex g10 = complex(1.0f64, 2.0f64); // { dg-error "conversion from 'complex<_Float64>' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g11(complex(1.0f128, 2.0f128)); + complex g12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g13(complex(1.0f16, 2.0f16)); + complex g14 = complex(1.0f16, 2.0f16); +#ifdef __STDCPP_BFLOAT16_T__ + complex g15(complex(1.0bf16, 2.0bf16)); + complex g16 = complex(1.0bf16, 2.0bf16); // { dg-error "conversion from 'complex<\[^\n\r]*>' to non-scalar type 'complex<_Float16>' requested" "" { target { float16 && bfloat16 } } } +#endif +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex h01(complex(1.0f, 2.0f)); + complex h02 = complex(1.0f, 2.0f); // { dg-error "conversion from 'complex' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h03(complex(1.0, 2.0)); + complex h04 = complex(1.0, 2.0); // { dg-error "conversion from 'complex' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h05(complex(1.0L, 2.0L)); + complex h06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h07(complex(1.0f32, 2.0f32)); + complex h08 = complex(1.0f32, 2.0f32); // { dg-error "conversion from 'complex<_Float32>' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h09(complex(1.0f64, 2.0f64)); + complex h10 = complex(1.0f64, 2.0f64); // { dg-error "conversion from 'complex<_Float64>' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h11(complex(1.0f128, 2.0f128)); + complex h12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } +#ifdef __STDCPP_FLOAT16_T__ + complex h13(complex(1.0f16, 2.0f16)); + complex h14 = complex(1.0f16, 2.0f16); // { dg-error "conversion from 'complex<_Float16>' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target { float16 && bfloat16 } } } +#endif + complex h15(complex(1.0bf16, 2.0bf16)); + complex h16 = complex(1.0bf16, 2.0bf16); +#endif +} -- cgit v1.1 From 9a8b868d7a3e0c4e754a3c2f21c524fec4a6b0ab Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 1 Nov 2022 00:19:02 +0000 Subject: Daily bump. --- gcc/ChangeLog | 291 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/testsuite/ChangeLog | 51 +++++++++ 3 files changed, 343 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 82da445..f7ab7da 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,294 @@ +2022-10-31 Guillermo E. Martinez + + * btfout.cc (btf_calc_num_vbytes): Compute enumeration size depending of + enumerator type btf_enum{,64}. + (btf_asm_type): Update btf_kflag according to enumeration type sign + using dtd_enum_unsigned field for both: BTF_KIND_ENUM{,64}. + (btf_asm_enum_const): New argument to represent the size of + the BTF enum type, writing the enumerator constant value for + 32 bits, if it's 64 bits then explicitly writes lower 32-bits + value and higher 32-bits value. + (output_asm_btf_enum_list): Add enumeration size argument. + * ctfc.cc (ctf_add_enum): New argument to represent CTF enum + basic information. + (ctf_add_generic): Use of ei_{name. size, unsigned} to build the + dtd structure containing enumeration information. + (ctf_add_enumerator): Update comment mention support for BTF + enumeration in 64-bits. + * dwarf2ctf.cc (gen_ctf_enumeration_type): Extract signedness + for enumeration type and use it in ctf_add_enum. + * ctfc.h (ctf_dmdef): Update dmd_value to HOST_WIDE_INT to allow + use 32/64 bits enumerators. + information. + (ctf_dtdef): New field to describe enum signedness. + +2022-10-31 Ju-Zhe Zhong + + * config/riscv/riscv-vector-builtins-bases.cc: Change constexpr back to CONSTEXPR. + * config/riscv/riscv-vector-builtins-shapes.cc (SHAPE): Ditto. + * config/riscv/riscv-vector-builtins.cc (struct registered_function_hasher): Ditto. + * config/riscv/riscv-vector-builtins.h (struct rvv_arg_type_info): Ditto. + +2022-10-31 Andrew Stubbs + + * config/gcn/gcn-valu.md (fminmaxop): New iterator. + (3): New define_expand. + (3): Likewise. + (reduc__scal_): Likewise. + * config/gcn/gcn.md (fexpander): New attribute. + +2022-10-31 Andrew Stubbs + + * config/gcn/gcn-valu.md (V64_SI): Delete iterator. + (V64_DI): Likewise. + (V64_1REG): Likewise. + (V64_INT_1REG): Likewise. + (V64_2REG): Likewise. + (V64_ALL): Likewise. + (V64_FP): Likewise. + (reduc__scal_): Use V_ALL. Use gen_vec_extract. + (fold_left_plus_): Use V_FP. + (*_dpp_shr_): Use V_1REG. + (*_dpp_shr_): Use V_DI. + (*plus_carry_dpp_shr_): Use V_INT_1REG. + (*plus_carry_in_dpp_shr_): Use V_SI. + (*plus_carry_dpp_shr_): Use V_DI. + (mov_from_lane63_): Delete. + (mov_from_lane63_): Delete. + * config/gcn/gcn.cc (gcn_expand_reduc_scalar): Support partial vectors. + * config/gcn/gcn.md (unspec): Remove UNSPEC_MOV_FROM_LANE63. + +2022-10-31 Andrew Stubbs + + * config/gcn/gcn.cc (gcn_simd_clone_compute_vecsize_and_simdlen): + Set base_type as ARG_UNUSED. + +2022-10-31 Jakub Jelinek + + * builtin-types.def (BT_COMPLEX_FLOAT16, BT_COMPLEX_FLOAT32, + BT_COMPLEX_FLOAT64, BT_COMPLEX_FLOAT128, BT_COMPLEX_FLOAT32X, + BT_COMPLEX_FLOAT64X, BT_COMPLEX_FLOAT128X, + BT_FN_COMPLEX_FLOAT16_COMPLEX_FLOAT16, + BT_FN_COMPLEX_FLOAT32_COMPLEX_FLOAT32, + BT_FN_COMPLEX_FLOAT64_COMPLEX_FLOAT64, + BT_FN_COMPLEX_FLOAT128_COMPLEX_FLOAT128, + BT_FN_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X, + BT_FN_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X, + BT_FN_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X, + BT_FN_FLOAT16_COMPLEX_FLOAT16, BT_FN_FLOAT32_COMPLEX_FLOAT32, + BT_FN_FLOAT64_COMPLEX_FLOAT64, BT_FN_FLOAT128_COMPLEX_FLOAT128, + BT_FN_FLOAT32X_COMPLEX_FLOAT32X, BT_FN_FLOAT64X_COMPLEX_FLOAT64X, + BT_FN_FLOAT128X_COMPLEX_FLOAT128X, + BT_FN_COMPLEX_FLOAT16_COMPLEX_FLOAT16_COMPLEX_FLOAT16, + BT_FN_COMPLEX_FLOAT32_COMPLEX_FLOAT32_COMPLEX_FLOAT32, + BT_FN_COMPLEX_FLOAT64_COMPLEX_FLOAT64_COMPLEX_FLOAT64, + BT_FN_COMPLEX_FLOAT128_COMPLEX_FLOAT128_COMPLEX_FLOAT128, + BT_FN_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X_COMPLEX_FLOAT32X, + BT_FN_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X_COMPLEX_FLOAT64X, + BT_FN_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X_COMPLEX_FLOAT128X): New. + * builtins.def (CABS_TYPE, CACOSH_TYPE, CARG_TYPE, CASINH_TYPE, + CPOW_TYPE, CPROJ_TYPE): Define and undefine later. + (BUILT_IN_CABS, BUILT_IN_CACOSH, BUILT_IN_CACOS, BUILT_IN_CARG, + BUILT_IN_CASINH, BUILT_IN_CASIN, BUILT_IN_CATANH, BUILT_IN_CATAN, + BUILT_IN_CCOSH, BUILT_IN_CCOS, BUILT_IN_CEXP, BUILT_IN_CLOG, + BUILT_IN_CPOW, BUILT_IN_CPROJ, BUILT_IN_CSINH, BUILT_IN_CSIN, + BUILT_IN_CSQRT, BUILT_IN_CTANH, BUILT_IN_CTAN): Add + DEF_EXT_LIB_FLOATN_NX_BUILTINS. + * fold-const-call.cc (fold_const_call_sc, fold_const_call_cc, + fold_const_call_ccc): Add various CASE_CFN_*_FN: cases when + CASE_CFN_* is present. + * gimple-ssa-backprop.cc (backprop::process_builtin_call_use): + Likewise. + * builtins.cc (expand_builtin, fold_builtin_1): Likewise. + * fold-const.cc (negate_mathfn_p, tree_expr_finite_p, + tree_expr_maybe_signaling_nan_p, tree_expr_maybe_nan_p, + tree_expr_maybe_real_minus_zero_p, tree_call_nonnegative_warnv_p): + Likewise. + +2022-10-31 Jakub Jelinek + + * builtin-types.def (BT_FN_BFLOAT16_BFLOAT16_BFLOAT16): New. + * builtins.def (BUILT_IN_NEXTAFTERF16B): New builtin. + * fold-const-call.cc (fold_const_call_sss): Handle + CFN_BUILT_IN_NEXTAFTERF16B. + +2022-10-31 Jakub Jelinek + + * builtin-types.def (BT_FLOAT16_PTR, BT_FLOAT32_PTR, BT_FLOAT64_PTR, + BT_FLOAT128_PTR, BT_FLOAT32X_PTR, BT_FLOAT64X_PTR, BT_FLOAT128X_PTR): + New DEF_PRIMITIVE_TYPE. + (BT_FN_INT_FLOAT16, BT_FN_INT_FLOAT32, BT_FN_INT_FLOAT64, + BT_FN_INT_FLOAT128, BT_FN_INT_FLOAT32X, BT_FN_INT_FLOAT64X, + BT_FN_INT_FLOAT128X, BT_FN_LONG_FLOAT16, BT_FN_LONG_FLOAT32, + BT_FN_LONG_FLOAT64, BT_FN_LONG_FLOAT128, BT_FN_LONG_FLOAT32X, + BT_FN_LONG_FLOAT64X, BT_FN_LONG_FLOAT128X, BT_FN_LONGLONG_FLOAT16, + BT_FN_LONGLONG_FLOAT32, BT_FN_LONGLONG_FLOAT64, + BT_FN_LONGLONG_FLOAT128, BT_FN_LONGLONG_FLOAT32X, + BT_FN_LONGLONG_FLOAT64X, BT_FN_LONGLONG_FLOAT128X): New + DEF_FUNCTION_TYPE_1. + (BT_FN_FLOAT16_FLOAT16_FLOAT16PTR, BT_FN_FLOAT32_FLOAT32_FLOAT32PTR, + BT_FN_FLOAT64_FLOAT64_FLOAT64PTR, BT_FN_FLOAT128_FLOAT128_FLOAT128PTR, + BT_FN_FLOAT32X_FLOAT32X_FLOAT32XPTR, + BT_FN_FLOAT64X_FLOAT64X_FLOAT64XPTR, + BT_FN_FLOAT128X_FLOAT128X_FLOAT128XPTR, BT_FN_FLOAT16_FLOAT16_INT, + BT_FN_FLOAT32_FLOAT32_INT, BT_FN_FLOAT64_FLOAT64_INT, + BT_FN_FLOAT128_FLOAT128_INT, BT_FN_FLOAT32X_FLOAT32X_INT, + BT_FN_FLOAT64X_FLOAT64X_INT, BT_FN_FLOAT128X_FLOAT128X_INT, + BT_FN_FLOAT16_FLOAT16_INTPTR, BT_FN_FLOAT32_FLOAT32_INTPTR, + BT_FN_FLOAT64_FLOAT64_INTPTR, BT_FN_FLOAT128_FLOAT128_INTPTR, + BT_FN_FLOAT32X_FLOAT32X_INTPTR, BT_FN_FLOAT64X_FLOAT64X_INTPTR, + BT_FN_FLOAT128X_FLOAT128X_INTPTR, BT_FN_FLOAT16_FLOAT16_LONG, + BT_FN_FLOAT32_FLOAT32_LONG, BT_FN_FLOAT64_FLOAT64_LONG, + BT_FN_FLOAT128_FLOAT128_LONG, BT_FN_FLOAT32X_FLOAT32X_LONG, + BT_FN_FLOAT64X_FLOAT64X_LONG, BT_FN_FLOAT128X_FLOAT128X_LONG): New + DEF_FUNCTION_TYPE_2. + (BT_FN_FLOAT16_FLOAT16_FLOAT16_INTPTR, + BT_FN_FLOAT32_FLOAT32_FLOAT32_INTPTR, + BT_FN_FLOAT64_FLOAT64_FLOAT64_INTPTR, + BT_FN_FLOAT128_FLOAT128_FLOAT128_INTPTR, + BT_FN_FLOAT32X_FLOAT32X_FLOAT32X_INTPTR, + BT_FN_FLOAT64X_FLOAT64X_FLOAT64X_INTPTR, + BT_FN_FLOAT128X_FLOAT128X_FLOAT128X_INTPTR): New DEF_FUNCTION_TYPE_3. + * builtins.def (ACOSH_TYPE, ATAN2_TYPE, ATANH_TYPE, COSH_TYPE, + FDIM_TYPE, HUGE_VAL_TYPE, HYPOT_TYPE, ILOGB_TYPE, LDEXP_TYPE, + LGAMMA_TYPE, LLRINT_TYPE, LOG10_TYPE, LRINT_TYPE, MODF_TYPE, + NEXTAFTER_TYPE, REMQUO_TYPE, SCALBLN_TYPE, SCALBN_TYPE, SINH_TYPE): + Define and undefine later. + (FMIN_TYPE, SQRT_TYPE): Undefine at a later line. + (INF_TYPE): Define at a later line. + (BUILT_IN_ACOSH, BUILT_IN_ACOS, BUILT_IN_ASINH, BUILT_IN_ASIN, + BUILT_IN_ATAN2, BUILT_IN_ATANH, BUILT_IN_ATAN, BUILT_IN_CBRT, + BUILT_IN_COSH, BUILT_IN_COS, BUILT_IN_ERFC, BUILT_IN_ERF, + BUILT_IN_EXP2, BUILT_IN_EXP, BUILT_IN_EXPM1, BUILT_IN_FDIM, + BUILT_IN_FMOD, BUILT_IN_FREXP, BUILT_IN_HYPOT, BUILT_IN_ILOGB, + BUILT_IN_LDEXP, BUILT_IN_LGAMMA, BUILT_IN_LLRINT, BUILT_IN_LLROUND, + BUILT_IN_LOG10, BUILT_IN_LOG1P, BUILT_IN_LOG2, BUILT_IN_LOGB, + BUILT_IN_LOG, BUILT_IN_LRINT, BUILT_IN_LROUND, BUILT_IN_MODF, + BUILT_IN_NEXTAFTER, BUILT_IN_POW, BUILT_IN_REMAINDER, BUILT_IN_REMQUO, + BUILT_IN_SCALBLN, BUILT_IN_SCALBN, BUILT_IN_SINH, BUILT_IN_SIN, + BUILT_IN_TANH, BUILT_IN_TAN, BUILT_IN_TGAMMA): Add + DEF_EXT_LIB_FLOATN_NX_BUILTINS. + (BUILT_IN_HUGE_VAL): Use HUGE_VAL_TYPE instead of INF_TYPE in + DEF_GCC_FLOATN_NX_BUILTINS. + * fold-const-call.cc (fold_const_call_ss): Add various CASE_CFN_*_FN: + cases when CASE_CFN_* is present. + (fold_const_call_sss): Likewise. + * builtins.cc (mathfn_built_in_2): Use CASE_MATHFN_FLOATN instead of + CASE_MATHFN for various builtins in SEQ_OF_CASE_MATHFN macro. + (builtin_with_linkage_p): Add CASE_FLT_FN_FLOATN_NX for various + builtins next to CASE_FLT_FN. + * fold-const.cc (tree_call_nonnegative_warnv_p): Add CASE_CFN_*_FN: + next to CASE_CFN_*: for various builtins. + * tree-call-cdce.cc (can_test_argument_range): Add + CASE_FLT_FN_FLOATN_NX next to CASE_FLT_FN for various builtins. + (edom_only_function): Likewise. + +2022-10-31 konglin1 + + * common/config/i386/i386-common.cc + (OPTION_MASK_ISA2_AVXNECONVERT_SET, + OPTION_MASK_ISA2_AVXNECONVERT_UNSET): New. + (ix86_handle_option): Handle -mavxneconvert, unset + avxneconvert when avx2 is disabled. + * common/config/i386/i386-cpuinfo.h (processor_types): Add + FEATURE_AVXNECONVERT. + * common/config/i386/i386-isas.h: Add ISA_NAME_TABLE_ENTRY for + avxneconvert. + * common/config/i386/cpuinfo.h (get_available_features): + Detect avxneconvert. + * config.gcc: Add avxneconvertintrin.h + * config/i386/avxneconvertintrin.h: New. + * config/i386/avx512bf16vlintrin.h (_mm256_cvtneps_pbh): + Unified builtin with avxneconvert. + (_mm_cvtneps_pbh): Ditto. + * config/i386/cpuid.h (bit_AVXNECONVERT): New. + * config/i386/i386-builtin-types.def: Add + DEF_POINTER_TYPE (PCV8HF, V8HF, CONST), + DEF_POINTER_TYPE (PCV8BF, V8BF, CONST), + DEF_POINTER_TYPE (PCV16HF, V16HF, CONST), + DEF_POINTER_TYPE (PCV16BF, V16BF, CONST), + DEF_FUNCTION_TYPE (V4SF, PCBFLOAT16), + DEF_FUNCTION_TYPE (V4SF, PCFLOAT16), + DEF_FUNCTION_TYPE (V8SF, PCBFLOAT16), + DEF_FUNCTION_TYPE (V8SF, PCFLOAT16), + DEF_FUNCTION_TYPE (V4SF, PCV8BF), + DEF_FUNCTION_TYPE (V4SF, PCV8HF), + DEF_FUNCTION_TYPE (V8SF, PCV16HF), + DEF_FUNCTION_TYPE (V8SF, PCV16BF), + * config/i386/i386-builtin.def: Add new builtins. + * config/i386/i386-c.cc (ix86_target_macros_internal): Define + __AVXNECONVERT__. + * config/i386/i386-expand.cc (ix86_expand_special_args_builtin): + Handle V4SF_FTYPE_PCBFLOAT16,V8SF_FTYPE_PCBFLOAT16, V4SF_FTYPE_PCFLOAT16, + V8SF_FTYPE_PCFLOAT16,V4SF_FTYPE_PCV8BF, + V4SF_FTYPE_PCV8HF,V8SF_FTYPE_PCV16BF,V8SF_FTYPE_PCV16HF. + * config/i386/i386-isa.def : Add DEF_PTA(AVXNECONVERT) New. + * config/i386/i386-options.cc (isa2_opts): Add -mavxneconvert. + (ix86_valid_target_attribute_inner_p): Handle avxneconvert. + * config/i386/i386.md: Add attr avx512bf16vl and avxneconvert. + * config/i386/i386.opt: Add option -mavxneconvert. + * config/i386/immintrin.h: Inculde avxneconvertintrin.h. + * config/i386/sse.md (vbcstnebf162ps_): New define_insn. + (vbcstnesh2ps_): Ditto. + (vcvtnee2ps_):Ditto. + (vcvtneo2ps_):Ditto. + (vcvtneps2bf16_v4sf): Ditto. + (*vcvtneps2bf16_v4sf): Ditto. + (vcvtneps2bf16_v8sf): Ditto. + * doc/invoke.texi: Document -mavxneconvert. + * doc/extend.texi: Document avxneconvert. + * doc/sourcebuild.texi: Document target avxneconvert. + +2022-10-31 konglin1 + + * config/i386/avx512bf16intrin.h (__attribute__): Change short to bf16. + (_mm_cvtsbh_ss): Ditto. + (_mm512_cvtne2ps_pbh): Ditto. + (_mm512_mask_cvtne2ps_pbh): Ditto. + (_mm512_maskz_cvtne2ps_pbh): Ditto. + * config/i386/avx512bf16vlintrin.h (__attribute__): Ditto. + (_mm256_cvtne2ps_pbh): Ditto. + (_mm256_mask_cvtne2ps_pbh): Ditto. + (_mm256_maskz_cvtne2ps_pbh): Ditto. + (_mm_cvtne2ps_pbh): Ditto. + (_mm_mask_cvtne2ps_pbh): Ditto. + (_mm_maskz_cvtne2ps_pbh): Ditto. + (_mm_cvtness_sbh): Ditto. + * config/i386/i386-builtin-types.def (V8BF): Add new + DEF_VECTOR_TYPE for BFmode. + (V16BF): Ditto. + (V32BF): Ditto. + * config/i386/i386-builtin.def (BDESC): Fixed builtins. + * config/i386/i386-expand.cc (ix86_expand_args_builtin): Changed + avx512bf16 ix86_builtin_func_type included HI to BF. + * config/i386/immintrin.h: Add SSE2 depend for avx512bf16. + * config/i386/sse.md (TARGET_AVX512VL): Changed HI vector to BF + vector. + (avx512f_cvtneps2bf16_v4sf): New define_expand. + (*avx512f_cvtneps2bf16_v4sf): New define_insn. + (avx512f_cvtneps2bf16_v4sf_maskz):Ditto. + (avx512f_cvtneps2bf16_v4sf_mask): Ditto. + (avx512f_cvtneps2bf16_v4sf_mask_1): Ditto. + +2022-10-31 liuhongt + + PR target/107261 + * config/i386/i386-modes.def (VECTOR_MODE): Support V2BFmode. + * config/i386/i386.cc (classify_argument): Handle V4BFmode and + V2BFmode. + (ix86_convert_const_vector_to_integer): Ditto. + * config/i386/i386.h (VALID_AVX512FP16_REG_MODE): Remove + V2BFmode. + (VALID_SSE2_REG_MODE): Add V4BFmode and V2BFmode. + (VALID_MMX_REG_MODE): Add V4BFmode. + * config/i386/i386.md (mode): Add V4BF and V2BF. + (MODE_SIZE): Ditto. + * config/i386/mmx.md (MMXMODE) Add V4BF. + (V_32): Add V2BF. + (V_16_32_64): Add V4BF and V2BF. + (mmxinsnmode): Add V4BF and V2BF. + (*mov_internal): Hanlde V4BFmode and V2BFmode. + 2022-10-29 Eric Botcazou * configure.ac (sjlj-exceptions): Restore dropped line. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index bed449a..3950253 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20221031 +20221101 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6e6635e..9dee429 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,54 @@ +2022-10-31 Jakub Jelinek + + * g++.dg/cpp23/ext-floating12.C: New test. + +2022-10-31 Guillermo E. Martinez + + * gcc.dg/debug/btf/btf-enum-1.c: Update testcase, with correct + info.kflags encoding. + * gcc.dg/debug/btf/btf-enum64-1.c: New testcase. + +2022-10-31 Jakub Jelinek + + * gcc.dg/torture/floatn-builtin.h: Add tests for newly added builtins. + +2022-10-31 konglin1 + + * gcc.target/i386/avx-check.h: Add avxneconvert check. + * gcc.target/i386/funcspec-56.inc: Add new target attribute. + * gcc.target/i386/sse-12.c: Add -mavxneconvert. + * gcc.target/i386/sse-13.c: Ditto. + * gcc.target/i386/sse-14.c: Ditto. + * gcc.target/i386/sse-22.c: Ditto. + * gcc.target/i386/sse-23.c: Ditto. + * g++.dg/other/i386-2.C: Ditto. + * g++.dg/other/i386-3.C: Ditto. + * lib/target-supports.exp:add check_effective_target_avxneconvert. + * gcc.target/i386/avx-ne-convert-1.c: New test. + * gcc.target/i386/avx-ne-convert-vbcstnebf162ps-2.c: Ditto. + * gcc.target/i386/avx-ne-convert-vbcstnesh2ps-2.c: Ditto. + * gcc.target/i386/avx-ne-convert-vcvtneebf162ps-2.c: Ditto. + * gcc.target/i386/avx-ne-convert-vcvtneeph2ps-2.c: Ditto. + * gcc.target/i386/avx-ne-convert-vcvtneobf162ps-2.c: Ditto. + * gcc.target/i386/avx-ne-convert-vcvtneoph2ps-2.c: Ditto. + * gcc.target/i386/avx-ne-convert-vcvtneps2bf16-2.c: Ditto. + * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c: Rename.. + * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1a.c: To this. + * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1b.c: New test. + +2022-10-31 konglin1 + + * gcc.target/i386/avx512bf16-cvtsbh2ss-1.c: Add fpmath option. + * gcc.target/i386/avx512bf16-vdpbf16ps-2.c: Fixed + scan-assembler. + * gcc.target/i386/avx512bf16vl-cvtness2sbh-1.c: Add x/y suffix + for vcvtneps2bf16. + * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1.c: Ditto. + +2022-10-31 liuhongt + + * gcc.target/i386/pr107261.c: New test. + 2022-10-29 Iain Buclaw * gdc.dg/simd19630.d: Move tests with errors to ... -- cgit v1.1 From 1b9a5cc9ec08e9f239dd2096edcc447b7a72f64a Mon Sep 17 00:00:00 2001 From: "Cui,Lili" Date: Tue, 1 Nov 2022 09:16:49 +0800 Subject: Add attribute hot judgement for INLINE_HINT_known_hot hint. We set up INLINE_HINT_known_hot hint only when we have profile feedback, now add function attribute judgement for it, when both caller and callee have __attribute__((hot)), we will also set up INLINE_HINT_known_hot hint for it. With this patch applied, ADL Multi-copy: 538.imagic_r 16.7% ICX Multi-copy: 538.imagic_r 15.2% CLX Multi-copy: 538.imagic_r 12.7% Znver3 Multi-copy: 538.imagic_r 10.6% Arm Multi-copy: 538.imagic_r 13.4% gcc/ChangeLog * ipa-inline-analysis.cc (do_estimate_edge_time): Add function attribute judgement for INLINE_HINT_known_hot hint. gcc/testsuite/ChangeLog: * gcc.dg/ipa/inlinehint-6.c: New test. --- gcc/ipa-inline-analysis.cc | 13 ++++++--- gcc/testsuite/gcc.dg/ipa/inlinehint-6.c | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/inlinehint-6.c (limited to 'gcc') diff --git a/gcc/ipa-inline-analysis.cc b/gcc/ipa-inline-analysis.cc index 1ca685d..7bd29c3 100644 --- a/gcc/ipa-inline-analysis.cc +++ b/gcc/ipa-inline-analysis.cc @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-utils.h" #include "cfgexpand.h" #include "gimplify.h" +#include "attribs.h" /* Cached node/edge growths. */ fast_call_summary *edge_growth_cache = NULL; @@ -249,15 +250,19 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time) hints = estimates.hints; } - /* When we have profile feedback, we can quite safely identify hot - edges and for those we disable size limits. Don't do that when - probability that caller will call the callee is low however, since it + /* When we have profile feedback or function attribute, we can quite safely + identify hot edges and for those we disable size limits. Don't do that + when probability that caller will call the callee is low however, since it may hurt optimization of the caller's hot path. */ - if (edge->count.ipa ().initialized_p () && edge->maybe_hot_p () + if ((edge->count.ipa ().initialized_p () && edge->maybe_hot_p () && (edge->count.ipa () * 2 > (edge->caller->inlined_to ? edge->caller->inlined_to->count.ipa () : edge->caller->count.ipa ()))) + || (lookup_attribute ("hot", DECL_ATTRIBUTES (edge->caller->decl)) + != NULL + && lookup_attribute ("hot", DECL_ATTRIBUTES (edge->callee->decl)) + != NULL)) hints |= INLINE_HINT_known_hot; gcc_checking_assert (size >= 0); diff --git a/gcc/testsuite/gcc.dg/ipa/inlinehint-6.c b/gcc/testsuite/gcc.dg/ipa/inlinehint-6.c new file mode 100644 index 0000000..1f3be64 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/inlinehint-6.c @@ -0,0 +1,47 @@ +/* { dg-options "-O3 -c -fdump-ipa-inline-details -fno-early-inlining -fno-ipa-cp" } */ +/* { dg-add-options bind_pic_locally } */ + +#define size_t long long int + +struct A +{ + size_t f1, f2, f3, f4; +}; +struct C +{ + struct A a; + size_t b; +}; +struct C x; + +__attribute__((hot)) struct C callee (struct A *a, struct C *c) +{ + c->a=(*a); + + if((c->b + 7) & 17) + { + c->a.f1 = c->a.f2 + c->a.f1; + c->a.f2 = c->a.f3 - c->a.f2; + c->a.f3 = c->a.f2 + c->a.f3; + c->a.f4 = c->a.f2 - c->a.f4; + c->b = c->a.f2; + + } + return *c; +} + +__attribute__((hot)) struct C caller (size_t d, size_t e, size_t f, size_t g, struct C *c) +{ + struct A a; + a.f1 = 1 + d; + a.f2 = e; + a.f3 = 12 + f; + a.f4 = 68 + g; + if (c->b > 0) + return callee (&a, c); + else + return *c; +} + +/* { dg-final { scan-ipa-dump "known_hot" "inline" } } */ + -- cgit v1.1 From 6a1f27f45e44bcfbcc06a1aad74bb076e56eda36 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 31 Oct 2022 13:37:13 -0400 Subject: c++: formatting tweaks gcc/cp/ChangeLog: * decl.cc (duplicate_decls): Reformat loop. * parser.cc (cp_parser_member_declaration): Add newline. * semantics.cc: Remove newline. --- gcc/cp/decl.cc | 9 +++------ gcc/cp/parser.cc | 1 + gcc/cp/semantics.cc | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index c7f1937..87cb7a6 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2343,12 +2343,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) DECL_INITIAL (old_result) = DECL_INITIAL (new_result); if (DECL_FUNCTION_TEMPLATE_P (newdecl)) { - tree parm; - DECL_ARGUMENTS (old_result) - = DECL_ARGUMENTS (new_result); - for (parm = DECL_ARGUMENTS (old_result); parm; - parm = DECL_CHAIN (parm)) - DECL_CONTEXT (parm) = old_result; + DECL_ARGUMENTS (old_result) = DECL_ARGUMENTS (new_result); + for (tree p = DECL_ARGUMENTS (old_result); p; p = DECL_CHAIN (p)) + DECL_CONTEXT (p) = old_result; if (tree fc = DECL_FRIEND_CONTEXT (new_result)) SET_DECL_FRIEND_CONTEXT (old_result, fc); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 9bdc609..6a5b065 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -27522,6 +27522,7 @@ cp_parser_member_declaration (cp_parser* parser) decl = grokfield (declarator, &decl_specifiers, initializer, /*init_const_expr_p=*/true, asm_specification, attributes); + if (parser->fully_implicit_function_template_p) { if (friend_p) diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 36aa9c4..7c5f90b 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -731,7 +731,6 @@ end_maybe_infinite_loop (tree cond) } } - /* Begin a conditional that might contain a declaration. When generating normal code, we want the declaration to appear before the statement containing the conditional. When generating template code, we want the -- cgit v1.1 From 43c40f114a68edc9a9cc9963dc940c11806ff863 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 31 Oct 2022 13:38:41 -0400 Subject: c++: set TREE_NOTHROW after genericize genericize might introduce function calls (and does on the contracts branch), so it's safer to set this flag later. gcc/cp/ChangeLog: * decl.cc (finish_function): Set TREE_NOTHROW later in the function. --- gcc/cp/decl.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 87cb7a6..6e98ea3 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -17867,14 +17867,6 @@ finish_function (bool inline_p) finish_fname_decls (); - /* If this function can't throw any exceptions, remember that. */ - if (!processing_template_decl - && !cp_function_chain->can_throw - && !flag_non_call_exceptions - && !decl_replaceable_p (fndecl, - opt_for_fn (fndecl, flag_semantic_interposition))) - TREE_NOTHROW (fndecl) = 1; - /* This must come after expand_function_end because cleanups might have declarations (from inline functions) that need to go into this function's blocks. */ @@ -18099,6 +18091,14 @@ finish_function (bool inline_p) && !DECL_OMP_DECLARE_REDUCTION_P (fndecl)) cp_genericize (fndecl); + /* If this function can't throw any exceptions, remember that. */ + if (!processing_template_decl + && !cp_function_chain->can_throw + && !flag_non_call_exceptions + && !decl_replaceable_p (fndecl, + opt_for_fn (fndecl, flag_semantic_interposition))) + TREE_NOTHROW (fndecl) = 1; + /* Emit the resumer and destroyer functions now, providing that we have not encountered some fatal error. */ if (coro_emit_helpers) -- cgit v1.1 From af6d747df7e311a6555dda3a75f6724ecc4481bd Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 31 Oct 2022 13:40:10 -0400 Subject: c++: pass std attributes to make_call_declarator It seems preferable to pass these to the function rather than set them separately after the call. gcc/cp/ChangeLog: * parser.cc (make_call_declarator): Add std_attrs parm. (cp_parser_lambda_declarator_opt): Pass it. (cp_parser_direct_declarator): Pass it. --- gcc/cp/parser.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 6a5b065..6da3280 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -1607,7 +1607,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) static cp_declarator *make_call_declarator (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, - tree, tree, tree, tree, location_t); + tree, tree, tree, tree, tree, location_t); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1780,7 +1780,8 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, /* Make a declarator for the function given by TARGET, with the indicated PARMS. The CV_QUALIFIERS apply to the function, as in "const"-qualified member function. The EXCEPTION_SPECIFICATION - indicates what exceptions can be thrown. */ + indicates what exceptions can be thrown. STD_ATTRS contains + attributes that appertain to the function type. */ cp_declarator * make_call_declarator (cp_declarator *target, @@ -1792,6 +1793,7 @@ make_call_declarator (cp_declarator *target, tree exception_specification, tree late_return_type, tree requires_clause, + tree std_attrs, location_t parens_loc) { cp_declarator *declarator; @@ -1816,6 +1818,8 @@ make_call_declarator (cp_declarator *target, else declarator->parameter_pack_p = false; + declarator->std_attributes = std_attrs; + return declarator; } @@ -11684,8 +11688,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) exception_spec, return_type, trailing_requires_clause, + std_attrs, UNKNOWN_LOCATION); - declarator->std_attributes = std_attrs; fco = grokmethod (&return_type_specs, declarator, @@ -23264,8 +23268,8 @@ cp_parser_direct_declarator (cp_parser* parser, exception_specification, late_return, requires_clause, + attrs, parens_loc); - declarator->std_attributes = attrs; declarator->attributes = gnu_attrs; /* Any subsequent parameter lists are to do with return type, so are not those of the declared -- cgit v1.1 From 5c5ef2f9ab545b680cd4bb6c540a9dadb12ead86 Mon Sep 17 00:00:00 2001 From: liuhongt Date: Thu, 27 Oct 2022 18:48:41 +0800 Subject: Enable more optimization for 32-bit/64-bit shrd/shld with imm shift count. This patch doens't handle variable count since it require 5 insns to be combined to get wanted pattern, but current pass_combine only supports at most 4. This patch doesn't handle 16-bit shrd/shld either. gcc/ChangeLog: PR target/55583 * config/i386/i386.md (*x86_64_shld_1): Rename to .. (x86_64_shld_1): .. this. (*x86_shld_1): Rename to .. (x86_shld_1): .. this. (*x86_64_shrd_1): Rename to .. (x86_64_shrd_1): .. this. (*x86_shrd_1): Rename to .. (x86_shrd_1): .. this. (*x86_64_shld_shrd_1_nozext): New pre_reload splitter. (*x86_shld_shrd_1_nozext): Ditto. (*x86_64_shrd_shld_1_nozext): Ditto. (*x86_shrd_shld_1_nozext): Ditto. gcc/testsuite/ChangeLog: * gcc.target/i386/pr55583.c: New test. --- gcc/config/i386/i386.md | 150 +++++++++++++++++++++++++++++++- gcc/testsuite/gcc.target/i386/pr55583.c | 27 ++++++ 2 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr55583.c (limited to 'gcc') diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index f28c2a1..8556798 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -12479,7 +12479,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "*x86_64_shld_1" +(define_insn "x86_64_shld_1" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") (ior:DI (ashift:DI (match_dup 0) (match_operand:QI 2 "const_0_to_63_operand")) @@ -12500,6 +12500,42 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) +(define_insn_and_split "*x86_64_shld_shrd_1_nozext" + [(set (match_operand:DI 0 "nonimmediate_operand") + (ior:DI (ashift:DI (match_operand:DI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_63_operand")) + (lshiftrt:DI + (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_63_operand")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT + && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + if (rtx_equal_p (operands[4], operands[0])) + { + operands[1] = force_reg (DImode, operands[1]); + emit_insn (gen_x86_64_shld_1 (operands[0], operands[1], operands[2], operands[3])); + } + else if (rtx_equal_p (operands[1], operands[0])) + { + operands[4] = force_reg (DImode, operands[4]); + emit_insn (gen_x86_64_shrd_1 (operands[0], operands[4], operands[3], operands[2])); + } + else + { + operands[1] = force_reg (DImode, operands[1]); + rtx tmp = gen_reg_rtx (DImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_64_shld_1 (tmp, operands[1], operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; +}) + (define_insn_and_split "*x86_64_shld_2" [(set (match_operand:DI 0 "nonimmediate_operand") (ior:DI (ashift:DI (match_dup 0) @@ -12543,7 +12579,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "*x86_shld_1" +(define_insn "x86_shld_1" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") (ior:SI (ashift:SI (match_dup 0) (match_operand:QI 2 "const_0_to_31_operand")) @@ -12564,6 +12600,41 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) +(define_insn_and_split "*x86_shld_shrd_1_nozext" + [(set (match_operand:SI 0 "nonimmediate_operand") + (ior:SI (ashift:SI (match_operand:SI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_31_operand")) + (lshiftrt:SI + (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_31_operand")))) + (clobber (reg:CC FLAGS_REG))] + "INTVAL (operands[3]) == 32 - INTVAL (operands[2]) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + if (rtx_equal_p (operands[4], operands[0])) + { + operands[1] = force_reg (SImode, operands[1]); + emit_insn (gen_x86_shld_1 (operands[0], operands[1], operands[2], operands[3])); + } + else if (rtx_equal_p (operands[1], operands[0])) + { + operands[4] = force_reg (SImode, operands[4]); + emit_insn (gen_x86_shrd_1 (operands[0], operands[4], operands[3], operands[2])); + } + else + { + operands[1] = force_reg (SImode, operands[1]); + rtx tmp = gen_reg_rtx (SImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_shld_1 (tmp, operands[1], operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; +}) + (define_insn_and_split "*x86_shld_2" [(set (match_operand:SI 0 "nonimmediate_operand") (ior:SI (ashift:SI (match_dup 0) @@ -13442,7 +13513,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "*x86_64_shrd_1" +(define_insn "x86_64_shrd_1" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") (ior:DI (lshiftrt:DI (match_dup 0) (match_operand:QI 2 "const_0_to_63_operand")) @@ -13463,6 +13534,42 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) +(define_insn_and_split "*x86_64_shrd_shld_1_nozext" + [(set (match_operand:DI 0 "nonimmediate_operand") + (ior:DI (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_63_operand")) + (ashift:DI + (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_63_operand")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT + && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + if (rtx_equal_p (operands[4], operands[0])) + { + operands[1] = force_reg (DImode, operands[1]); + emit_insn (gen_x86_64_shrd_1 (operands[0], operands[1], operands[2], operands[3])); + } + else if (rtx_equal_p (operands[1], operands[0])) + { + operands[4] = force_reg (DImode, operands[4]); + emit_insn (gen_x86_64_shld_1 (operands[0], operands[4], operands[3], operands[2])); + } + else + { + operands[1] = force_reg (DImode, operands[1]); + rtx tmp = gen_reg_rtx (DImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_64_shrd_1 (tmp, operands[1], operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; +}) + (define_insn_and_split "*x86_64_shrd_2" [(set (match_operand:DI 0 "nonimmediate_operand") (ior:DI (lshiftrt:DI (match_dup 0) @@ -13506,7 +13613,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "*x86_shrd_1" +(define_insn "x86_shrd_1" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") (ior:SI (lshiftrt:SI (match_dup 0) (match_operand:QI 2 "const_0_to_31_operand")) @@ -13527,6 +13634,41 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) +(define_insn_and_split "*x86_shrd_shld_1_nozext" + [(set (match_operand:SI 0 "nonimmediate_operand") + (ior:SI (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_31_operand")) + (ashift:SI + (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_31_operand")))) + (clobber (reg:CC FLAGS_REG))] + "INTVAL (operands[3]) == 32 - INTVAL (operands[2]) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + if (rtx_equal_p (operands[4], operands[0])) + { + operands[1] = force_reg (SImode, operands[1]); + emit_insn (gen_x86_shrd_1 (operands[0], operands[1], operands[2], operands[3])); + } + else if (rtx_equal_p (operands[1], operands[0])) + { + operands[4] = force_reg (SImode, operands[4]); + emit_insn (gen_x86_shld_1 (operands[0], operands[4], operands[3], operands[2])); + } + else + { + operands[1] = force_reg (SImode, operands[1]); + rtx tmp = gen_reg_rtx (SImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_shrd_1 (tmp, operands[1], operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; +}) + (define_insn_and_split "*x86_shrd_2" [(set (match_operand:SI 0 "nonimmediate_operand") (ior:SI (lshiftrt:SI (match_dup 0) diff --git a/gcc/testsuite/gcc.target/i386/pr55583.c b/gcc/testsuite/gcc.target/i386/pr55583.c new file mode 100644 index 0000000..1c128b5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr55583.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wno-shift-count-overflow" } */ +/* { dg-final { scan-assembler-times {(?n)shrd[ql]?[\t ]*\$2} 4 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times {(?n)shrdl?[\t ]*\$2} 2 { target ia32 } } } */ +/* { dg-final { scan-assembler-times {(?n)shldl?[\t ]*\$2} 1 { target ia32 } } } */ +/* { dg-final { scan-assembler-times {(?n)shld[ql]?[\t ]*\$2} 2 { target { ! ia32 } } } } */ + +typedef unsigned long u64; +typedef unsigned int u32; +typedef unsigned short u16; + +long a, b; +int c, d; +short e, f; +const int n = 2; + +void test64r () { b = ((u64)b >> n) | (a << (64 - n)); } +void test32r () { d = ((u32)d >> n) | (c << (32 - n)); } + +unsigned long ua, ub; +unsigned int uc, ud; +unsigned short ue, uf; + +void testu64l () { ub = (ub << n) | (ua >> (64 - n)); } +void testu64r () { ub = (ub >> n) | (ua << (64 - n)); } +void testu32l () { ud = (ud << n) | (uc >> (32 - n)); } +void testu32r () { ud = (ud >> n) | (uc << (32 - n)); } -- cgit v1.1 From 4acc4c2be84d66075d60736623c3a7134d129eaa Mon Sep 17 00:00:00 2001 From: liuhongt Date: Tue, 25 Oct 2022 17:10:23 +0800 Subject: Fix incorrect digit constraint Matching constraints are used in these circumstances. More precisely, the two operands that match must include one input-only operand and one output-only operand. Moreover, the digit must be a smaller number than the number of the operand that uses it in the constraint. In pr107057, the 2 operands in the pattern are both input operands. gcc/ChangeLog: PR target/107057 * config/i386/sse.md (*vec_interleave_highv2df): Remove constraint 1. (*vec_interleave_lowv2df): Ditto. (vec_concatv2df): Ditto. (*avx512f_unpcklpd512): Ditto and renamed to .. (avx512f_unpcklpd512): .. this. (avx512f_movddup512): Change to define_insn. (avx_movddup256): Ditto. (*avx_unpcklpd256): Remove constraint 1 and renamed to .. (avx_unpcklpd256): .. this. * config/i386/i386.cc (ix86_vec_interleave_v2df_operator_ok): Disallow MEM_P (op1) && MEM_P (op2). gcc/testsuite/ChangeLog: * gcc.target/i386/pr107057.c: New test. --- gcc/config/i386/i386.cc | 2 +- gcc/config/i386/sse.md | 140 +++++++++++++------------------ gcc/testsuite/gcc.target/i386/pr107057.c | 19 +++++ 3 files changed, 77 insertions(+), 84 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr107057.c (limited to 'gcc') diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index c0f3714..f858649 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -15657,7 +15657,7 @@ ix86_vec_interleave_v2df_operator_ok (rtx operands[3], bool high) if (MEM_P (operands[0])) return rtx_equal_p (operands[0], operands[1 + high]); if (MEM_P (operands[1]) && MEM_P (operands[2])) - return TARGET_SSE3 && rtx_equal_p (operands[1], operands[2]); + return false; return true; } diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 3df9e07..fa93ae7 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -12168,107 +12168,88 @@ }) (define_insn "*vec_interleave_highv2df" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,v,v,x,v,m") + [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,v,x,v,m") (vec_select:V2DF (vec_concat:V4DF - (match_operand:V2DF 1 "nonimmediate_operand" " 0,v,o,o,o,v") - (match_operand:V2DF 2 "nonimmediate_operand" " x,v,1,0,v,0")) + (match_operand:V2DF 1 "nonimmediate_operand" " 0,v,o,o,v") + (match_operand:V2DF 2 "nonimmediate_operand" " x,v,0,v,0")) (parallel [(const_int 1) (const_int 3)])))] "TARGET_SSE2 && ix86_vec_interleave_v2df_operator_ok (operands, 1)" "@ unpckhpd\t{%2, %0|%0, %2} vunpckhpd\t{%2, %1, %0|%0, %1, %2} - %vmovddup\t{%H1, %0|%0, %H1} movlpd\t{%H1, %0|%0, %H1} vmovlpd\t{%H1, %2, %0|%0, %2, %H1} %vmovhpd\t{%1, %0|%q0, %1}" - [(set_attr "isa" "noavx,avx,sse3,noavx,avx,*") - (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov") + [(set_attr "isa" "noavx,avx,noavx,avx,*") + (set_attr "type" "sselog,sselog,ssemov,ssemov,ssemov") (set (attr "prefix_data16") - (if_then_else (eq_attr "alternative" "3,5") + (if_then_else (eq_attr "alternative" "2,4") (const_string "1") (const_string "*"))) - (set_attr "prefix" "orig,maybe_evex,maybe_vex,orig,maybe_evex,maybe_vex") - (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")]) + (set_attr "prefix" "orig,maybe_evex,orig,maybe_evex,maybe_vex") + (set_attr "mode" "V2DF,V2DF,V1DF,V1DF,V1DF")]) -(define_expand "avx512f_movddup512" - [(set (match_operand:V8DF 0 "register_operand") +(define_insn "avx512f_movddup512" + [(set (match_operand:V8DF 0 "register_operand" "=v") (vec_select:V8DF (vec_concat:V16DF - (match_operand:V8DF 1 "nonimmediate_operand") + (match_operand:V8DF 1 "nonimmediate_operand" "m") (match_dup 1)) (parallel [(const_int 0) (const_int 8) (const_int 2) (const_int 10) (const_int 4) (const_int 12) (const_int 6) (const_int 14)])))] - "TARGET_AVX512F") - -(define_expand "avx512f_unpcklpd512" - [(set (match_operand:V8DF 0 "register_operand") - (vec_select:V8DF - (vec_concat:V16DF - (match_operand:V8DF 1 "register_operand") - (match_operand:V8DF 2 "nonimmediate_operand")) - (parallel [(const_int 0) (const_int 8) - (const_int 2) (const_int 10) - (const_int 4) (const_int 12) - (const_int 6) (const_int 14)])))] - "TARGET_AVX512F") + "TARGET_AVX512F" + "vmovddup\t{%1, %0|%0, %1}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "V8DF")]) -(define_insn "*avx512f_unpcklpd512" - [(set (match_operand:V8DF 0 "register_operand" "=v,v") +(define_insn "avx512f_unpcklpd512" + [(set (match_operand:V8DF 0 "register_operand" "=v") (vec_select:V8DF (vec_concat:V16DF - (match_operand:V8DF 1 "nonimmediate_operand" "vm, v") - (match_operand:V8DF 2 "nonimmediate_operand" "1 ,vm")) + (match_operand:V8DF 1 "register_operand" "v") + (match_operand:V8DF 2 "nonimmediate_operand" "vm")) (parallel [(const_int 0) (const_int 8) (const_int 2) (const_int 10) (const_int 4) (const_int 12) (const_int 6) (const_int 14)])))] "TARGET_AVX512F" - "@ - vmovddup\t{%1, %0|%0, %1} - vunpcklpd\t{%2, %1, %0|%0, %1, %2}" + "vunpcklpd\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "sselog") (set_attr "prefix" "evex") (set_attr "mode" "V8DF")]) ;; Recall that the 256-bit unpck insns only shuffle within their lanes. -(define_expand "avx_movddup256" - [(set (match_operand:V4DF 0 "register_operand") +(define_insn "avx_movddup256" + [(set (match_operand:V4DF 0 "register_operand" "=v") (vec_select:V4DF (vec_concat:V8DF - (match_operand:V4DF 1 "nonimmediate_operand") + (match_operand:V4DF 1 "nonimmediate_operand" "m") (match_dup 1)) (parallel [(const_int 0) (const_int 4) (const_int 2) (const_int 6)])))] - "TARGET_AVX && ") - -(define_expand "avx_unpcklpd256" - [(set (match_operand:V4DF 0 "register_operand") - (vec_select:V4DF - (vec_concat:V8DF - (match_operand:V4DF 1 "register_operand") - (match_operand:V4DF 2 "nonimmediate_operand")) - (parallel [(const_int 0) (const_int 4) - (const_int 2) (const_int 6)])))] - "TARGET_AVX && ") + "TARGET_AVX && " + "vmovddup\t{%1, %0|%0, %1}" + [(set_attr "type" "sselog") + (set_attr "prefix" "") + (set_attr "mode" "V4DF")]) -(define_insn "*avx_unpcklpd256" - [(set (match_operand:V4DF 0 "register_operand" "=v,v") +(define_insn "avx_unpcklpd256" + [(set (match_operand:V4DF 0 "register_operand" "=v") (vec_select:V4DF (vec_concat:V8DF - (match_operand:V4DF 1 "nonimmediate_operand" " v,m") - (match_operand:V4DF 2 "nonimmediate_operand" "vm,1")) + (match_operand:V4DF 1 "register_operand" " v") + (match_operand:V4DF 2 "nonimmediate_operand" "vm")) (parallel [(const_int 0) (const_int 4) (const_int 2) (const_int 6)])))] "TARGET_AVX && " - "@ - vunpcklpd\t{%2, %1, %0|%0, %1, %2} - vmovddup\t{%1, %0|%0, %1}" + "vunpcklpd\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "sselog") - (set_attr "prefix" "vex") + (set_attr "prefix" "") (set_attr "mode" "V4DF")]) (define_expand "vec_interleave_lowv4df" @@ -12330,29 +12311,28 @@ }) (define_insn "*vec_interleave_lowv2df" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,v,v,x,v,o") + [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,v,x,v,o") (vec_select:V2DF (vec_concat:V4DF - (match_operand:V2DF 1 "nonimmediate_operand" " 0,v,m,0,v,0") - (match_operand:V2DF 2 "nonimmediate_operand" " x,v,1,m,m,v")) + (match_operand:V2DF 1 "nonimmediate_operand" " 0,v,0,v,0") + (match_operand:V2DF 2 "nonimmediate_operand" " x,v,m,m,v")) (parallel [(const_int 0) (const_int 2)])))] "TARGET_SSE2 && ix86_vec_interleave_v2df_operator_ok (operands, 0)" "@ unpcklpd\t{%2, %0|%0, %2} vunpcklpd\t{%2, %1, %0|%0, %1, %2} - %vmovddup\t{%1, %0|%0, %q1} movhpd\t{%2, %0|%0, %q2} vmovhpd\t{%2, %1, %0|%0, %1, %q2} %vmovlpd\t{%2, %H0|%H0, %2}" - [(set_attr "isa" "noavx,avx,sse3,noavx,avx,*") - (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov") + [(set_attr "isa" "noavx,avx,noavx,avx,*") + (set_attr "type" "sselog,sselog,ssemov,ssemov,ssemov") (set (attr "prefix_data16") - (if_then_else (eq_attr "alternative" "3,5") + (if_then_else (eq_attr "alternative" "2,4") (const_string "1") (const_string "*"))) - (set_attr "prefix" "orig,maybe_evex,maybe_vex,orig,maybe_evex,maybe_vex") - (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")]) + (set_attr "prefix" "orig,maybe_evex,orig,maybe_evex,maybe_vex") + (set_attr "mode" "V2DF,V2DF,V1DF,V1DF,V1DF")]) (define_split [(set (match_operand:V2DF 0 "memory_operand") @@ -13558,56 +13538,50 @@ (set_attr "mode" "V2DF,DF,DF")]) (define_insn "vec_concatv2df" - [(set (match_operand:V2DF 0 "register_operand" "=x,x,v,x,v,x,x, v,x,x") + [(set (match_operand:V2DF 0 "register_operand" "=x,x,v,x,x, v,x,x") (vec_concat:V2DF - (match_operand:DF 1 "nonimmediate_operand" " 0,x,v,m,m,0,x,vm,0,0") - (match_operand:DF 2 "nonimm_or_0_operand" " x,x,v,1,1,m,m, C,x,m")))] - "TARGET_SSE - && (!(MEM_P (operands[1]) && MEM_P (operands[2])) - || (TARGET_SSE3 && rtx_equal_p (operands[1], operands[2])))" + (match_operand:DF 1 "nonimmediate_operand" " 0,x,v,0,x,vm,0,0") + (match_operand:DF 2 "nonimm_or_0_operand" " x,x,v,m,m, C,x,m")))] + "TARGET_SSE && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "@ unpcklpd\t{%2, %0|%0, %2} vunpcklpd\t{%2, %1, %0|%0, %1, %2} vunpcklpd\t{%2, %1, %0|%0, %1, %2} - %vmovddup\t{%1, %0|%0, %1} - vmovddup\t{%1, %0|%0, %1} movhpd\t{%2, %0|%0, %2} vmovhpd\t{%2, %1, %0|%0, %1, %2} %vmovq\t{%1, %0|%0, %1} movlhps\t{%2, %0|%0, %2} movhps\t{%2, %0|%0, %2}" [(set (attr "isa") - (cond [(eq_attr "alternative" "0,5") + (cond [(eq_attr "alternative" "0,3") (const_string "sse2_noavx") - (eq_attr "alternative" "1,6") + (eq_attr "alternative" "1,4") (const_string "avx") - (eq_attr "alternative" "2,4") + (eq_attr "alternative" "2") (const_string "avx512vl") - (eq_attr "alternative" "3") - (const_string "sse3") - (eq_attr "alternative" "7") + (eq_attr "alternative" "5") (const_string "sse2") ] (const_string "noavx"))) (set (attr "type") (if_then_else - (eq_attr "alternative" "0,1,2,3,4") + (eq_attr "alternative" "0,1,2") (const_string "sselog") (const_string "ssemov"))) (set (attr "prefix_data16") - (if_then_else (eq_attr "alternative" "5") + (if_then_else (eq_attr "alternative" "3") (const_string "1") (const_string "*"))) (set (attr "prefix") - (cond [(eq_attr "alternative" "1,6") + (cond [(eq_attr "alternative" "1,4") (const_string "vex") - (eq_attr "alternative" "2,4") + (eq_attr "alternative" "2") (const_string "evex") - (eq_attr "alternative" "3,7") + (eq_attr "alternative" "5") (const_string "maybe_vex") ] (const_string "orig"))) - (set_attr "mode" "V2DF,V2DF,V2DF, DF, DF, V1DF,V1DF,DF,V4SF,V2SF")]) + (set_attr "mode" "V2DF,V2DF,V2DF,V1DF,V1DF,DF,V4SF,V2SF")]) ;; vmovq clears also the higher bits. (define_insn "vec_set_0" diff --git a/gcc/testsuite/gcc.target/i386/pr107057.c b/gcc/testsuite/gcc.target/i386/pr107057.c new file mode 100644 index 0000000..40b49ac --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr107057.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mavx -mcmodel=large -O3" } */ + +typedef double v2df __attribute__ ((vector_size (16))); +v2df f (double a, double b) +{ + v2df v; + double *c = (double *)&v; + *c = a; + *(c+1) = b; + return v; +} +void g () +{ + v2df x = f (1.0, 1.0); + v2df y = f (2.0, 2.0); + for (;*(double *)&x<=8; x+=y) + g (); +} -- cgit v1.1 From 0122faae30fe1ad1dfa8c69f3d3f0428b996b600 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 31 Oct 2022 06:11:28 -0400 Subject: c++: Reorganize per-scope lambda discriminators We currently use a per-extra-scope counter to discriminate multiple lambdas in a particular such scope. This is not ABI compliant. This patch merely refactors the existing code to make it easier to drop in a conformant mangling -- there's no functional change here. I rename the LAMBDA_EXPR_DISCIMINATOR to LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR, foreshadowing that there'll be a new discriminator. To provide ABI warnings we'll need to calculate both, and that requires some repacking of the lambda_expr's fields. Finally, although we end up calling the discriminator setter and the scope recorder (nearly) always consecutively, it's clearer to handle it as two separate operations. That also allows us to remove the instantiation special-case for a null extra-scope. gcc/cp/ * cp-tree.h (LAMBDA_EXPR_DISCRIMINATOR): Rename to ... (LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR): ... here. (struct tree_lambda_expr): Make default_capture_mode & discriminator_scope bitfields. (record_null_lambda_scope) Delete. (record_lambda_scope_discriminator): Declare. * lambda.cc (struct lambda_discriminator): New struct. (lambda_scope, lambda_scope_stack): Adjust types. (lambda_count): Delete. (struct tree_int): Delete. (start_lambda_scope, finish_lambda_scope): Adjust. (record_lambda_scope): Only record the scope. (record_lambda_scope_discriminator): New. * mangle.cc (write_closure_type_name): Adjust. * module.cc (trees_out::core_vals): Likewise, (trees_in::core_vals): Likewise. * parser.cc (cp_parser_lambda_expression): Call record_lambda_scope_discriminator. * pt.cc (tsubst_lambda_expr): Adjust record_lambda_scope caling. Call record_lambda_scope_discriminator. Commonize control flow on tsubsting the operator function. libcc1/ * libcp1plugin.cc (plugin_start_closure): Adjust. gcc/testsuite/ * g++.dg/abi/lambda-sig1-17.C: New. * g++.dg/abi/lambda-sig1.h: New. * g++.dg/cpp1y/lambda-mangle-1.C: Extracted to ... * g++.dg/cpp1y/lambda-mangle-1.h: ... here. * g++.dg/cpp1y/lambda-mangle-1-11.C: New * g++.dg/cpp1y/lambda-mangle-1-17.C --- gcc/cp/cp-tree.h | 17 ++--- gcc/cp/lambda.cc | 96 +++++++++++++------------ gcc/cp/mangle.cc | 2 +- gcc/cp/module.cc | 4 +- gcc/cp/parser.cc | 5 +- gcc/cp/pt.cc | 50 ++++--------- gcc/testsuite/g++.dg/abi/lambda-sig1-17.C | 26 +++++++ gcc/testsuite/g++.dg/abi/lambda-sig1.h | 42 +++++++++++ gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C | 25 +++++++ gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C | 25 +++++++ gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C | 88 ----------------------- gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h | 89 +++++++++++++++++++++++ 12 files changed, 285 insertions(+), 184 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1-17.C create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1.h create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C delete mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h (limited to 'gcc') diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6d84514..4c0bacb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1500,9 +1500,10 @@ enum cp_lambda_default_capture_mode_type { #define LAMBDA_EXPR_EXTRA_SCOPE(NODE) \ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope) -/* If EXTRA_SCOPE, this is the number of the lambda within that scope. */ -#define LAMBDA_EXPR_DISCRIMINATOR(NODE) \ - (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator) +/* Lambdas in the same extra scope might need a discriminating count. + This is a single per-scope count. */ +#define LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR(NODE) \ + (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_scope) /* During parsing of the lambda, a vector of capture proxies which need to be pushed once we're done processing a nested lambda. */ @@ -1530,8 +1531,8 @@ struct GTY (()) tree_lambda_expr tree regen_info; vec *pending_proxies; location_t locus; - enum cp_lambda_default_capture_mode_type default_capture_mode : 8; - short int discriminator; + enum cp_lambda_default_capture_mode_type default_capture_mode : 2; + unsigned discriminator_scope : 15; // Per-scope discriminator }; /* Non-zero if this template specialization has access violations that @@ -7778,10 +7779,10 @@ extern tree cp_build_vec_convert (tree, location_t, tree, tsubst_flags_t); extern tree cp_build_bit_cast (location_t, tree, tree, tsubst_flags_t); -extern void start_lambda_scope (tree); -extern void record_lambda_scope (tree); -extern void record_null_lambda_scope (tree); +extern void start_lambda_scope (tree decl); extern void finish_lambda_scope (void); +extern void record_lambda_scope (tree lambda); +extern void record_lambda_scope_discriminator (tree lambda); extern tree start_lambda_function (tree fn, tree lambda_expr); extern void finish_lambda_function (tree body); extern bool regenerated_lambda_fn_p (tree); diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index e9d5d4d..d2673e2 100644 --- a/gcc/cp/lambda.cc +++ b/gcc/cp/lambda.cc @@ -1444,79 +1444,77 @@ is_lambda_ignored_entity (tree val) return false; } -/* Lambdas that appear in variable initializer or default argument scope - get that in their mangling, so we need to record it. We might as well - use the count for function and namespace scopes as well. */ -static GTY(()) tree lambda_scope; -static GTY(()) int lambda_count; -struct GTY(()) tree_int +/* Lambdas that appear in variable initializer or default argument + scope get that in their mangling, so we need to record it. Also, + multiple lambdas in the same scope may need a mangling + discriminator. Record in the same data structure. */ +struct GTY(()) lambda_discriminator { - tree t; - int i; + tree scope; + unsigned nesting; // Inside a function, VAR_DECLs get the function + // as scope. This counts that nesting. + unsigned count; // The per-scope counter. }; -static GTY(()) vec *lambda_scope_stack; +// The current scope. +static GTY(()) lambda_discriminator lambda_scope; +// Stack of previous scopes. +static GTY(()) vec *lambda_scope_stack; + +// Push DECL as lambda extra scope, also new discriminator counters. void start_lambda_scope (tree decl) { - tree_int ti; - gcc_assert (decl); - /* Once we're inside a function, we ignore variable scope and just push - the function again so that popping works properly. */ + gcc_checking_assert (decl); if (current_function_decl && TREE_CODE (decl) == VAR_DECL) - decl = current_function_decl; - ti.t = lambda_scope; - ti.i = lambda_count; - vec_safe_push (lambda_scope_stack, ti); - if (lambda_scope != decl) + // If we're inside a function, we ignore variable scope. Don't push. + lambda_scope.nesting++; + else { - /* Don't reset the count if we're still in the same function. */ - lambda_scope = decl; - lambda_count = 0; + vec_safe_push (lambda_scope_stack, lambda_scope); + lambda_scope.scope = decl; + lambda_scope.nesting = 0; + lambda_scope.count = 0; } } +// Pop from the current lambda extra scope. + void -record_lambda_scope (tree lambda) +finish_lambda_scope (void) { - LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope; - LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++; - if (lambda_scope) + if (!lambda_scope.nesting--) { - tree closure = LAMBDA_EXPR_CLOSURE (lambda); - gcc_checking_assert (closure); - maybe_key_decl (lambda_scope, TYPE_NAME (closure)); + lambda_scope = lambda_scope_stack->last (); + lambda_scope_stack->pop (); } } -/* This lambda is an instantiation of a lambda in a template default argument - that got no LAMBDA_EXPR_EXTRA_SCOPE, so this shouldn't either. But we do - need to use and increment the global count to avoid collisions. */ +// Record the current lambda scope into LAMBDA void -record_null_lambda_scope (tree lambda) +record_lambda_scope (tree lambda) { - if (vec_safe_is_empty (lambda_scope_stack)) - record_lambda_scope (lambda); - else + LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope.scope; + if (lambda_scope.scope) { - tree_int *p = lambda_scope_stack->begin(); - LAMBDA_EXPR_EXTRA_SCOPE (lambda) = p->t; - LAMBDA_EXPR_DISCRIMINATOR (lambda) = p->i++; + tree closure = LAMBDA_EXPR_CLOSURE (lambda); + gcc_checking_assert (closure); + maybe_key_decl (lambda_scope.scope, TYPE_NAME (closure)); } - gcc_assert (LAMBDA_EXPR_EXTRA_SCOPE (lambda) == NULL_TREE); } +// Record the per-scope discriminator of LAMBDA. If the extra scope +// is empty, we must use the empty scope counter, which might not be +// the live one. + void -finish_lambda_scope (void) +record_lambda_scope_discriminator (tree lambda) { - tree_int *p = &lambda_scope_stack->last (); - if (lambda_scope != p->t) - { - lambda_scope = p->t; - lambda_count = p->i; - } - lambda_scope_stack->pop (); + auto *slot = (vec_safe_is_empty (lambda_scope_stack) + || LAMBDA_EXPR_EXTRA_SCOPE (lambda) + ? &lambda_scope : lambda_scope_stack->begin ()); + LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda) = slot->count++; } tree @@ -1648,6 +1646,10 @@ prune_lambda_captures (tree body) } } +// Record the per-scope per-signature discriminator of LAMBDA. If the +// extra scope is empty, we must use the empty scope counter, which +// might not be the live one. + void finish_lambda_function (tree body) { diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index e396218..a62c975 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -1810,7 +1810,7 @@ write_closure_type_name (const tree type) write_method_parms (parms, /*method_p=*/1, fn); write_char ('E'); - write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda)); + write_compact_number (LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda)); } /* Convert NUMBER to ascii using base BASE and generating at least diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 9957df5..df05b52 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -6327,7 +6327,7 @@ trees_out::core_vals (tree t) if (streaming_p ()) { WU (((lang_tree_node *)t)->lambda_expression.default_capture_mode); - WU (((lang_tree_node *)t)->lambda_expression.discriminator); + WU (((lang_tree_node *)t)->lambda_expression.discriminator_scope); } break; @@ -6819,7 +6819,7 @@ trees_in::core_vals (tree t) = state->read_location (*this); RUC (cp_lambda_default_capture_mode_type, ((lang_tree_node *)t)->lambda_expression.default_capture_mode); - RU (((lang_tree_node *)t)->lambda_expression.discriminator); + RU (((lang_tree_node *)t)->lambda_expression.discriminator_scope); break; case OVERLOAD: diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 6da3280..e0e3cf3 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11035,6 +11035,7 @@ cp_parser_lambda_expression (cp_parser* parser) return error_mark_node; record_lambda_scope (lambda_expr); + record_lambda_scope_discriminator (lambda_expr); /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ determine_visibility (TYPE_NAME (type)); @@ -11085,9 +11086,7 @@ cp_parser_lambda_expression (cp_parser* parser) ok = false; if (ok) - { - cp_parser_lambda_body (parser, lambda_expr); - } + cp_parser_lambda_body (parser, lambda_expr); else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) { if (cp_parser_skip_to_closing_brace (parser)) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 51bfbbc..fc6279c 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -19866,21 +19866,13 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (type == error_mark_node) return error_mark_node; - if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE) - { - /* A lambda in a default argument outside a class gets no - LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But - tsubst_default_argument calls start_lambda_scope, so we need to - specifically ignore it here, and use the global scope. */ - record_null_lambda_scope (r); - - /* If we're pushed into another scope (PR105652), fix it. */ - if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t))) - TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type)) - = TYPE_CONTEXT (TREE_TYPE (t)); - } - else + if (LAMBDA_EXPR_EXTRA_SCOPE (t)) record_lambda_scope (r); + else if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t))) + /* If we're pushed into another scope (PR105652), fix it. */ + TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type)) + = TYPE_CONTEXT (TREE_TYPE (t)); + record_lambda_scope_discriminator (r); /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ determine_visibility (TYPE_NAME (type)); @@ -19911,29 +19903,17 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) fntype = build_memfn_type (fntype, type, type_memfn_quals (fntype), type_memfn_rqual (fntype)); - tree fn, tmpl; - if (oldtmpl) + tree inst = (oldtmpl + ? tsubst_template_decl (oldtmpl, args, complain, fntype) + : tsubst_function_decl (oldfn, args, complain, fntype)); + if (inst == error_mark_node) { - 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); - } - else - { - 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); + r = error_mark_node; + goto out; } + finish_member_declaration (inst); + + tree fn = oldtmpl ? DECL_TEMPLATE_RESULT (inst) : inst; /* Let finish_function set this. */ DECL_DECLARED_CONSTEXPR_P (fn) = false; diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C b/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C new file mode 100644 index 0000000..cb71209 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C @@ -0,0 +1,26 @@ +// { dg-do compile { target c++20 } } +// { dg-options -fabi-version=17 } + +#include "lambda-sig1.h" + +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE3_clEf:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfT_E1_clIiEEDafS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfT_E4_clIiEEDafS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlT_E2_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlT_E_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE3_clEf:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE6_clEf:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E1_clIiEEDafS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E4_clIiEEDafS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E7_clIiEEDafS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E2_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E5_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE0_clEi:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE3_clEi:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliT_E1_clIiEEDaiS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliT_E4_clIiEEDaiS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlT_E2_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlT_E_clIiEEDaS1_:} } } diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1.h b/gcc/testsuite/g++.dg/abi/lambda-sig1.h new file mode 100644 index 0000000..a8b77ae --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/lambda-sig1.h @@ -0,0 +1,42 @@ +template struct X +{ + void Fn () + { + { + auto v1 = [] (U) {}; + auto v2 = [] (T) {}; + auto v3 = [] (T, U) {}; + + v1 (1); + v2 (1); + v3 (1, 2); + } + if constexpr (I) + { + auto v1 = [] (U) {}; + auto v2 = [] (T) {}; + auto v3 = [] (T, U) {}; + + v1 (1); + v2 (1); + v3 (1, 2); + } + { + auto v1 = [] (U) {}; + auto v2 = [] (T) {}; + auto v3 = [] (T, U) {}; + + v1 (1); + v2 (1); + v3 (1, 2); + } + + }; +}; + +void f (X &x, X &y, X &z) +{ + x.Fn (); + y.Fn (); + z.Fn (); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C new file mode 100644 index 0000000..9847587 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C @@ -0,0 +1,25 @@ +// { dg-do compile { target c++14 } } +// { dg-additional-options -fabi-version=11 } + +// PRs 78621 + +#include "lambda-mangle-1.h" + +// We erroneously mangled lambda auto parms as-if template parameters (T_), +// rather than auto (Da). Fixed in abi version 11 + + +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } } diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C new file mode 100644 index 0000000..31af5b8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C @@ -0,0 +1,25 @@ +// { dg-do compile { target c++14 } } +// { dg-additional-options -fabi-version=17 } + +// PRs 78621 + +#include "lambda-mangle-1.h" + +// We erroneously mangled lambda auto parms as-if template parameters (T_), +// rather than auto (Da). Fixed in abi version 11 +// Up to abi version 17 we had a single per-scope discriminator + +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } } diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C deleted file mode 100644 index 8f13535..0000000 --- a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C +++ /dev/null @@ -1,88 +0,0 @@ -// { dg-do compile { target c++14 } } - -// PRs 78621 - -// We erroneously mangled lambda auto parms as-if template parameters (T_), -// rather than auto (Da). Fixed in abi version 11 - -template class X; - -template -T &&forward (T &v) -{ - return static_cast (v); -} - -template -void eat (T &v) -{ -} - -template - void eat (S &, T &v) -{ -} - -void Foo () -{ - auto lam = [](auto &) { }; - auto lam_1 = [](int &, auto &) { }; - auto lam_2 = [](auto &, X &) { }; - auto lam_3 = [](auto (*)[5]) { }; - - forward (lam); - forward (lam_1); - forward (lam_2); - forward (lam_3); - - eat (lam); - eat (lam_1); - eat (lam_2); - eat (lam_3); - - // The auto lambda should mangle similarly to the non-auto one - auto lambda_1 = [](float *, float *) { }; - auto lambda_2 = [](auto *, auto *) { }; - auto lambda_3 = [](auto *, auto *) { }; - - int *i; - - eat (i, lambda_1); - eat (i, lambda_2); - - // The autos should squangle to the first one. - eat (lambda_2, lambda_3); -} - -template void Bar () -{ - auto lambda_1 = [](X *, float *, float *) { }; - auto lambda_2 = [](X *, auto *, auto *) { }; - auto lambda_3 = [](X *, auto *...) {}; - - int *i; - - eat (i, lambda_1); - eat (i, lambda_2); - eat (i, lambda_3); -} - -void Baz () -{ - Bar (); -} - -// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } } -// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } } -// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } } -// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } } -// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } } -// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } } -// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } } -// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } } -// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } } -// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } } -// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } } -// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } } -// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } } -// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } } diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h new file mode 100644 index 0000000..c91ce01 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h @@ -0,0 +1,89 @@ +// { dg-do compile { target c++14 } } + +// PRs 78621 + +// We erroneously mangled lambda auto parms as-if template parameters (T_), +// rather than auto (Da). Fixed in abi version 11 + +template class X; + +template +T &&forward (T &v) +{ + return static_cast (v); +} + +template +void eat (T &v) +{ +} + +template + void eat (S &, T &v) +{ +} + +inline void Foo () +{ + auto lam = [](auto &) { }; + auto lam_1 = [](int &, auto &) { }; + auto lam_2 = [](auto &, X &) { }; + auto lam_3 = [](auto (*)[5]) { }; + + forward (lam); + forward (lam_1); + forward (lam_2); + forward (lam_3); + + eat (lam); + eat (lam_1); + eat (lam_2); + eat (lam_3); + + // The auto lambda should mangle similarly to the non-auto one + auto lambda_1 = [](float *, float *) { }; + auto lambda_2 = [](auto *, auto *) { }; + auto lambda_3 = [](auto *, auto *) { }; + + int *i; + + eat (i, lambda_1); + eat (i, lambda_2); + + // The autos should squangle to the first one. + eat (lambda_2, lambda_3); +} + +template void Bar () +{ + auto lambda_1 = [](X *, float *, float *) { }; + auto lambda_2 = [](X *, auto *, auto *) { }; + auto lambda_3 = [](X *, auto *...) {}; + + int *i; + + eat (i, lambda_1); + eat (i, lambda_2); + eat (i, lambda_3); +} + +void Baz () +{ + Bar (); + Foo (); +} + +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } } -- cgit v1.1 From 5cee5f94000ee5eabce9b223c44c7923c1c69f61 Mon Sep 17 00:00:00 2001 From: Alexander Monakov Date: Mon, 31 Oct 2022 17:35:57 +0300 Subject: i386: correct integer division modeling in znver.md In znver.md, division instructions have descriptions like (define_insn_reservation "znver1_idiv_DI" 41 (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "memory" "none")))) "znver1-double,znver1-ieu2*41") which says that DImode idiv has latency 41 (which is correct) and that it occupies 2nd integer execution unit for 41 consecutive cycles, but that is not correct: 1) the division instruction is partially pipelined, and has throughput 1/14, not 1/41; 2) for the most part it occupies a separate division unit, not the general arithmetic unit. Evidently, interaction of such 41-cycle paths with the rest of reservations causes a combinatorial explosion in the automaton. Fix this by modeling the integer division unit properly, and correcting reservations to use the measured reciprocal throughput of those instructions (available from uops.info). A similar correction for floating-point divisions is left for a followup patch. Top 5 znver table sizes, before: 68692 r znver1_ieu_check 68692 r znver1_ieu_transitions 99792 r znver1_ieu_min_issue_delay 428108 r znver1_fp_min_issue_delay 856216 r znver1_fp_transitions After: 1454 r znver1_ieu_translate 1454 r znver1_translate 2304 r znver1_ieu_transitions 428108 r znver1_fp_min_issue_delay 856216 r znver1_fp_transitions gcc/ChangeLog: PR target/87832 * config/i386/znver.md (znver1_idiv): New automaton. (znver1-idiv): New unit. (znver1_idiv_DI): Correct unit and cycles in the reservation. (znver1_idiv_SI): Ditto. (znver1_idiv_HI): Ditto. (znver1_idiv_QI): Ditto. (znver1_idiv_mem_DI): Ditto. (znver1_idiv_mem_SI): Ditto. (znver1_idiv_mem_HI): Ditto. (znver1_idiv_mem_QI): Ditto. (znver3_idiv_DI): Ditto. (znver3_idiv_SI): Ditto. (znver3_idiv_HI): Ditto. (znver3_idiv_QI): Ditto. (znver3_idiv_mem_DI): Ditto. (znver3_idiv_mem_SI): Ditto. (znver3_idiv_mem_HI): Ditto. (znver3_idiv_mem_QI): Ditto. --- gcc/config/i386/znver.md | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/znver.md b/gcc/config/i386/znver.md index 9c25b4e..4aa098f 100644 --- a/gcc/config/i386/znver.md +++ b/gcc/config/i386/znver.md @@ -23,8 +23,8 @@ ;; AMD znver1, znver2 and znver3 Scheduling ;; Modeling automatons for zen decoders, integer execution pipes, -;; AGU pipes and floating point execution units. -(define_automaton "znver1, znver1_ieu, znver1_fp, znver1_agu") +;; SIMD/FP domain, AGU pipes, and dividers. +(define_automaton "znver1, znver1_ieu, znver1_fp, znver1_agu, znver1_idiv") ;; Decoders unit has 4 decoders and all of them can decode fast path ;; and vector type instructions. @@ -93,6 +93,9 @@ +znver1-fp2+znver1-fp3 +znver1-agu0+znver1-agu1+znver2-agu2") +;; Dividers +(define_cpu_unit "znver1-idiv" "znver1_idiv") + ;; Call instruction (define_insn_reservation "znver1_call" 1 (and (eq_attr "cpu" "znver1") @@ -176,28 +179,28 @@ (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "memory" "none")))) - "znver1-double,znver1-ieu2*41") + "znver1-double,znver1-idiv*14") (define_insn_reservation "znver1_idiv_SI" 25 (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "SI") (eq_attr "memory" "none")))) - "znver1-double,znver1-ieu2*25") + "znver1-double,znver1-idiv*14") (define_insn_reservation "znver1_idiv_HI" 17 (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "HI") (eq_attr "memory" "none")))) - "znver1-double,znver1-ieu2*17") + "znver1-double,znver1-idiv*14") (define_insn_reservation "znver1_idiv_QI" 12 (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "QI") (eq_attr "memory" "none")))) - "znver1-direct,znver1-ieu2*12") + "znver1-direct,znver1-idiv*13") ;; Mem operands (define_insn_reservation "znver1_idiv_mem_DI" 45 @@ -205,84 +208,84 @@ (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "memory" "none")))) - "znver1-double,znver1-load,znver1-ieu2*41") + "znver1-double,znver1-load,znver1-idiv*14") (define_insn_reservation "znver1_idiv_mem_SI" 29 (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "SI") (eq_attr "memory" "none")))) - "znver1-double,znver1-load,znver1-ieu2*25") + "znver1-double,znver1-load,znver1-idiv*14") (define_insn_reservation "znver1_idiv_mem_HI" 21 (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "HI") (eq_attr "memory" "none")))) - "znver1-double,znver1-load,znver1-ieu2*17") + "znver1-double,znver1-load,znver1-idiv*14") (define_insn_reservation "znver1_idiv_mem_QI" 16 (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "QI") (eq_attr "memory" "none")))) - "znver1-direct,znver1-load,znver1-ieu2*12") + "znver1-direct,znver1-load,znver1-idiv*13") (define_insn_reservation "znver3_idiv_DI" 18 (and (eq_attr "cpu" "znver3") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "memory" "none")))) - "znver1-double,znver1-ieu2*18") + "znver1-double,znver1-idiv*7") (define_insn_reservation "znver3_idiv_SI" 12 (and (eq_attr "cpu" "znver3") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "SI") (eq_attr "memory" "none")))) - "znver1-double,znver1-ieu2*12") + "znver1-double,znver1-idiv*6") (define_insn_reservation "znver3_idiv_HI" 10 (and (eq_attr "cpu" "znver3") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "HI") (eq_attr "memory" "none")))) - "znver1-double,znver1-ieu2*10") + "znver1-double,znver1-idiv*4") (define_insn_reservation "znver3_idiv_QI" 9 (and (eq_attr "cpu" "znver3") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "QI") (eq_attr "memory" "none")))) - "znver1-direct,znver1-ieu2*9") + "znver1-direct,znver1-idiv*4") (define_insn_reservation "znver3_idiv_mem_DI" 22 (and (eq_attr "cpu" "znver3") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "memory" "load")))) - "znver1-double,znver1-load,znver1-ieu2*22") + "znver1-double,znver1-load,znver1-idiv*7") (define_insn_reservation "znver3_idiv_mem_SI" 16 (and (eq_attr "cpu" "znver3") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "SI") (eq_attr "memory" "load")))) - "znver1-double,znver1-load,znver1-ieu2*16") + "znver1-double,znver1-load,znver1-idiv*6") (define_insn_reservation "znver3_idiv_mem_HI" 14 (and (eq_attr "cpu" "znver3") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "HI") (eq_attr "memory" "load")))) - "znver1-double,znver1-load,znver1-ieu2*10") + "znver1-double,znver1-load,znver1-idiv*4") (define_insn_reservation "znver3_idiv_mem_QI" 13 (and (eq_attr "cpu" "znver3") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "QI") (eq_attr "memory" "load")))) - "znver1-direct,znver1-load,znver1-ieu2*9") + "znver1-direct,znver1-load,znver1-idiv*4") ;; STR ISHIFT which are micro coded. ;; Fix me: Latency need to be rechecked. -- cgit v1.1 From 7cc2824e39440dd71a9d2832c51ef260bb36d8ca Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Mon, 31 Oct 2022 09:53:01 -0400 Subject: Intersect with nonzero bits can indicate change incorrectly. * value-range.cc (irange::intersect_nonzero_bits): If new non-zero mask is the same as original, flag no change. --- gcc/value-range.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gcc') diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 03b3c4b..3743ec7 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -3017,6 +3017,10 @@ irange::intersect_nonzero_bits (const irange &r) if (mask_to_wi (m_nonzero_mask, t) != mask_to_wi (r.m_nonzero_mask, t)) { wide_int nz = get_nonzero_bits () & r.get_nonzero_bits (); + // If the nonzero bits did not change, return false. + if (nz == get_nonzero_bits ()) + return false; + m_nonzero_mask = wide_int_to_tree (t, nz); if (set_range_from_nonzero_bits ()) return true; -- cgit v1.1 From 592bbe3d7eb3cff656c731e84ad872719a4a9d16 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Mon, 31 Oct 2022 10:56:25 -0400 Subject: Allow queries on exit block. Ranger was not allowing the exit block to be queried for range_on_entry or exit. This removes that restriction. * gimple-range-cache.cc (ranger_cache::fill_block_cache): Allow exit block to be specified. (ranger_cache::range_from_dom): If exit block is specified, use the immediate predecessor instead of the dominator to start. * gimple-range.cc (gimple_ranger::range_on_exit): Allow query for exit block. --- gcc/gimple-range-cache.cc | 16 ++++++++++------ gcc/gimple-range.cc | 1 - 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index f279371..89e2403 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -1193,9 +1193,8 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb) Value_Range block_result (type); Value_Range undefined (type); - // At this point we shouldn't be looking at the def, entry or exit block. - gcc_checking_assert (bb != def_bb && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun) && - bb != EXIT_BLOCK_PTR_FOR_FN (cfun)); + // At this point we shouldn't be looking at the def, entry block. + gcc_checking_assert (bb != def_bb && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)); gcc_checking_assert (m_workback.length () == 0); // If the block cache is set, then we've already visited this block. @@ -1434,10 +1433,15 @@ ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb, // Default value is global range. get_global_range (r, name); + // The dominator of EXIT_BLOCK doesn't seem to be set, so at least handle + // the common single exit cases. + if (start_bb == EXIT_BLOCK_PTR_FOR_FN (cfun) && single_pred_p (start_bb)) + bb = single_pred_edge (start_bb)->src; + else + bb = get_immediate_dominator (CDI_DOMINATORS, start_bb); + // Search until a value is found, pushing blocks which may need calculating. - for (bb = get_immediate_dominator (CDI_DOMINATORS, start_bb); - bb; - prev_bb = bb, bb = get_immediate_dominator (CDI_DOMINATORS, bb)) + for ( ; bb; prev_bb = bb, bb = get_immediate_dominator (CDI_DOMINATORS, bb)) { // Accumulate any block exit inferred ranges. m_exit.maybe_adjust_range (infer, name, bb); diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 0584397..110cf57 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -167,7 +167,6 @@ void gimple_ranger::range_on_exit (vrange &r, basic_block bb, tree name) { // on-exit from the exit block? - gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)); gcc_checking_assert (gimple_range_ssa_p (name)); unsigned idx; -- cgit v1.1 From 7b1cdca6d6d594a8a9d88062252212e145f2f4eb Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Mon, 31 Oct 2022 15:18:00 -0400 Subject: Remove builtin_unreachable in VRP Removal of __builtin_unreachable calls were handled in an inconsistent way. This removes then in the VRP pass, and sets the global range appropriately. * tree-vrp.cc (class remove_unreachable): New. (remove_unreachable::maybe_register_block): New. (remove_unreachable::remove_and_update_globals): New. (rvrp_folder::rvrp_folder): Initialize m_unreachable. (rvrp_folder::post_fold_bb): Maybe register unreachable block. (rvrp_folder::m_unreachable): New member. (execute_ranger_vrp): Add final_pass flag, remove unreachables. --- gcc/tree-vrp.cc | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index e5a292b..f0e4d37 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -51,6 +51,183 @@ along with GCC; see the file COPYING3. If not see #include "value-pointer-equiv.h" #include "gimple-fold.h" #include "tree-dfa.h" +#include "tree-ssa-dce.h" + +// This class is utilized by VRP and ranger to remove __builtin_unreachable +// calls, and reflect any resulting global ranges. +// +// maybe_register_block () is called on basic blocks, and if that block +// matches the pattern of one branch being a builtin_unreachable, register +// the resulting executable edge in a list. +// +// After all blocks have been processed, remove_and_update_globals() will +// - check all exports from registered blocks +// - ensure the cache entry of each export is set with the appropriate range +// - rewrite the conditions to take the executable edge +// - perform DCE on any feeding instructions to those rewritten conditions +// +// Then each of the immediate use chain of each export is walked, and a new +// global range created by unioning the ranges at all remaining use locations. + +class remove_unreachable { +public: + remove_unreachable (gimple_ranger &r) : m_ranger (r) { m_list.create (30); } + ~remove_unreachable () { m_list.release (); } + void maybe_register_block (basic_block bb); + bool remove_and_update_globals (bool final_p); + vec m_list; + gimple_ranger &m_ranger; +}; + +// Check if block BB has a __builtin_unreachable () call on one arm, and +// register the executable edge if so. + +void +remove_unreachable::maybe_register_block (basic_block bb) +{ + gimple *s = gimple_outgoing_range_stmt_p (bb); + if (!s || gimple_code (s) != GIMPLE_COND) + return; + + edge e0 = EDGE_SUCC (bb, 0); + basic_block bb0 = e0->dest; + bool un0 = EDGE_COUNT (bb0->succs) == 0 + && gimple_seq_unreachable_p (bb_seq (bb0)); + edge e1 = EDGE_SUCC (bb, 1); + basic_block bb1 = e1->dest; + bool un1 = EDGE_COUNT (bb1->succs) == 0 + && gimple_seq_unreachable_p (bb_seq (bb1)); + + // If the 2 blocks are not different, ignore. + if (un0 == un1) + return; + + if (un0) + m_list.safe_push (e1); + else + m_list.safe_push (e0); +} + +// Process the edges in the list, change the conditions and removing any +// dead code feeding those conditions. Calculate the range of any +// names that may have been exported from those blocks, and determine if +// there is any updates to their global ranges.. +// FINAL_P indicates all builtin_unreachable calls should be removed. +// Return true if any builtin_unreachables/globals eliminated/updated. + +bool +remove_unreachable::remove_and_update_globals (bool final_p) +{ + if (m_list.length () == 0) + return false; + + bool change = false; + tree name; + unsigned i; + bitmap_iterator bi; + auto_bitmap all_exports; + for (i = 0; i < m_list.length (); i++) + { + edge e = m_list[i]; + gimple *s = gimple_outgoing_range_stmt_p (e->src); + gcc_checking_assert (gimple_code (s) == GIMPLE_COND); + bool lhs_p = TREE_CODE (gimple_cond_lhs (s)) == SSA_NAME; + bool rhs_p = TREE_CODE (gimple_cond_rhs (s)) == SSA_NAME; + // Do not remove __builtin_unreachable if it confers a relation, or + // that relation will be lost in subsequent passes. Unless its the + // final pass. + if (!final_p && lhs_p && rhs_p) + continue; + // If this is already a constant condition, don't look either + if (!lhs_p && !rhs_p) + continue; + + bool dominate_exit_p = true; + FOR_EACH_GORI_EXPORT_NAME (m_ranger.gori (), e->src, name) + { + // Ensure the cache is set for NAME in the succ block. + Value_Range r(TREE_TYPE (name)); + Value_Range ex(TREE_TYPE (name)); + m_ranger.range_on_entry (r, e->dest, name); + m_ranger.range_on_entry (ex, EXIT_BLOCK_PTR_FOR_FN (cfun), name); + // If the range produced by this __builtin_unreachacble expression + // is not fully reflected in the range at exit, then it does not + // dominate the exit of the funciton. + if (ex.intersect (r)) + dominate_exit_p = false; + } + + // If the exit is dominated, add to the export list. Otherwise if this + // isn't the final VRP pass, leave the call in the IL. + if (dominate_exit_p) + bitmap_ior_into (all_exports, m_ranger.gori ().exports (e->src)); + else if (!final_p) + continue; + + change = true; + // Rewrite the condition. + if (e->flags & EDGE_TRUE_VALUE) + gimple_cond_make_true (as_a (s)); + else + gimple_cond_make_false (as_a (s)); + update_stmt (s); + } + + if (bitmap_empty_p (all_exports)) + return false; + // Invoke DCE on all exported names to elimnate dead feeding defs + auto_bitmap dce; + bitmap_copy (dce, all_exports); + // Don't attempt to DCE parameters. + EXECUTE_IF_SET_IN_BITMAP (all_exports, 0, i, bi) + if (SSA_NAME_IS_DEFAULT_DEF (ssa_name (i))) + bitmap_clear_bit (dce, i); + simple_dce_from_worklist (dce); + + // Loop over all uses of each name and find maximal range. This is the + // new global range. + use_operand_p use_p; + imm_use_iterator iter; + EXECUTE_IF_SET_IN_BITMAP (all_exports, 0, i, bi) + { + name = ssa_name (i); + if (!name || SSA_NAME_IN_FREE_LIST (name)) + continue; + Value_Range r (TREE_TYPE (name)); + Value_Range exp_range (TREE_TYPE (name)); + r.set_undefined (); + FOR_EACH_IMM_USE_FAST (use_p, iter, name) + { + gimple *use_stmt = USE_STMT (use_p); + if (is_gimple_debug (use_stmt)) + continue; + if (!m_ranger.range_of_expr (exp_range, name, use_stmt)) + exp_range.set_varying (TREE_TYPE (name)); + r.union_ (exp_range); + if (r.varying_p ()) + break; + } + // Include the on-exit range to ensure non-dominated unreachables + // don't incorrectly impact the global range. + m_ranger.range_on_entry (exp_range, EXIT_BLOCK_PTR_FOR_FN (cfun), name); + r.union_ (exp_range); + if (r.varying_p () || r.undefined_p ()) + continue; + if (!set_range_info (name, r)) + continue; + change = true; + if (dump_file) + { + fprintf (dump_file, "Global Exported (via unreachable): "); + print_generic_expr (dump_file, name, TDF_SLIM); + fprintf (dump_file, " = "); + gimple_range_global (r, name); + r.dump (dump_file); + fputc ('\n', dump_file); + } + } + return change; +} /* Set of SSA names found live during the RPO traversal of the function for still active basic-blocks. */ @@ -4260,6 +4437,7 @@ class rvrp_folder : public substitute_and_fold_engine public: rvrp_folder (gimple_ranger *r) : substitute_and_fold_engine (), + m_unreachable (*r), m_simplifier (r, r->non_executable_edge_flag) { m_ranger = r; @@ -4312,6 +4490,8 @@ public: void post_fold_bb (basic_block bb) override { m_pta->leave (bb); + if (cfun->after_inlining) + m_unreachable.maybe_register_block (bb); } void pre_fold_stmt (gimple *stmt) override @@ -4328,6 +4508,7 @@ public: return ret; } + remove_unreachable m_unreachable; private: DISABLE_COPY_AND_ASSIGN (rvrp_folder); gimple_ranger *m_ranger; @@ -4339,7 +4520,8 @@ private: from anywhere to perform a VRP pass, including from EVRP. */ unsigned int -execute_ranger_vrp (struct function *fun, bool warn_array_bounds_p) +execute_ranger_vrp (struct function *fun, bool warn_array_bounds_p, + bool final_p) { loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); @@ -4350,6 +4532,8 @@ execute_ranger_vrp (struct function *fun, bool warn_array_bounds_p) gimple_ranger *ranger = enable_ranger (fun, false); rvrp_folder folder (ranger); folder.substitute_and_fold (); + // Remove tagged builtin-unreachable and maybe update globals. + folder.m_unreachable.remove_and_update_globals (final_p); if (dump_file && (dump_flags & TDF_DETAILS)) ranger->dump (dump_file); @@ -4428,11 +4612,11 @@ public: { // Early VRP pass. if (my_pass == 0) - return execute_ranger_vrp (fun, /*warn_array_bounds_p=*/false); + return execute_ranger_vrp (fun, /*warn_array_bounds_p=*/false, false); if ((my_pass == 1 && param_vrp1_mode == VRP_MODE_RANGER) || (my_pass == 2 && param_vrp2_mode == VRP_MODE_RANGER)) - return execute_ranger_vrp (fun, warn_array_bounds_p); + return execute_ranger_vrp (fun, warn_array_bounds_p, my_pass == 2); return execute_vrp (fun, warn_array_bounds_p); } -- cgit v1.1 From e7310e24b1c0ca67b1bb507c1330b2bf39e59e32 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 25 Oct 2022 16:42:41 -0400 Subject: Make ranger vrp1 default. Turn on ranger as the default vrp1 pass and adjust testcases. gcc/ * params.opt (param_vrp1_mode): Make ranger default. gcc/testsuite/ * gcc.dg/pr68217.c: Test [-INF, -INF][0, 0] instead of [-INF, 0]. * gcc.dg/tree-ssa/vrp-unreachable.c: New. Test unreachable removal. --- gcc/params.opt | 2 +- gcc/testsuite/gcc.dg/pr68217.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/vrp-unreachable.c | 42 +++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-unreachable.c (limited to 'gcc') diff --git a/gcc/params.opt b/gcc/params.opt index 3001566..a34fee1 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -1166,7 +1166,7 @@ Common Joined UInteger Var(param_vect_induction_float) Init(1) IntegerRage(0, 1) Enable loop vectorization of floating point inductions. -param=vrp1-mode= -Common Joined Var(param_vrp1_mode) Enum(vrp_mode) Init(VRP_MODE_VRP) Param Optimization +Common Joined Var(param_vrp1_mode) Enum(vrp_mode) Init(VRP_MODE_RANGER) Param Optimization --param=vrp1-mode=[vrp|ranger] Specifies the mode VRP1 should operate in. -param=vrp2-mode= diff --git a/gcc/testsuite/gcc.dg/pr68217.c b/gcc/testsuite/gcc.dg/pr68217.c index eb4f15e..60c8010 100644 --- a/gcc/testsuite/gcc.dg/pr68217.c +++ b/gcc/testsuite/gcc.dg/pr68217.c @@ -10,4 +10,4 @@ int foo (void) return 0; } -/* { dg-final { scan-tree-dump "\\\[-INF, 0\\\]" "vrp1" } } */ +/* { dg-final { scan-tree-dump "\\\[-INF, -INF\\\]\\\[0, 0\\\]" "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-unreachable.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-unreachable.c new file mode 100644 index 0000000..cdc5740 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-unreachable.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1-alias -fdump-tree-vrp2-alias" } */ + +void dead (unsigned n); +void alive (unsigned n); + +void func (unsigned n, unsigned m) +{ + if (n == 0) + __builtin_unreachable(); + if (n == 1) + __builtin_unreachable(); + if (n & 0x1) + __builtin_unreachable(); + if (n == 2) + __builtin_unreachable(); + if (n == 3) + __builtin_unreachable(); + if (n & 0x2) + __builtin_unreachable(); + if (n == 4) + __builtin_unreachable(); + if (n == 5) + __builtin_unreachable(); + if (n & 0x4) + __builtin_unreachable(); + if (n == 6) + __builtin_unreachable(); + if (n == 7) + __builtin_unreachable(); + if (n <8) + dead (n); + if (n != m) + __builtin_unreachable(); + alive (n); + alive (m); +} + +/* { dg-final { scan-tree-dump-not "dead" "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "builtin_unreachable" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-not "builtin_unreachable" "vrp2" } } */ +/* { dg-final { scan-tree-dump-times "fff8" 4 "vrp2" } } */ -- cgit v1.1 From 82b0345f6137b112728590d7c010dcd2cef08514 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 1 Nov 2022 13:18:33 -0400 Subject: Make sure ssa-name is valid. PR tree-optimization/107497 * tree-vrp.cc (remove_unreachable::remove_and_update_globals): Check that ssa-name still exists before accessing it. --- gcc/tree-vrp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index f0e4d37..39f7eb7 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -180,7 +180,7 @@ remove_unreachable::remove_and_update_globals (bool final_p) bitmap_copy (dce, all_exports); // Don't attempt to DCE parameters. EXECUTE_IF_SET_IN_BITMAP (all_exports, 0, i, bi) - if (SSA_NAME_IS_DEFAULT_DEF (ssa_name (i))) + if (!ssa_name (i) || SSA_NAME_IS_DEFAULT_DEF (ssa_name (i))) bitmap_clear_bit (dce, i); simple_dce_from_worklist (dce); -- cgit v1.1 From bdf0018519c39931fdcc7aeffe9e87ba756894d7 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Tue, 1 Nov 2022 17:27:39 +0100 Subject: [PR tree-optimization/107490] Handle NANs in op[12]_range. None of the build_ functions in range-op handle NANs. This is by design in order to force us to handle NANs specially, because "x relop NAN" makes no sense. This patch fixes a handful of op[12]_range entries that weren't handling NANs. PR tree-optimization/107490 gcc/ChangeLog: * range-op-float.cc (foperator_unordered_lt::op1_range): Handle NANs. (foperator_unordered_lt::op2_range): Same. (foperator_unordered_le::op1_range): Same. (foperator_unordered_le::op2_range): Same. (foperator_unordered_gt::op1_range): Same. (foperator_unordered_gt::op2_range): Same. (foperator_unordered_ge::op1_range): Same. (foperator_unordered_ge::op2_range): Same. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr107490.c: New test. --- gcc/range-op-float.cc | 40 +++++++++++++++++++++++++------- gcc/testsuite/gcc.dg/tree-ssa/pr107490.c | 28 ++++++++++++++++++++++ 2 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr107490.c (limited to 'gcc') diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index 04208c8..a1f3729 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -1332,7 +1332,10 @@ foperator_unordered_lt::op1_range (frange &r, tree type, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_lt (r, type, op2); + if (op2.known_isnan ()) + r.set_varying (type); + else + build_lt (r, type, op2); break; case BRS_FALSE: @@ -1359,7 +1362,10 @@ foperator_unordered_lt::op2_range (frange &r, tree type, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_gt (r, type, op1); + if (op1.known_isnan ()) + r.set_varying (type); + else + build_gt (r, type, op1); break; case BRS_FALSE: @@ -1420,7 +1426,10 @@ foperator_unordered_le::op1_range (frange &r, tree type, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_le (r, type, op2); + if (op2.known_isnan ()) + r.set_varying (type); + else + build_le (r, type, op2); break; case BRS_FALSE: @@ -1448,7 +1457,10 @@ foperator_unordered_le::op2_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_ge (r, type, op1); + if (op1.known_isnan ()) + r.set_varying (type); + else + build_ge (r, type, op1); break; case BRS_FALSE: @@ -1511,7 +1523,10 @@ foperator_unordered_gt::op1_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_gt (r, type, op2); + if (op2.known_isnan ()) + r.set_varying (type); + else + build_gt (r, type, op2); break; case BRS_FALSE: @@ -1539,7 +1554,10 @@ foperator_unordered_gt::op2_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_lt (r, type, op1); + if (op1.known_isnan ()) + r.set_varying (type); + else + build_lt (r, type, op1); break; case BRS_FALSE: @@ -1602,7 +1620,10 @@ foperator_unordered_ge::op1_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_ge (r, type, op2); + if (op2.known_isnan ()) + r.set_varying (type); + else + build_ge (r, type, op2); break; case BRS_FALSE: @@ -1629,7 +1650,10 @@ foperator_unordered_ge::op2_range (frange &r, tree type, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_le (r, type, op1); + if (op1.known_isnan ()) + r.set_varying (type); + else + build_le (r, type, op1); break; case BRS_FALSE: diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107490.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107490.c new file mode 100644 index 0000000..87c7f0a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107490.c @@ -0,0 +1,28 @@ +// { dg-do compile } +// { dg-options "-Os -fno-trapping-math -w" } + +extern void abort (void); + +#define MIN2(a,b) (((a)<(b)) ? (a) : (b)) +#define MAX2(a,b) (((a)>(b)) ? (a) : (b)) + +double p[2] = { 4.f, 5.f }; + +int main() +{ + long j; + double R, n, x; + n = 1.e300f; + x = -1.e300f; + for( j=0; j < 2; j++ ) + { + x = MAX2(x,p[j]); + n = MIN2(n,p[j]); + } + R = x-n; + + if( R < 0.1 ) + abort (); + + return 0; +} -- cgit v1.1 From e5c15eb183f17e806ad6b58c9497321ded87866f Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 1 Nov 2022 13:45:08 -0600 Subject: gcc/file-prefix-map: Allow remapping of relative paths Relative paths currently aren't remapped by -ffile-prefix-map and friends. When cross compiling with separate 'source' and 'build' directories, the same relative paths between directories may not be available on target as compared to build time. In order to be able to remap these relative build paths to paths that would work on target, resolve paths within the file-prefix-map function using realpath(). This does cause a change of behaviour if users were previously relying upon symlinks or absolute paths not being resolved. Use basename to ensure plain filenames don't have paths added. gcc/ChangeLog: * file-prefix-map.cc (remap_filename): Allow remapping of relative paths. --- gcc/file-prefix-map.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/file-prefix-map.cc b/gcc/file-prefix-map.cc index 24733f8..439586b 100644 --- a/gcc/file-prefix-map.cc +++ b/gcc/file-prefix-map.cc @@ -70,19 +70,29 @@ remap_filename (file_prefix_map *maps, const char *filename) file_prefix_map *map; char *s; const char *name; + char *realname; size_t name_len; + if (lbasename (filename) == filename) + return filename; + + realname = lrealpath (filename); + for (map = maps; map; map = map->next) - if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0) + if (filename_ncmp (realname, map->old_prefix, map->old_len) == 0) break; if (!map) - return filename; - name = filename + map->old_len; + { + free (realname); + return filename; + } + name = realname + map->old_len; name_len = strlen (name) + 1; s = (char *) ggc_alloc_atomic (name_len + map->new_len); memcpy (s, map->new_prefix, map->new_len); memcpy (s + map->new_len, name, name_len); + free (realname); return s; } -- cgit v1.1 From 4f8aac77e05d0ae0b7f242fd1aa344d36ff52ceb Mon Sep 17 00:00:00 2001 From: David Seifert Date: Tue, 1 Nov 2022 14:27:53 -0600 Subject: configure: cache result of "sys/sdt.h" header check Use AC_CACHE_CHECK to store the result of the header check for systemtap's "sys/sdt.h", which is similar in spirit to libstdc++'s AC_CACHE_CHECK(..., glibcxx_cv_sys_sdt_h). gcc/ * configure.ac: Add AC_CACHE_CHECK(..., gcc_cv_sys_sdt_h). * configure: Regenerate. --- gcc/configure | 20 +++++++++++++++----- gcc/configure.ac | 16 +++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/configure b/gcc/configure index 0ee4be4..e55c656 100755 --- a/gcc/configure +++ b/gcc/configure @@ -31103,15 +31103,25 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking sys/sdt.h in the target C library" >&5 $as_echo_n "checking sys/sdt.h in the target C library... " >&6; } -have_sys_sdt_h=no -if test -f $target_header_dir/sys/sdt.h; then - have_sys_sdt_h=yes +if ${gcc_cv_sys_sdt_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gcc_cv_sys_sdt_h=no + if test -f $target_header_dir/sys/sdt.h; then + gcc_cv_sys_sdt_h=yes + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_sys_sdt_h" >&5 +$as_echo "$gcc_cv_sys_sdt_h" >&6; } +if test x$gcc_cv_sys_sdt_h = xyes; then : + $as_echo "#define HAVE_SYS_SDT_H 1" >>confdefs.h + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_sys_sdt_h" >&5 -$as_echo "$have_sys_sdt_h" >&6; } # Check if TFmode long double should be used by default or not. # Some glibc targets used DFmode long double, but with glibc 2.4 diff --git a/gcc/configure.ac b/gcc/configure.ac index 4ecccff..9ca7779 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -6778,14 +6778,16 @@ AC_SUBST([enable_default_ssp]) # Test for on the target. GCC_TARGET_TEMPLATE([HAVE_SYS_SDT_H]) -AC_MSG_CHECKING(sys/sdt.h in the target C library) -have_sys_sdt_h=no -if test -f $target_header_dir/sys/sdt.h; then - have_sys_sdt_h=yes - AC_DEFINE(HAVE_SYS_SDT_H, 1, +AC_CACHE_CHECK([sys/sdt.h in the target C library], [gcc_cv_sys_sdt_h], [ + gcc_cv_sys_sdt_h=no + if test -f $target_header_dir/sys/sdt.h; then + gcc_cv_sys_sdt_h=yes + fi +]) +AS_IF([test x$gcc_cv_sys_sdt_h = xyes], [ + AC_DEFINE([HAVE_SYS_SDT_H], [1], [Define if your target C library provides sys/sdt.h]) -fi -AC_MSG_RESULT($have_sys_sdt_h) +]) # Check if TFmode long double should be used by default or not. # Some glibc targets used DFmode long double, but with glibc 2.4 -- cgit v1.1 From 2b0e81d5cc2f7e1d773f6c502bd65b097f392675 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 31 Oct 2022 06:11:28 -0400 Subject: c++: per-scope, per-signature lambda discriminators This implements ABI-compliant lambda discriminators. Not only do we have per-scope counters, but we also distinguish by lambda signature. Only lambdas with the same signature will need non-zero discriminators. As the discriminator is signature-dependent, we have to process the lambda function's declaration before we can determine it. For templated and generic lambdas the signature is that of the uninstantiated lambda -- not separate for each instantiation. With this change, gcc and clang now produce the same lambda manglings for all these testcases. gcc/cp/ * cp-tree.h (LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR): New. (struct tree_lambda_expr): Add discriminator_sig bitfield. (recrd_lambda_scope_sig_discriminator): Declare. * lambda.cc (struct lambda_sig_count): New. (lambda_discriminator): Add signature vector. (start_lambda_scope): Adjust. (compare_lambda_template_head, compare_lambda_sig): New. (record_lambda_scope_sig_discriminator): New. * mangle.cc (write_closure_type): Use the scope-sig discriminator for ABI >= 18. Emit abi mangling warning if needed. * module.cc (trees_out::core_vals): Stream the new discriminator. (trees_in::core_vals): Likewise. * parser.cc (cp_parser_lambda_declarator_opt): Call record_lambda_scope_sig_discriminator. * pt.cc (tsubst_lambda_expr): Likewise. libcc1/ * libcp1plugin.cc (plugin_start_lambda_closure_class_type): Initialize the per-scope, per-signature discriminator. gcc/testsuite/ * g++.dg/abi/lambda-sig1-18.C: New. * g++.dg/abi/lambda-sig1-18vs17.C: New. * g++.dg/cpp1y/lambda-mangle-1-18.C: New. --- gcc/cp/cp-tree.h | 7 +- gcc/cp/lambda.cc | 148 +++++++++++++++++++++++- gcc/cp/mangle.cc | 8 +- gcc/cp/module.cc | 2 + gcc/cp/parser.cc | 1 + gcc/cp/pt.cc | 1 + gcc/testsuite/g++.dg/abi/lambda-sig1-18.C | 34 ++++++ gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C | 40 +++++++ gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C | 26 +++++ 9 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1-18.C create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C (limited to 'gcc') diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4c0bacb..d13bb3d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1501,9 +1501,12 @@ enum cp_lambda_default_capture_mode_type { (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope) /* Lambdas in the same extra scope might need a discriminating count. - This is a single per-scope count. */ + For ABI 17, we have single per-scope count, for ABI 18, we have + per-scope, per-signature numbering. */ #define LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR(NODE) \ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_scope) +#define LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR(NODE) \ + (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_sig) /* During parsing of the lambda, a vector of capture proxies which need to be pushed once we're done processing a nested lambda. */ @@ -1533,6 +1536,7 @@ struct GTY (()) tree_lambda_expr location_t locus; enum cp_lambda_default_capture_mode_type default_capture_mode : 2; unsigned discriminator_scope : 15; // Per-scope discriminator + unsigned discriminator_sig : 15; // Per-scope, per-signature discriminator }; /* Non-zero if this template specialization has access violations that @@ -7783,6 +7787,7 @@ extern void start_lambda_scope (tree decl); extern void finish_lambda_scope (void); extern void record_lambda_scope (tree lambda); extern void record_lambda_scope_discriminator (tree lambda); +extern void record_lambda_scope_sig_discriminator (tree lambda, tree fn); extern tree start_lambda_function (tree fn, tree lambda_expr); extern void finish_lambda_function (tree body); extern bool regenerated_lambda_fn_p (tree); diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index d2673e2..c7a9268 100644 --- a/gcc/cp/lambda.cc +++ b/gcc/cp/lambda.cc @@ -1447,13 +1447,21 @@ is_lambda_ignored_entity (tree val) /* Lambdas that appear in variable initializer or default argument scope get that in their mangling, so we need to record it. Also, multiple lambdas in the same scope may need a mangling - discriminator. Record in the same data structure. */ + discriminator. In ABI <= 17, there is a single per-scope sequence + number. In ABI >= 18, there are per-scope per-signature sequence + numbers. */ +struct GTY(()) lambda_sig_count +{ + tree fn; // The lambda fn whose sig this is. + unsigned count; +}; struct GTY(()) lambda_discriminator { tree scope; unsigned nesting; // Inside a function, VAR_DECLs get the function // as scope. This counts that nesting. unsigned count; // The per-scope counter. + vec *discriminators; // Per-signature counters }; // The current scope. static GTY(()) lambda_discriminator lambda_scope; @@ -1475,6 +1483,7 @@ start_lambda_scope (tree decl) lambda_scope.scope = decl; lambda_scope.nesting = 0; lambda_scope.count = 0; + lambda_scope.discriminators = nullptr; } } @@ -1504,6 +1513,116 @@ record_lambda_scope (tree lambda) } } +// Compare lambda template heads TMPL_A and TMPL_B, used for both +// templated lambdas, and template template parameters of said lambda. + +static bool +compare_lambda_template_head (tree tmpl_a, tree tmpl_b) +{ + // We only need one level of template parms + tree inner_a = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl_a)); + tree inner_b = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl_b)); + + // We only compare explicit template parms, ignoring trailing + // synthetic ones. + int len_a = TREE_VEC_LENGTH (inner_a); + int len_b = TREE_VEC_LENGTH (inner_b); + + for (int ix = 0, len = MAX (len_a, len_b); ix != len; ix++) + { + tree parm_a = NULL_TREE; + if (ix < len_a) + { + parm_a = TREE_VEC_ELT (inner_a, ix); + if (parm_a == error_mark_node) + return false; + parm_a = TREE_VALUE (parm_a); + if (DECL_VIRTUAL_P (parm_a)) + parm_a = NULL_TREE; + } + + tree parm_b = NULL_TREE; + if (ix < len_b) + { + parm_b = TREE_VEC_ELT (inner_b, ix); + if (parm_b == error_mark_node) + return false; + parm_b = TREE_VALUE (parm_b); + if (DECL_VIRTUAL_P (parm_b)) + parm_b = NULL_TREE; + } + + if (!parm_a && !parm_b) + // we're done + break; + + if (!(parm_a && parm_b)) + return false; + + if (TREE_CODE (parm_a) != TREE_CODE (parm_b)) + return false; + + if (TREE_CODE (parm_a) == PARM_DECL) + { + if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm_a)) + != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm_b))) + return false; + + if (!same_type_p (TREE_TYPE (parm_a), TREE_TYPE (parm_b))) + return false; + } + else + { + if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm_a)) + != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm_b))) + return false; + + if (TREE_CODE (parm_a) != TEMPLATE_DECL) + gcc_checking_assert (TREE_CODE (parm_a) == TYPE_DECL); + else if (!compare_lambda_template_head (parm_a, parm_b)) + return false; + } + } + + return true; +} + +// Compare lambda signatures FN_A and FN_B, they may be TEMPLATE_DECLs too. + +static bool +compare_lambda_sig (tree fn_a, tree fn_b) +{ + if (TREE_CODE (fn_a) == TEMPLATE_DECL + && TREE_CODE (fn_b) == TEMPLATE_DECL) + { + if (!compare_lambda_template_head (fn_a, fn_b)) + return false; + fn_a = DECL_TEMPLATE_RESULT (fn_a); + fn_b = DECL_TEMPLATE_RESULT (fn_b); + } + else if (TREE_CODE (fn_a) == TEMPLATE_DECL + || TREE_CODE (fn_b) == TEMPLATE_DECL) + return false; + + if (fn_a == error_mark_node + || fn_b == error_mark_node) + return false; + + for (tree args_a = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn_a))), + args_b = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn_b))); + args_a || args_b; + args_a = TREE_CHAIN (args_a), args_b = TREE_CHAIN (args_b)) + { + if (!args_a || !args_b) + return false; + // This check also deals with differing varadicness + if (!same_type_p (TREE_VALUE (args_a), TREE_VALUE (args_b))) + return false; + } + + return true; +} + // Record the per-scope discriminator of LAMBDA. If the extra scope // is empty, we must use the empty scope counter, which might not be // the live one. @@ -1517,6 +1636,33 @@ record_lambda_scope_discriminator (tree lambda) LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda) = slot->count++; } +// Record the per-scope per-signature discriminator of LAMBDA. If the +// extra scope is empty, we must use the empty scope counter, which +// might not be the live one. + +void +record_lambda_scope_sig_discriminator (tree lambda, tree fn) +{ + auto *slot = (vec_safe_is_empty (lambda_scope_stack) + || LAMBDA_EXPR_EXTRA_SCOPE (lambda) + ? &lambda_scope : lambda_scope_stack->begin ()); + gcc_checking_assert (LAMBDA_EXPR_EXTRA_SCOPE (lambda) == slot->scope); + + // A linear search, we're not expecting this to be a big list, and + // this avoids needing a signature hash function. + lambda_sig_count *sig; + if (unsigned ix = vec_safe_length (slot->discriminators)) + for (sig = slot->discriminators->begin (); ix--; sig++) + if (compare_lambda_sig (fn, sig->fn)) + goto found; + { + lambda_sig_count init = {fn, 0}; + sig = vec_safe_push (slot->discriminators, init); + } + found: + LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda) = sig->count++; +} + tree start_lambda_function (tree fco, tree lambda_expr) { diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index a62c975..e97428e 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -1810,7 +1810,13 @@ write_closure_type_name (const tree type) write_method_parms (parms, /*method_p=*/1, fn); write_char ('E'); - write_compact_number (LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda)); + if ((LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda) + != LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda)) + && abi_warn_or_compat_version_crosses (18)) + G.need_abi_warning = true; + write_compact_number (abi_version_at_least (18) + ? LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda) + : LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda)); } /* Convert NUMBER to ascii using base BASE and generating at least diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index df05b52..0e9af31 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -6328,6 +6328,7 @@ trees_out::core_vals (tree t) { WU (((lang_tree_node *)t)->lambda_expression.default_capture_mode); WU (((lang_tree_node *)t)->lambda_expression.discriminator_scope); + WU (((lang_tree_node *)t)->lambda_expression.discriminator_sig); } break; @@ -6820,6 +6821,7 @@ trees_in::core_vals (tree t) RUC (cp_lambda_default_capture_mode_type, ((lang_tree_node *)t)->lambda_expression.default_capture_mode); RU (((lang_tree_node *)t)->lambda_expression.discriminator_scope); + RU (((lang_tree_node *)t)->lambda_expression.discriminator_sig); break; case OVERLOAD: diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index e0e3cf3..fd59de4 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11712,6 +11712,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) fco = finish_fully_implicit_template (parser, fco); finish_member_declaration (fco); + record_lambda_scope_sig_discriminator (lambda_expr, fco); obstack_free (&declarator_obstack, p); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index fc6279c..c3fc56a 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -19912,6 +19912,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) goto out; } finish_member_declaration (inst); + record_lambda_scope_sig_discriminator (r, inst); tree fn = oldtmpl ? DECL_TEMPLATE_RESULT (inst) : inst; diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1-18.C b/gcc/testsuite/g++.dg/abi/lambda-sig1-18.C new file mode 100644 index 0000000..88692ed --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/lambda-sig1-18.C @@ -0,0 +1,34 @@ +// { dg-do compile { target c++20 } } +// { dg-options -fabi-version=18 } + +#include "lambda-sig1.h" + +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE_clEf:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf:} } } + +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlTyfT_E_clIiEEDafS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlTyfT_E0_clIiEEDafS1_:} } } + +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlTyT_E_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlTyT_E0_clIiEEDaS1_:} } } + +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE_clEf:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE1_clEf:} } } + +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyfT_E_clIiEEDafS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyfT_E0_clIiEEDafS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyfT_E1_clIiEEDafS1_:} } } + +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyT_E_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyT_E0_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyT_E1_clIiEEDaS1_:} } } + +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE_clEi:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE0_clEi:} } } + +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlTyiT_E_clIiEEDaiS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlTyiT_E0_clIiEEDaiS1_:} } } + +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlTyT_E_clIiEEDaS1_:} } } +// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlTyT_E0_clIiEEDaS1_:} } } diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C b/gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C new file mode 100644 index 0000000..b191fb3 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C @@ -0,0 +1,40 @@ +// { dg-do compile { target c++20 } } +// { dg-options {-fabi-version=18 -Wabi=17} } + +#include "lambda-sig1.h" + +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfT_E7_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyfT_E1_clIiEEDafS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlT_E5_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyT_E1_clIiEEDaS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE6_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE1_cvPFvfEEv'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENUlfE6_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENUlfE1_4_FUNEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE6_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE1_clEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfT_E4_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyfT_E0_clIiEEDafS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlT_E2_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyT_E0_clIiEEDaS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE3_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE0_cvPFvfEEv'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENUlfE3_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENUlfE0_4_FUNEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE3_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfT_E1_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyfT_E_clIiEEDafS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlT_E_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyT_E_clIiEEDaS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE0_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE_cvPFvfEEv'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENUlfE0_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENUlfE_4_FUNEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE_clEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfT_E4_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlTyfT_E0_clIiEEDafS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlT_E2_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlTyT_E0_clIiEEDaS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfE3_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlfE0_cvPFvfEEv'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENUlfE3_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENUlfE0_4_FUNEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfE3_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfT_E1_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlTyfT_E_clIiEEDafS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlT_E_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlTyT_E_clIiEEDaS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfE0_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlfE_cvPFvfEEv'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENUlfE0_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENUlfE_4_FUNEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlfE_clEf'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliT_E4_clIiEEDaiS1_'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUlTyiT_E0_clIiEEDaiS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUlT_E2_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUlTyT_E0_clIiEEDaS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliE3_cvPFviEEv'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUliE0_cvPFviEEv'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENUliE3_4_FUNEi'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENUliE0_4_FUNEi'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliE3_clEi'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUliE0_clEi'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliT_E1_clIiEEDaiS1_'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUlTyiT_E_clIiEEDaiS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUlT_E_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUlTyT_E_clIiEEDaS1_'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliE0_cvPFviEEv'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUliE_cvPFviEEv'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENUliE0_4_FUNEi'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENUliE_4_FUNEi'\) [^\n]*\n} } +// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliE0_clEi'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUliE_clEi'\) [^\n]*\n} } diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C new file mode 100644 index 0000000..22ad15e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C @@ -0,0 +1,26 @@ +// { dg-do compile { target c++14 } } +// { dg-additional-options -fabi-version=18 } + +// PRs 78621 + +#include "lambda-mangle-1.h" + +// We erroneously mangled lambda auto parms as-if template parameters (T_), +// rather than auto (Da). Fixed in abi version 11 + +// ABI 18 uses per-scope per-signature lambda discriminator + +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E_EOS1_S2_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE_EOS0_S1_:" } } +// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E_EOS0_RS0_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E_EvS2_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE_EvS1_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E_EvRS0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E_EvRT_RT0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E_EvRS1_RS3_:" } } +// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E_Z3FoovEUlS1_S3_E0_EvRS0_RS2_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E_EvRS3_RS5_:" } } +// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E_EvRT_RT0_:" } } -- cgit v1.1 From 74e904bdcac3abdd0453daf3b6195d17e44b4cee Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 2 Nov 2022 00:17:38 +0000 Subject: Daily bump. --- gcc/ChangeLog | 116 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/cp/ChangeLog | 58 ++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 37 +++++++++++++++ 4 files changed, 212 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f7ab7da..fcf39f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,119 @@ +2022-11-01 David Seifert + + * configure.ac: Add AC_CACHE_CHECK(..., gcc_cv_sys_sdt_h). + * configure: Regenerate. + +2022-11-01 Richard Purdie + + * file-prefix-map.cc (remap_filename): Allow remapping of relative paths. + +2022-11-01 Aldy Hernandez + + PR tree-optimization/107490 + * range-op-float.cc (foperator_unordered_lt::op1_range): Handle + NANs. + (foperator_unordered_lt::op2_range): Same. + (foperator_unordered_le::op1_range): Same. + (foperator_unordered_le::op2_range): Same. + (foperator_unordered_gt::op1_range): Same. + (foperator_unordered_gt::op2_range): Same. + (foperator_unordered_ge::op1_range): Same. + (foperator_unordered_ge::op2_range): Same. + +2022-11-01 Andrew MacLeod + + PR tree-optimization/107497 + * tree-vrp.cc (remove_unreachable::remove_and_update_globals): + Check that ssa-name still exists before accessing it. + +2022-11-01 Andrew MacLeod + + * params.opt (param_vrp1_mode): Make ranger default. + +2022-11-01 Andrew MacLeod + + * tree-vrp.cc (class remove_unreachable): New. + (remove_unreachable::maybe_register_block): New. + (remove_unreachable::remove_and_update_globals): New. + (rvrp_folder::rvrp_folder): Initialize m_unreachable. + (rvrp_folder::post_fold_bb): Maybe register unreachable block. + (rvrp_folder::m_unreachable): New member. + (execute_ranger_vrp): Add final_pass flag, remove unreachables. + +2022-11-01 Andrew MacLeod + + * gimple-range-cache.cc (ranger_cache::fill_block_cache): Allow + exit block to be specified. + (ranger_cache::range_from_dom): If exit block is specified, use + the immediate predecessor instead of the dominator to start. + * gimple-range.cc (gimple_ranger::range_on_exit): Allow query + for exit block. + +2022-11-01 Andrew MacLeod + + * value-range.cc (irange::intersect_nonzero_bits): If new + non-zero mask is the same as original, flag no change. + +2022-11-01 Alexander Monakov + + PR target/87832 + * config/i386/znver.md (znver1_idiv): New automaton. + (znver1-idiv): New unit. + (znver1_idiv_DI): Correct unit and cycles in the reservation. + (znver1_idiv_SI): Ditto. + (znver1_idiv_HI): Ditto. + (znver1_idiv_QI): Ditto. + (znver1_idiv_mem_DI): Ditto. + (znver1_idiv_mem_SI): Ditto. + (znver1_idiv_mem_HI): Ditto. + (znver1_idiv_mem_QI): Ditto. + (znver3_idiv_DI): Ditto. + (znver3_idiv_SI): Ditto. + (znver3_idiv_HI): Ditto. + (znver3_idiv_QI): Ditto. + (znver3_idiv_mem_DI): Ditto. + (znver3_idiv_mem_SI): Ditto. + (znver3_idiv_mem_HI): Ditto. + (znver3_idiv_mem_QI): Ditto. + +2022-11-01 liuhongt + + PR target/107057 + * config/i386/sse.md (*vec_interleave_highv2df): Remove + constraint 1. + (*vec_interleave_lowv2df): Ditto. + (vec_concatv2df): Ditto. + (*avx512f_unpcklpd512): Ditto and renamed to .. + (avx512f_unpcklpd512): .. this. + (avx512f_movddup512): Change to define_insn. + (avx_movddup256): Ditto. + (*avx_unpcklpd256): Remove constraint 1 and renamed + to .. + (avx_unpcklpd256): .. this. + * config/i386/i386.cc (ix86_vec_interleave_v2df_operator_ok): + Disallow MEM_P (op1) && MEM_P (op2). + +2022-11-01 liuhongt + + PR target/55583 + * config/i386/i386.md (*x86_64_shld_1): Rename to .. + (x86_64_shld_1): .. this. + (*x86_shld_1): Rename to .. + (x86_shld_1): .. this. + (*x86_64_shrd_1): Rename to .. + (x86_64_shrd_1): .. this. + (*x86_shrd_1): Rename to .. + (x86_shrd_1): .. this. + (*x86_64_shld_shrd_1_nozext): New pre_reload splitter. + (*x86_shld_shrd_1_nozext): Ditto. + (*x86_64_shrd_shld_1_nozext): Ditto. + (*x86_shrd_shld_1_nozext): Ditto. + +2022-11-01 Cui,Lili + + * ipa-inline-analysis.cc (do_estimate_edge_time): Add function attribute + judgement for INLINE_HINT_known_hot hint. + 2022-10-31 Guillermo E. Martinez * btfout.cc (btf_calc_num_vbytes): Compute enumeration size depending of diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3950253..a8fe89b 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20221101 +20221102 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 82629ef..fd5efb1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,61 @@ +2022-11-01 Nathan Sidwell + + * cp-tree.h (LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR): New. + (struct tree_lambda_expr): Add discriminator_sig bitfield. + (recrd_lambda_scope_sig_discriminator): Declare. + * lambda.cc (struct lambda_sig_count): New. + (lambda_discriminator): Add signature vector. + (start_lambda_scope): Adjust. + (compare_lambda_template_head, compare_lambda_sig): New. + (record_lambda_scope_sig_discriminator): New. + * mangle.cc (write_closure_type): Use the scope-sig discriminator for + ABI >= 18. Emit abi mangling warning if needed. + * module.cc (trees_out::core_vals): Stream the new discriminator. + (trees_in::core_vals): Likewise. + * parser.cc (cp_parser_lambda_declarator_opt): Call + record_lambda_scope_sig_discriminator. + * pt.cc (tsubst_lambda_expr): Likewise. + +2022-11-01 Nathan Sidwell + + * cp-tree.h (LAMBDA_EXPR_DISCRIMINATOR): Rename to ... + (LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR): ... here. + (struct tree_lambda_expr): Make default_capture_mode & + discriminator_scope bitfields. + (record_null_lambda_scope) Delete. + (record_lambda_scope_discriminator): Declare. + * lambda.cc (struct lambda_discriminator): New struct. + (lambda_scope, lambda_scope_stack): Adjust types. + (lambda_count): Delete. + (struct tree_int): Delete. + (start_lambda_scope, finish_lambda_scope): Adjust. + (record_lambda_scope): Only record the scope. + (record_lambda_scope_discriminator): New. + * mangle.cc (write_closure_type_name): Adjust. + * module.cc (trees_out::core_vals): Likewise, + (trees_in::core_vals): Likewise. + * parser.cc (cp_parser_lambda_expression): Call + record_lambda_scope_discriminator. + * pt.cc (tsubst_lambda_expr): Adjust record_lambda_scope caling. Call + record_lambda_scope_discriminator. Commonize control flow on tsubsting + the operator function. + +2022-11-01 Jason Merrill + + * parser.cc (make_call_declarator): Add std_attrs parm. + (cp_parser_lambda_declarator_opt): Pass it. + (cp_parser_direct_declarator): Pass it. + +2022-11-01 Jason Merrill + + * decl.cc (finish_function): Set TREE_NOTHROW later in the function. + +2022-11-01 Jason Merrill + + * decl.cc (duplicate_decls): Reformat loop. + * parser.cc (cp_parser_member_declaration): Add newline. + * semantics.cc: Remove newline. + 2022-10-28 Marek Polacek * call.cc (maybe_warn_dangling_reference): Enable the warning in diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9dee429..525604d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,40 @@ +2022-11-01 Nathan Sidwell + + * g++.dg/abi/lambda-sig1-18.C: New. + * g++.dg/abi/lambda-sig1-18vs17.C: New. + * g++.dg/cpp1y/lambda-mangle-1-18.C: New. + +2022-11-01 Aldy Hernandez + + PR tree-optimization/107490 + * gcc.dg/tree-ssa/pr107490.c: New test. + +2022-11-01 Andrew MacLeod + + * gcc.dg/pr68217.c: Test [-INF, -INF][0, 0] instead of [-INF, 0]. + * gcc.dg/tree-ssa/vrp-unreachable.c: New. Test unreachable removal. + +2022-11-01 Nathan Sidwell + + * g++.dg/abi/lambda-sig1-17.C: New. + * g++.dg/abi/lambda-sig1.h: New. + * g++.dg/cpp1y/lambda-mangle-1.C: Extracted to ... + * g++.dg/cpp1y/lambda-mangle-1.h: ... here. + * g++.dg/cpp1y/lambda-mangle-1-11.C: New + * g++.dg/cpp1y/lambda-mangle-1-17.C + +2022-11-01 liuhongt + + * gcc.target/i386/pr107057.c: New test. + +2022-11-01 liuhongt + + * gcc.target/i386/pr55583.c: New test. + +2022-11-01 Cui,Lili + + * gcc.dg/ipa/inlinehint-6.c: New test. + 2022-10-31 Jakub Jelinek * g++.dg/cpp23/ext-floating12.C: New test. -- cgit v1.1 From eaba55ffef961c28f6a15d845a4d6b77b8a8bab1 Mon Sep 17 00:00:00 2001 From: Xionghu Luo Date: Wed, 12 Oct 2022 10:43:38 +0800 Subject: rs6000: Byte reverse V8HI on Power8 by vector rotation. gcc/ PR target/100866 * config/rs6000/altivec.md: (*altivec_vrl): Named to... (altivec_vrl): ...this. * config/rs6000/vsx.md (revb_): Call vspltish and vrlh when target is Power8 and mode is V8HI. gcc/testsuite/ PR target/100866 * gcc.target/powerpc/pr100866-2.c: New. --- gcc/config/rs6000/altivec.md | 2 +- gcc/config/rs6000/vsx.md | 21 +++++++++++++++------ gcc/testsuite/gcc.target/powerpc/pr100866-2.c | 13 +++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/pr100866-2.c (limited to 'gcc') diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 2c4940f..8466007 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -1875,7 +1875,7 @@ } [(set_attr "type" "vecperm")]) -(define_insn "*altivec_vrl" +(define_insn "altivec_vrl" [(set (match_operand:VI2 0 "register_operand" "=v") (rotate:VI2 (match_operand:VI2 1 "register_operand" "v") (match_operand:VI2 2 "register_operand" "v")))] diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index e0e34a7..fb5cf04 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -6087,12 +6087,21 @@ emit_insn (gen_p9_xxbr_ (operands[0], operands[1])); else { - /* Want to have the elements in reverse order relative - to the endian mode in use, i.e. in LE mode, put elements - in BE order. */ - rtx sel = swap_endian_selector_for_mode(mode); - emit_insn (gen_altivec_vperm_ (operands[0], operands[1], - operands[1], sel)); + if (mode == V8HImode) + { + rtx splt = gen_reg_rtx (V8HImode); + emit_insn (gen_altivec_vspltish (splt, GEN_INT (8))); + emit_insn (gen_altivec_vrlh (operands[0], operands[1], splt)); + } + else + { + /* Want to have the elements in reverse order relative + to the endian mode in use, i.e. in LE mode, put elements + in BE order. */ + rtx sel = swap_endian_selector_for_mode (mode); + emit_insn (gen_altivec_vperm_ (operands[0], operands[1], + operands[1], sel)); + } } DONE; diff --git a/gcc/testsuite/gcc.target/powerpc/pr100866-2.c b/gcc/testsuite/gcc.target/powerpc/pr100866-2.c new file mode 100644 index 0000000..4357d1b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr100866-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-O2 -mdejagnu-cpu=power8" } */ +/* { dg-final { scan-assembler {\mvspltish\M} } } */ +/* { dg-final { scan-assembler {\mvrlh\M} } } */ + +#include + +vector unsigned short revb(vector unsigned short a) +{ + return vec_revb(a); +} + -- cgit v1.1 From c3299cde4f33121f82a7a25d10c152ac96d2b035 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Wed, 2 Nov 2022 10:52:59 +0100 Subject: builtins: Guard builtins.cc against HUGE_VAL and NAN definitions trunk bootstrap recently broke on Solaris like this: /vol/gcc/src/hg/master/local/gcc/builtins.cc:2104:8: error: pasting "CFN_BUILT_IN_" and "(" does not give a valid preprocessing token 2104 | case CFN_BUILT_IN_##MATHFN: \ | ^~~~~~~~~~~~~ /vol/gcc/src/hg/master/local/gcc/builtins.cc:2112:3: note: in expansion of macro 'CASE_MATHFN' 2112 | CASE_MATHFN(MATHFN) \ | ^~~~~~~~~~~ /vol/gcc/src/hg/master/local/gcc/builtins.cc:1967:5: note: in expansion of macro 'CASE_MATHFN_FLOATN' 1967 | CASE_MATHFN_FLOATN (HUGE_VAL) \ and similarly for NAN. It turns out this happens because is included at some point, which (in ) defines While this only happpens on Solaris right now, the same issue would be present on other targets when gets included somehow. To avoid this, this patch #undef's both macros. Bootstrapped without regressions on i386-pc-solaris2.11 and sparc-sun-solaris2.11. 2022-11-01 Rainer Orth gcc: * builtins.cc (mathfn_built_in_2): #undef HUGE_VAL, NAN. --- gcc/builtins.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/builtins.cc b/gcc/builtins.cc index b359ce2..4dc1ca6 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -1931,6 +1931,11 @@ mathfn_built_in_2 (tree type, combined_fn fn) built_in_function fcodef64x = END_BUILTINS; built_in_function fcodef128x = END_BUILTINS; + /* If has been included somehow, HUGE_VAL and NAN definitions + break the uses below. */ +#undef HUGE_VAL +#undef NAN + switch (fn) { #define SEQ_OF_CASE_MATHFN \ -- cgit v1.1 From 58511b3fc035f7fe77c3403f7b99de3a795a7964 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Wed, 2 Nov 2022 12:39:45 +0100 Subject: Fix bug in frange::contains_p() for signed zeros. The contains_p() code wasn't returning true for non-singleton ranges containing signed zeros. With this patch we now handle: -0.0 exists in [-3, +5.0] +0.0 exists in [-3, +5.0] gcc/ChangeLog: * value-range.cc (frange::contains_p): Fix signed zero handling. (range_tests_signed_zeros): New test. --- gcc/value-range.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 3743ec7..a855aaf 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -661,7 +661,7 @@ frange::contains_p (tree cst) const { // Make sure the signs are equal for signed zeros. if (HONOR_SIGNED_ZEROS (m_type) && real_iszero (rv)) - return m_min.sign == m_max.sign && m_min.sign == rv->sign; + return rv->sign == m_min.sign || rv->sign == m_max.sign; return true; } return false; @@ -3859,6 +3859,14 @@ range_tests_signed_zeros () ASSERT_TRUE (r0.contains_p (neg_zero)); ASSERT_FALSE (r0.contains_p (zero)); + r0 = frange (neg_zero, zero); + ASSERT_TRUE (r0.contains_p (neg_zero)); + ASSERT_TRUE (r0.contains_p (zero)); + + r0 = frange_float ("-3", "5"); + ASSERT_TRUE (r0.contains_p (neg_zero)); + ASSERT_TRUE (r0.contains_p (zero)); + // The intersection of zeros that differ in sign is a NAN (or // undefined if not honoring NANs). r0 = frange (neg_zero, neg_zero); -- cgit v1.1 From abaa32c7384edef065c79741764bc112dd18f32d Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 2 Nov 2022 10:01:22 -0600 Subject: gcc: honour -ffile-prefix-map in ASM_MAP [PR93371] -ffile-prefix-map is supposed to be a superset of -fmacro-prefix-map and -fdebug-prefix-map. However, when building .S or .s files, gas is not called with the appropriate --debug-prefix-map option when -ffile-prefix-map is used. While the user can specify -fdebug-prefix-map when building assembly files via gcc, it's more ergonomic to also support -ffile-prefix-map; especially since for .S files that could contain the __FILE__ macro, one would then also have to specify -fmacro-prefix-map. gcc: PR driver/93371 * gcc.cc (ASM_MAP): Honour -ffile-prefix-map. --- gcc/gcc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/gcc.cc b/gcc/gcc.cc index afb23cd..98a239c 100644 --- a/gcc/gcc.cc +++ b/gcc/gcc.cc @@ -877,7 +877,7 @@ proper position among the other output files. */ #endif #ifdef HAVE_AS_DEBUG_PREFIX_MAP -#define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}" +#define ASM_MAP " %{ffile-prefix-map=*:--debug-prefix-map %*} %{fdebug-prefix-map=*:--debug-prefix-map %*}" #else #define ASM_MAP "" #endif -- cgit v1.1 From a1a6b912b5f905e768da4d0f434591b4d523be49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20M=C3=BCllner?= Date: Thu, 27 Oct 2022 20:42:30 +0200 Subject: RISC-V: Add Zawrs ISA extension support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for the Zawrs ISA extension. Zawrs has been ratified by the RISC-V BoD on Oct 20th, 2022. Binutils support has been merged as: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=eb668e50036e979fb0a74821df4eee0307b44e66 gcc/ChangeLog: * common/config/riscv/riscv-common.cc: Add zawrs extension. * config/riscv/riscv-opts.h (MASK_ZAWRS): New. (TARGET_ZAWRS): New. * config/riscv/riscv.opt: New. gcc/testsuite/ChangeLog: * gcc.target/riscv/zawrs.c: New test. Signed-off-by: Christoph Müllner --- gcc/common/config/riscv/riscv-common.cc | 4 ++++ gcc/config/riscv/riscv-opts.h | 3 +++ gcc/config/riscv/riscv.opt | 3 +++ gcc/testsuite/gcc.target/riscv/zawrs.c | 13 +++++++++++++ 4 files changed, 23 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/zawrs.c (limited to 'gcc') diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index d6404a0..4b7f777 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -163,6 +163,8 @@ static const struct riscv_ext_version riscv_ext_version_table[] = {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0}, {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0}, + {"zawrs", ISA_SPEC_CLASS_NONE, 1, 0}, + {"zba", ISA_SPEC_CLASS_NONE, 1, 0}, {"zbb", ISA_SPEC_CLASS_NONE, 1, 0}, {"zbc", ISA_SPEC_CLASS_NONE, 1, 0}, @@ -1180,6 +1182,8 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] = {"zicsr", &gcc_options::x_riscv_zi_subext, MASK_ZICSR}, {"zifencei", &gcc_options::x_riscv_zi_subext, MASK_ZIFENCEI}, + {"zawrs", &gcc_options::x_riscv_za_subext, MASK_ZAWRS}, + {"zba", &gcc_options::x_riscv_zb_subext, MASK_ZBA}, {"zbb", &gcc_options::x_riscv_zb_subext, MASK_ZBB}, {"zbc", &gcc_options::x_riscv_zb_subext, MASK_ZBC}, diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index 1dfe8c8..25fd85b 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -73,6 +73,9 @@ enum stack_protector_guard { #define TARGET_ZICSR ((riscv_zi_subext & MASK_ZICSR) != 0) #define TARGET_ZIFENCEI ((riscv_zi_subext & MASK_ZIFENCEI) != 0) +#define MASK_ZAWRS (1 << 0) +#define TARGET_ZAWRS ((riscv_za_subext & MASK_ZAWRS) != 0) + #define MASK_ZBA (1 << 0) #define MASK_ZBB (1 << 1) #define MASK_ZBC (1 << 2) diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index 426ea95..7c3ca48 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -204,6 +204,9 @@ TargetVariable int riscv_zi_subext TargetVariable +int riscv_za_subext + +TargetVariable int riscv_zb_subext TargetVariable diff --git a/gcc/testsuite/gcc.target/riscv/zawrs.c b/gcc/testsuite/gcc.target/riscv/zawrs.c new file mode 100644 index 0000000..0b7e266 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zawrs.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zawrs" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zawrs" { target { rv32 } } } */ + +#ifndef __riscv_zawrs +#error Feature macro not defined +#endif + +int +foo (int a) +{ + return a; +} -- cgit v1.1 From 58035eeece7894d1936db6bf0dd4f8eedd07a479 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 3 Nov 2022 00:17:32 +0000 Subject: Daily bump. --- gcc/ChangeLog | 29 +++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/testsuite/ChangeLog | 9 +++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fcf39f0..ecbd2f8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2022-11-02 Christoph Müllner + + * common/config/riscv/riscv-common.cc: Add zawrs extension. + * config/riscv/riscv-opts.h (MASK_ZAWRS): New. + (TARGET_ZAWRS): New. + * config/riscv/riscv.opt: New. + +2022-11-02 Rasmus Villemoes + + PR driver/93371 + * gcc.cc (ASM_MAP): Honour -ffile-prefix-map. + +2022-11-02 Aldy Hernandez + + * value-range.cc (frange::contains_p): Fix signed zero handling. + (range_tests_signed_zeros): New test. + +2022-11-02 Rainer Orth + + * builtins.cc (mathfn_built_in_2): #undef HUGE_VAL, NAN. + +2022-11-02 Xionghu Luo + + PR target/100866 + * config/rs6000/altivec.md: (*altivec_vrl): Named to... + (altivec_vrl): ...this. + * config/rs6000/vsx.md (revb_): Call vspltish and vrlh when + target is Power8 and mode is V8HI. + 2022-11-01 David Seifert * configure.ac: Add AC_CACHE_CHECK(..., gcc_cv_sys_sdt_h). diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index a8fe89b..99ca023 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20221102 +20221103 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 525604d..b397adf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2022-11-02 Christoph Müllner + + * gcc.target/riscv/zawrs.c: New test. + +2022-11-02 Xionghu Luo + + PR target/100866 + * gcc.target/powerpc/pr100866-2.c: New. + 2022-11-01 Nathan Sidwell * g++.dg/abi/lambda-sig1-18.C: New. -- cgit v1.1 From e3c898e12d0ace542498c9fe975e549b5a6c8acd Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 3 Nov 2022 02:53:41 +0000 Subject: c: C2x auto Implement C2x auto, a more restricted version of the C++ feature (closer to GNU C __auto_type in terms of what's supported). Since the feature is very close to GNU C __auto_type, much of the implementation can be shared. The main differences are: * Any prior declaration of the identifier in an outer scope is shadowed during the initializer (whereas __auto_type leaves any such declaration visible until the initializer ends and the scope of the __auto_type declaration itself starts). (A prior declaration in the same scope is undefined behavior.) * The standard feature supports braced initializers (containing a single expression, optionally followed by a comma). * The standard feature disallows the declaration from declaring anything that's not an ordinary identifier (thus, the initializer cannot declare a tag or the members of a structure or union), while making it undefined behavior for it to declare more than one ordinary identifier. (For the latter, while I keep the existing error from __auto_type in the case of more than one declarator, I don't restrict other ordinary identifiers from being declared in inner scopes such as GNU statement expressions. I do however disallow defining the members of an enumeration inside the initializer (if the enum definition has no tag, that doesn't actually violate a constraint), to avoid an enum type becoming accessible beyond where it would have been without auto. (Preventing new types from escaping the initializer - thus, ensuring that anything written with auto corresponds to something that could have been written without auto, modulo multiple evaluation of VLA size expressions when not using auto - is a key motivation for some restrictions on what can be declared in the initializer.) The rule on shadowing and restrictions on other declarations in the initializer are actually general rules for what C2x calls underspecified declarations, a description that covers constexpr as well as auto (in particular, this disallows a constexpr initializer from referencing the variable being initialized). Thus, some of the code added for those restrictions will also be of use in implementing C2x constexpr. auto with a type specifier remains a storage class specifier with the same meaning as before (i.e. a redundant storage class specifier for use at block scope). Note that the feature is only enabled in C2x mode (-std=c2x or -std=gnu2x); in older modes, a declaration with auto and no type is treated as a case of implicit int (only accepted at block scope). Since many of the restrictions on C2x auto are specified as undefined behavior rather than constraint violations, it would be possible to support more features from C++ auto without requiring diagnostics (but maybe not a good idea, if it isn't clear exactly what semantics might be given to such a feature in a future revision of C; and -Wc23-c2y-compat should arguably warn for any such future feature anyway). For now the features are limited to something close to what's supported with __auto_type, with the differences as discussed above between the two features. Bootstrapped with no regressions for x86_64-pc-linux-gnu. gcc/c/ * c-decl.cc (in_underspecified_init, start_underspecified_init) (finish_underspecified_init): New. (shadow_tag_warned, parser_xref_tag, start_struct, start_enum): Give errors inside initializers of underspecified declarations. (grokdeclarator): Handle (erroneous) case of C2X auto on a parameter. (declspecs_add_type): Handle c2x_auto_p case. (declspecs_add_scspec): Handle auto possibly setting c2x_auto_p in C2X mode. (finish_declspecs): Handle c2x_auto_p. * c-parser.cc (c_parser_declaration_or_fndef): Handle C2X auto. * c-tree.h (C_DECL_UNDERSPECIFIED): New macro. (struct c_declspecs): Add c2x_auto_p. (start_underspecified_init, finish_underspecified_init): New prototypes. * c-typeck.cc (build_external_ref): Give error for underspecified declaration referenced in its initializer. gcc/testsuite/ * gcc.dg/c2x-auto-1.c, gcc.dg/c2x-auto-2.c, gcc.dg/c2x-auto-3.c, gcc.dg/c2x-auto-4.c, gcc.dg/gnu2x-auto-1.c: New tests. --- gcc/c/c-decl.cc | 143 +++++++++++++++++++++++++++++++++++- gcc/c/c-parser.cc | 81 ++++++++++++++++---- gcc/c/c-tree.h | 11 +++ gcc/c/c-typeck.cc | 3 + gcc/testsuite/gcc.dg/c2x-auto-1.c | 81 ++++++++++++++++++++ gcc/testsuite/gcc.dg/c2x-auto-2.c | 38 ++++++++++ gcc/testsuite/gcc.dg/c2x-auto-3.c | 64 ++++++++++++++++ gcc/testsuite/gcc.dg/c2x-auto-4.c | 5 ++ gcc/testsuite/gcc.dg/gnu2x-auto-1.c | 11 +++ 9 files changed, 418 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/c2x-auto-1.c create mode 100644 gcc/testsuite/gcc.dg/c2x-auto-2.c create mode 100644 gcc/testsuite/gcc.dg/c2x-auto-3.c create mode 100644 gcc/testsuite/gcc.dg/c2x-auto-4.c create mode 100644 gcc/testsuite/gcc.dg/gnu2x-auto-1.c (limited to 'gcc') diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 795c971..a99b745 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -1472,6 +1472,67 @@ pop_file_scope (void) maybe_apply_pending_pragma_weaks (); } +/* Whether we are curently inside the initializer for an + underspecified object definition (C2x auto or constexpr). */ +static bool in_underspecified_init; + +/* Start an underspecified object definition for NAME at LOC. This + means that NAME is shadowed inside its initializer, so neither the + definition being initialized, nor any definition from an outer + scope, may be referenced during that initializer. Return state to + be passed to finish_underspecified_init. */ +unsigned int +start_underspecified_init (location_t loc, tree name) +{ + bool prev = in_underspecified_init; + bool ok; + tree decl = build_decl (loc, VAR_DECL, name, error_mark_node); + C_DECL_UNDERSPECIFIED (decl) = 1; + struct c_scope *scope = current_scope; + struct c_binding *b = I_SYMBOL_BINDING (name); + if (b && B_IN_SCOPE (b, scope)) + { + error_at (loc, "underspecified declaration of %qE, which is already " + "declared in this scope", name); + ok = false; + } + else + { + bind (name, decl, scope, false, false, loc); + ok = true; + } + in_underspecified_init = true; + return ok | (prev << 1); +} + +/* Finish an underspecified object definition for NAME, before that + name is bound to the real declaration instead of a placeholder. + PREV_STATE is the value returned by the call to + start_underspecified_init. */ +void +finish_underspecified_init (tree name, unsigned int prev_state) +{ + if (prev_state & 1) + { + /* A VAR_DECL was bound to the name to shadow any previous + declarations for the name; remove that binding now. */ + struct c_scope *scope = current_scope; + struct c_binding *b = I_SYMBOL_BINDING (name); + gcc_assert (b); + gcc_assert (B_IN_SCOPE (b, scope)); + gcc_assert (VAR_P (b->decl)); + gcc_assert (C_DECL_UNDERSPECIFIED (b->decl)); + I_SYMBOL_BINDING (name) = b->shadowed; + /* In erroneous cases there may be other bindings added to this + scope during the initializer. */ + struct c_binding **p = &scope->bindings; + while (*p != b) + p = &((*p)->prev); + *p = free_binding_and_advance (*p); + } + in_underspecified_init = (prev_state & (1u << 1)) >> 1; +} + /* Adjust the bindings for the start of a statement expression. */ void @@ -4764,6 +4825,17 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) warned = 1; } + if (in_underspecified_init) + { + /* This can only occur with extensions such as statement + expressions, but is still appropriate as an error to + avoid types declared in such a context escaping to + the type of an auto variable. */ + error ("%qT declared in underspecified object initializer", + value); + warned = 1; + } + if (name == NULL_TREE) { if (warned != 1 && code != ENUMERAL_TYPE) @@ -6458,6 +6530,15 @@ grokdeclarator (const struct c_declarator *declarator, enum c_declarator_kind first_non_attr_kind; unsigned int alignas_align = 0; + if (type == NULL_TREE) + { + /* This can occur for auto on a parameter in C2X mode. Set a + dummy type here so subsequent code can give diagnostics for + this case. */ + gcc_assert (declspecs->c2x_auto_p); + gcc_assert (decl_context == PARM); + type = declspecs->type = integer_type_node; + } if (TREE_CODE (type) == ERROR_MARK) return error_mark_node; if (expr == NULL) @@ -6683,9 +6764,13 @@ grokdeclarator (const struct c_declarator *declarator, || storage_class == csc_typedef) storage_class = csc_none; } - else if (decl_context != NORMAL && (storage_class != csc_none || threadp)) + else if (decl_context != NORMAL && (storage_class != csc_none + || threadp + || declspecs->c2x_auto_p)) { - if (decl_context == PARM && storage_class == csc_register) + if (decl_context == PARM + && storage_class == csc_register + && !declspecs->c2x_auto_p) ; else { @@ -8428,6 +8513,9 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name, pushtag (loc, name, ref); decl_attributes (&ref, attrs, (int) ATTR_FLAG_TYPE_IN_PLACE); + if (in_underspecified_init) + error_at (loc, "%qT declared in underspecified object initializer", + ref); ret.spec = ref; return ret; @@ -8523,6 +8611,9 @@ start_struct (location_t loc, enum tree_code code, tree name, ? "sizeof" : (in_typeof ? "typeof" : "alignof"))); + if (in_underspecified_init) + error_at (loc, "%qT defined in underspecified object initializer", ref); + return ref; } @@ -9433,6 +9524,10 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name, ? "sizeof" : (in_typeof ? "typeof" : "alignof"))); + if (in_underspecified_init) + error_at (loc, "%qT defined in underspecified object initializer", + enumtype); + return enumtype; } @@ -11261,6 +11356,20 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, if (TREE_UNAVAILABLE (type)) specs->unavailable_p = true; + /* As a type specifier is present, "auto" must be used as a storage + class specifier, not for type deduction. */ + if (specs->c2x_auto_p) + { + specs->c2x_auto_p = false; + if (specs->storage_class != csc_none) + error ("multiple storage classes in declaration specifiers"); + else if (specs->thread_p) + error ("%qs used with %", + specs->thread_gnu_p ? "__thread" : "_Thread_local"); + else + specs->storage_class = csc_auto; + } + /* Handle type specifier keywords. */ if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type) @@ -12179,6 +12288,16 @@ declspecs_add_scspec (location_t loc, } break; case RID_AUTO: + if (flag_isoc2x + && specs->typespec_kind == ctsk_none + && specs->storage_class != csc_typedef) + { + /* "auto" potentially used for type deduction. */ + if (specs->c2x_auto_p) + error ("duplicate %qE", scspec); + specs->c2x_auto_p = true; + return specs; + } n = csc_auto; break; case RID_EXTERN: @@ -12198,6 +12317,11 @@ declspecs_add_scspec (location_t loc, break; case RID_TYPEDEF: n = csc_typedef; + if (specs->c2x_auto_p) + { + error ("% used with %"); + specs->c2x_auto_p = false; + } break; default: gcc_unreachable (); @@ -12284,7 +12408,7 @@ finish_declspecs (struct c_declspecs *specs) { gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p && !specs->signed_p && !specs->unsigned_p - && !specs->complex_p); + && !specs->complex_p && !specs->c2x_auto_p); /* Set a dummy type. */ if (TREE_CODE (specs->type) == ERROR_MARK) @@ -12320,6 +12444,18 @@ finish_declspecs (struct c_declspecs *specs) "ISO C does not support plain % meaning " "%"); } + else if (specs->c2x_auto_p) + { + /* Type to be filled in later, including applying postfix + attributes. This warning only actually appears for + -Wc11-c2x-compat in C2X mode; in older modes, there may + be a warning or pedwarn for implicit "int" instead, or + other errors for use of auto at file scope. */ + pedwarn_c11 (input_location, OPT_Wpedantic, + "ISO C does not support % type deduction " + "before C2X"); + return specs; + } else { specs->typespec_word = cts_int; @@ -12336,6 +12472,7 @@ finish_declspecs (struct c_declspecs *specs) specs->explicit_signed_p = specs->signed_p; /* Now compute the actual type. */ + gcc_assert (!specs->c2x_auto_p); switch (specs->typespec_word) { case cts_auto_type: diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index ca533c9..d70697b 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -2103,7 +2103,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, } finish_declspecs (specs); - bool auto_type_p = specs->typespec_word == cts_auto_type; + bool gnu_auto_type_p = specs->typespec_word == cts_auto_type; + bool std_auto_type_p = specs->c2x_auto_p; + bool any_auto_type_p = gnu_auto_type_p || std_auto_type_p; + gcc_assert (!(gnu_auto_type_p && std_auto_type_p)); + const char *auto_type_keyword = gnu_auto_type_p ? "__auto_type" : "auto"; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { bool handled_assume = false; @@ -2114,8 +2118,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, specs->attrs = handle_assume_attribute (here, specs->attrs, nested); } - if (auto_type_p) - error_at (here, "%<__auto_type%> in empty declaration"); + if (any_auto_type_p) + error_at (here, "%qs in empty declaration", auto_type_keyword); else if (specs->typespec_kind == ctsk_none && attribute_fallthrough_p (specs->attrs)) { @@ -2159,7 +2163,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, shadow_tag_warned (specs, 1); return; } - else if (c_dialect_objc () && !auto_type_p) + else if (c_dialect_objc () && !any_auto_type_p) { /* Prefix attributes are an error on method decls. */ switch (c_parser_peek_token (parser)->type) @@ -2253,6 +2257,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool dummy = false; timevar_id_t tv; tree fnbody = NULL_TREE; + tree std_auto_name = NULL_TREE; /* Declaring either one or more declarators (in which case we should diagnose if there were no declaration specifiers) or a function definition (in which case the diagnostic for @@ -2270,7 +2275,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, c_parser_skip_to_end_of_block_or_statement (parser); return; } - if (auto_type_p && declarator->kind != cdk_id) + if (gnu_auto_type_p && declarator->kind != cdk_id) { error_at (here, "%<__auto_type%> requires a plain identifier" @@ -2278,6 +2283,21 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, c_parser_skip_to_end_of_block_or_statement (parser); return; } + if (std_auto_type_p) + { + struct c_declarator *d = declarator; + while (d->kind == cdk_attrs) + d = d->declarator; + if (d->kind != cdk_id) + { + error_at (here, + "% requires a plain identifier, possibly with" + " attributes, as declarator"); + c_parser_skip_to_end_of_block_or_statement (parser); + return; + } + std_auto_name = d->u.id.id; + } if (c_parser_next_token_is (parser, CPP_EQ) || c_parser_next_token_is (parser, CPP_COMMA) || c_parser_next_token_is (parser, CPP_SEMICOLON) @@ -2317,19 +2337,37 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, struct c_expr init; location_t init_loc; c_parser_consume_token (parser); - if (auto_type_p) + if (any_auto_type_p) { init_loc = c_parser_peek_token (parser)->location; rich_location richloc (line_table, init_loc); + unsigned int underspec_state = 0; + if (std_auto_type_p) + underspec_state = start_underspecified_init (init_loc, + std_auto_name); start_init (NULL_TREE, asm_name, global_bindings_p (), &richloc); /* A parameter is initialized, which is invalid. Don't attempt to instrument the initializer. */ int flag_sanitize_save = flag_sanitize; if (nested && !empty_ok) flag_sanitize = 0; - init = c_parser_expr_no_commas (parser, NULL); + if (std_auto_type_p + && c_parser_next_token_is (parser, CPP_OPEN_BRACE)) + { + matching_braces braces; + braces.consume_open (parser); + init = c_parser_expr_no_commas (parser, NULL); + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + braces.skip_until_found_close (parser); + } + else + init = c_parser_expr_no_commas (parser, NULL); + if (std_auto_type_p) + finish_underspecified_init (std_auto_name, underspec_state); flag_sanitize = flag_sanitize_save; - if (TREE_CODE (init.value) == COMPONENT_REF + if (gnu_auto_type_p + && TREE_CODE (init.value) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1))) error_at (here, "%<__auto_type%> used with a bit-field" @@ -2345,6 +2383,16 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, specs->locations[cdw_typedef] = init_loc; specs->typedef_p = true; specs->type = init_type; + if (specs->postfix_attrs) + { + /* Postfix [[]] attributes are valid with C2X + auto, although not with __auto_type, and + modify the type given by the initializer. */ + specs->postfix_attrs = + c_warn_type_attributes (specs->postfix_attrs); + decl_attributes (&specs->type, specs->postfix_attrs, 0); + specs->postfix_attrs = NULL_TREE; + } if (vm_type) { bool maybe_const = true; @@ -2400,11 +2448,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, } else { - if (auto_type_p) + if (any_auto_type_p) { error_at (here, - "%<__auto_type%> requires an initialized " - "data declaration"); + "%qs requires an initialized data declaration", + auto_type_keyword); c_parser_skip_to_end_of_block_or_statement (parser); return; } @@ -2492,11 +2540,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, } if (c_parser_next_token_is (parser, CPP_COMMA)) { - if (auto_type_p) + if (any_auto_type_p) { error_at (here, - "%<__auto_type%> may only be used with" - " a single declarator"); + "%qs may only be used with a single declarator", + auto_type_keyword); c_parser_skip_to_end_of_block_or_statement (parser); return; } @@ -2529,10 +2577,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, return; } } - else if (auto_type_p) + else if (any_auto_type_p) { error_at (here, - "%<__auto_type%> requires an initialized data declaration"); + "%qs requires an initialized data declaration", + auto_type_keyword); c_parser_skip_to_end_of_block_or_statement (parser); return; } diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index facfc12..8116e5c 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -100,6 +100,10 @@ along with GCC; see the file COPYING3. If not see #define C_DECL_COMPOUND_LITERAL_P(DECL) \ DECL_LANG_FLAG_5 (VAR_DECL_CHECK (DECL)) +/* Set on decls used as placeholders for a C2x underspecified object + definition. */ +#define C_DECL_UNDERSPECIFIED(DECL) DECL_LANG_FLAG_7 (DECL) + /* Nonzero for a decl which either doesn't exist or isn't a prototype. N.B. Could be simplified if all built-in decls had complete prototypes (but this is presently difficult because some of them need FILE*). */ @@ -430,6 +434,11 @@ struct c_declspecs { enum-type-specifier;", but such an empty declaration is valid in C2x when "enum identifier;" would not be). */ BOOL_BITFIELD enum_type_specifier_ref_p : 1; + /* Whether "auto" was specified in C2X (or later) mode and means the + type is to be deduced from an initializer, or would mean that if + no type specifier appears later in these declaration + specifiers. */ + BOOL_BITFIELD c2x_auto_p : 1; /* The address space that the declaration belongs to. */ addr_space_t address_space; }; @@ -592,6 +601,8 @@ extern bool switch_statement_break_seen_p; extern bool global_bindings_p (void); extern tree pushdecl (tree); +extern unsigned int start_underspecified_init (location_t, tree); +extern void finish_underspecified_init (tree, unsigned int); extern void push_scope (void); extern tree pop_scope (void); extern void c_bindings_start_stmt_expr (struct c_spot_bindings *); diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 052ae6d..6360984 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -2861,6 +2861,9 @@ build_external_ref (location_t loc, tree id, bool fun, tree *type) { ref = decl; *type = TREE_TYPE (ref); + if (DECL_P (decl) && C_DECL_UNDERSPECIFIED (decl)) + error_at (loc, "underspecified %qD referenced in its initializer", + decl); } else if (fun) /* Implicit function declaration. */ diff --git a/gcc/testsuite/gcc.dg/c2x-auto-1.c b/gcc/testsuite/gcc.dg/c2x-auto-1.c new file mode 100644 index 0000000..f8460fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-auto-1.c @@ -0,0 +1,81 @@ +/* Test C2x auto. Valid code, compilation tests. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +auto i = 1; +extern int i; +static auto l = { 0L }; +extern long l; +extern auto const d = 0.0; /* { dg-warning "initialized and declared 'extern'" } */ +extern const double d; +double dx; +auto ((i2)) = 3; +extern int i2; +const auto i3 [[]] = { 4, }; +extern int i4; +thread_local auto f = 1.0f; +float ff; +extern typeof (f) ff; +auto h = (short) 0; +extern short h; + +struct s { int a; }; +struct s sv; +struct s2; +enum e : int; + +extern const volatile long double cvld; +extern void (*tfp) (void); + +int a[10]; +int *ap; + +typedef int ti; + +void +tf () +{ + auto asv = (struct s) { 0 }; + extern typeof (asv) sv; + auto s2p = (struct s2 *) 0; + struct s3; + auto s3p = (struct s3 *) 0; + auto ev = (enum e) 0; + static const auto volatile acvld = 0.5L; + extern typeof (acvld) cvld; + /* lvalue conversion occurs on the initializer, so losing qualifiers. */ + auto ncd = d; + extern typeof (ncd) dx; + _Atomic double ad = 0.0; + auto nad = ad; + extern typeof (nad) dx; + /* Function-to-pointer conversion occurs on the initializer. */ + auto fp = tf; + extern typeof (fp) tfp; + /* Array-to-pointer conversion occurs on the initializer. */ + auto aap = a; + extern typeof (aap) ap; + /* Shadowing a declaration from a containing scope is OK. */ + auto i = 2L; + extern typeof (i) l; + /* auto can be used in for loops. */ + for (auto ix = 2; ix < 10; ix++) + { + extern typeof (ix) i2; + } + /* auto is valid with bit-field initializers; the choice of type those have + in expressions is unspecified but should match how _Generic handles such + expressions. */ + struct b { int a : 2; unsigned b : 3; } bv = { }; + auto bfa = bv.a; + auto bfb = bv.b; + static_assert (_Generic (bv.a, typeof (bfa) : 1, default : 2) == 1); + static_assert (_Generic (bv.b, typeof (bfb) : 1, default : 2) == 1); + /* The traditional meaning of auto with a type specifier is OK. */ + auto short s; + char auto c; + auto struct t { int x; } t; + /* That includes the case where the type comes from a typedef name. */ + auto ti int_from_typedef = 3.0; + extern typeof (int_from_typedef) i2; +} diff --git a/gcc/testsuite/gcc.dg/c2x-auto-2.c b/gcc/testsuite/gcc.dg/c2x-auto-2.c new file mode 100644 index 0000000..a41f813 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-auto-2.c @@ -0,0 +1,38 @@ +/* Test C2x auto. Valid code, execution tests. Based on auto-type-1.c. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ +/* { dg-require-effective-target alloca } */ + +extern void abort (void); +extern void exit (int); + +auto i = 1; +extern int i; +auto c = (char) 1; +extern char c; +static auto u = 10U; +extern unsigned int u; +const auto ll = 1LL; +extern const long long ll; + +int +main (void) +{ + if (i != 1 || c != 1 || u != 10U) + abort (); + auto ai = i; + int *aip = &ai; + if (ai != 1) + abort (); + auto p = (int (*) [++i]) 0; + if (i != 2) + abort (); + if (sizeof (*p) != 2 * sizeof (int)) + abort (); + int vla[u][u]; + int (*vp)[u] = &vla[0]; + auto vpp = ++vp; + if (vp != &vla[1]) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-auto-3.c b/gcc/testsuite/gcc.dg/c2x-auto-3.c new file mode 100644 index 0000000..a34ce31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-auto-3.c @@ -0,0 +1,64 @@ +/* Test C2x auto. Invalid code. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +auto; /* { dg-error "empty declaration" } */ +auto *p = (int *) 0; /* { dg-error "plain identifier" } */ +auto i; /* { dg-error "initialized data declaration" } */ +auto g { } /* { dg-error "initialized data declaration" } */ +auto a = 1, b = 2; /* { dg-error "single declarator" } */ +auto long e0 = 0; /* { dg-error "file-scope declaration" } */ +long auto e1 = 0; /* { dg-error "file-scope declaration" } */ +int auto e2 = 0; /* { dg-error "file-scope declaration" } */ + +extern int e3; +auto e3 = 1; /* { dg-error "underspecified declaration of 'e3', which is already declared in this scope" } */ + +void +f () +{ + extern int fe1; + auto fe1 = 1; /* { dg-error "underspecified declaration of 'fe1', which is already declared in this scope" } */ + /* { dg-error "declaration of 'fe1' with no linkage follows extern declaration" "linkage error" { target *-*-* } .-1 } */ + auto fe2 = (struct s *) 0; /* { dg-error "declared in underspecified object initializer" } */ + auto fe3 = (union u *) 0; /* { dg-error "declared in underspecified object initializer" } */ + auto fe4 = (struct s2 { int a; }) { }; /* { dg-error "defined in underspecified object initializer" } */ + auto fe5 = (struct { int a; }) { }; /* { dg-error "defined in underspecified object initializer" } */ + auto fe6 = (union u2 { int a; }) { }; /* { dg-error "defined in underspecified object initializer" } */ + auto fe7 = (union { int a; }) { }; /* { dg-error "defined in underspecified object initializer" } */ + auto fe8 = sizeof (enum e { A }); /* { dg-error "defined in underspecified object initializer" } */ + /* The following case is undefined behavior (so doesn't actually require a + diagnostic). */ + auto fe9 = sizeof (enum { B }); /* { dg-error "defined in underspecified object initializer" } */ + /* Examples with a forward declaration, then definition inside auto. */ + struct s3; + auto fe10 = (struct s3 { int a; }) { }; /* { dg-error "defined in underspecified object initializer" } */ + union u3; + auto fe11 = (union u3 { int a; }) { }; /* { dg-error "defined in underspecified object initializer" } */ +} + +void f2 (auto x); /* { dg-error "storage class specified for parameter" } */ +void f3 (auto y) { } /* { dg-error "storage class specified for parameter" } */ + +auto e4 = sizeof (e4); /* { dg-error "underspecified 'e4' referenced in its initializer" } */ +__SIZE_TYPE__ e5; +void +f4 () +{ + auto e5 = sizeof (e5); /* { dg-error "underspecified 'e5' referenced in its initializer" } */ +} + +auto typedef int T; /* { dg-error "'typedef' used with 'auto'" } */ +auto auto e6 = 1; /* { dg-error "duplicate 'auto'" } */ +static auto int e7 = 1; /* { dg-error "multiple storage classes in declaration specifiers" } */ +_Thread_local auto int e8 = 2; /* { dg-error "'_Thread_local' used with 'auto'" } */ +_Thread_local int auto e9 = 3; /* { dg-error "'_Thread_local' used with 'auto'" } */ +/* { dg-error "file-scope declaration of 'e9' specifies 'auto'" "file-scope error" { target *-*-* } .-1 } */ + +typedef auto int T2; /* { dg-error "multiple storage classes in declaration specifiers" } */ + +void +f5 () +{ + static int auto e10 = 3; /* { dg-error "multiple storage classes in declaration specifiers" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-auto-4.c b/gcc/testsuite/gcc.dg/c2x-auto-4.c new file mode 100644 index 0000000..3c6cb34 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-auto-4.c @@ -0,0 +1,5 @@ +/* Test C2x auto. -Wc11-c2x-compat warning. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */ + +auto x = 2; /* { dg-warning "ISO C does not support 'auto' type deduction before" } */ diff --git a/gcc/testsuite/gcc.dg/gnu2x-auto-1.c b/gcc/testsuite/gcc.dg/gnu2x-auto-1.c new file mode 100644 index 0000000..e0b9e86 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu2x-auto-1.c @@ -0,0 +1,11 @@ +/* Test C2x auto. Invalid code with GNU extensions. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu2x" } */ + +void +f () +{ + /* Do not allow a non-definition declaration of a tag in the auto + initializer, to avoid it escaping an inner scope as shown here. */ + auto x = ({ struct s; struct s *x = 0; x; }); /* { dg-error "declared in underspecified object initializer" } */ +} -- cgit v1.1 From 20d5dca80b82df9b1295359edb44eb08c45c4334 Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Thu, 3 Nov 2022 01:22:45 -0500 Subject: testsuite: Fix gen-vect-34.c with vect_masked_load [PR106806] This is to fix the failure on powerpc as reported in PR106806, the test case requires tree ifcvt pass to perform on that loop, and it relies on masked_load support. The fix is to guard the expected scan with vect_masked_load effective target. As tested on powerpc64{,le}-linux-gnu and aarch64-linux-gnu (cfarm machine), the failures were gone. But on x86_64-redhat-linux (cfarm machine) the result becomes from PASS to N/A. I think it's expected since that machine doesn't support AVX by default so both check_avx_available and vect_masked_load fail, it should work fine on machines with default AVX support, or if we adjust the current check_avx_available with current_compiler_flags. PR testsuite/106806 gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/gen-vect-34.c: Adjust with vect_masked_load effective target. --- gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c index 41877e0..c2e5dfe 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c @@ -13,4 +13,4 @@ float summul(int n, float *arg1, float *arg2) return res1; } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { avr-*-* pru-*-* riscv*-*-* } } } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_masked_load } } } */ -- cgit v1.1 From f95e4eced20666a981881f76d66d997922648687 Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Thu, 3 Nov 2022 09:55:41 +0000 Subject: amdgcn: Fix duplicate conditionals [PR107510] Just a harmless cut-and-paste issue. PR target/107510 gcc/ChangeLog: * config/gcn/gcn.cc (gcn_expand_reduc_scalar): Remove duplicate UNSPEC_SMIN_DPP_SHR conditionals. --- gcc/config/gcn/gcn.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'gcc') diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc index b9d9170..1996115 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -4927,7 +4927,6 @@ gcn_expand_reduc_scalar (machine_mode mode, rtx src, int unspec) machine_mode scalar_mode = GET_MODE_INNER (mode); int vf = GET_MODE_NUNITS (mode); bool use_moves = (((unspec == UNSPEC_SMIN_DPP_SHR - || unspec == UNSPEC_SMIN_DPP_SHR || unspec == UNSPEC_SMAX_DPP_SHR || unspec == UNSPEC_UMIN_DPP_SHR || unspec == UNSPEC_UMAX_DPP_SHR) @@ -4936,7 +4935,6 @@ gcn_expand_reduc_scalar (machine_mode mode, rtx src, int unspec) || (unspec == UNSPEC_PLUS_DPP_SHR && scalar_mode == DFmode)); rtx_code code = (unspec == UNSPEC_SMIN_DPP_SHR ? SMIN - : unspec == UNSPEC_SMIN_DPP_SHR ? SMIN : unspec == UNSPEC_SMAX_DPP_SHR ? SMAX : unspec == UNSPEC_UMIN_DPP_SHR ? UMIN : unspec == UNSPEC_UMAX_DPP_SHR ? UMAX -- cgit v1.1 From 553b1d3dd5b9253ebdf66ee3260c717d5b807dd1 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 3 Nov 2022 14:17:42 +0100 Subject: i386: Fix uninitialized register after peephole2 conversion [PR107404] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The eliminate reg-reg move by inverting the condition of a cmove #2 peephole2 converts the following sequence: 473: bx:DI=[r14:DI*0x8+r12:DI] 960: r15:DI=r8:DI 485: {flags:CCC=cmp(r15:DI+bx:DI,bx:DI);r15:DI=r15:DI+bx:DI;} 737: r15:DI={(geu(flags:CCC,0))?r15:DI:bx:DI} to: 1110: {flags:CCC=cmp(r8:DI+bx:DI,bx:DI);r8:DI=r8:DI+bx:DI;} 1111: r15:DI=[r14:DI*0x8+r12:DI] 1112: r15:DI={(geu(flags:CCC,0))?r8:DI:r15:DI} Please note that(insn 1110) uses register BX, but its initialization was eliminated. Avoid conversion if eliminated move intialized a register, used in the moved instruction. 2022-11-03 Uroš Bizjak gcc/ChangeLog: PR target/107404 * config/i386/i386.md (eliminate reg-reg move by inverting the condition of a cmove #2 peephole2): Check if eliminated move initialized a register, used in the moved instruction. gcc/testsuite/ChangeLog: PR target/107404 * g++.target/i386/pr107404.C: New test. --- gcc/config/i386/i386.md | 3 +- gcc/testsuite/g++.target/i386/pr107404.C | 53 ++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.target/i386/pr107404.C (limited to 'gcc') diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 8556798..436eabb6 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -21800,7 +21800,8 @@ && REGNO (operands[2]) != REGNO (operands[1]) && peep2_reg_dead_p (2, operands[1]) && peep2_reg_dead_p (4, operands[2]) - && !reg_overlap_mentioned_p (operands[0], operands[3])" + && !reg_overlap_mentioned_p (operands[0], operands[3]) + && !reg_mentioned_p (operands[2], operands[6])" [(parallel [(set (match_dup 7) (match_dup 8)) (set (match_dup 1) (match_dup 9))]) (set (match_dup 0) (match_dup 3)) diff --git a/gcc/testsuite/g++.target/i386/pr107404.C b/gcc/testsuite/g++.target/i386/pr107404.C new file mode 100644 index 0000000..e47d0fd --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr107404.C @@ -0,0 +1,53 @@ +// PR target/107404 +// { dg-do run } +// { dg-options "-O3" } + +unsigned long long a; +void b(unsigned long long *f, int p2) { *f ^= p2; } +long c; +char e, i; +short g, m; +long long ab[1][25][21][22]; +unsigned long long aa[1][21][22]; +unsigned long long ae[1][25][21][21]; +long long ac[129360]; +char ad[25][1][21]; +char ah[1][25][1][21]; +short af[100]; +long max(long f, unsigned long p2) { return f < p2 ? p2 : f; } +const int &max2(const int &f, const int &p2) { return f < p2 ? p2 : f; } +void foo(unsigned f, unsigned p2, char l, char p4, long long n[][25][21][22], + unsigned long long p6[][21][22], unsigned long long u[][25][21][21]) { + long an; + for (int j = 0; j < 4; j = p2) + for (short k = 0; k < 7; k += 2) + for (short o = 0; o < (short)p2 + 21742; o = l) { + for (signed char p = 2; p < 9; p += p4) + if (p6[j][o][p]) + for (long q(3); 4 ? n[0][k][o][0] : 0; + q += p6[0][o][0] ? p6[j][0][p] : 0) + ac[j + q] = 5066799590; + for (long r(p4 - 16); r < 21; r += 4) { + ad[k][o][r] = max(u[j][k][o][r], f + u[j][k][o][r]); + long d = u[j][k][o][r]; + an = d < p2 ? p2 : d; + e = ah[j][k][o][r] = an; + af[o * r] = i; + } + for (short s(c); s < (short)p2; s = 2) + for (short am(m); am; am = max2(3, p2)) + for (long y = 0; y; y = 3) + for (short t(0); t < max2(g, 0);) + ; + } +} +int main() { + foo(7, 1558227751, 104, 16, ab, aa, ae); + for (unsigned long v = 0; v < 5; ++v) + for (unsigned long w = 0; w < 1; ++w) + for (unsigned long x = 0; x < 21; ++x) + b(&a, ad[v][w][x]); + + if (a) + __builtin_abort(); +} -- cgit v1.1 From 6629444170f85e9b1e243aa07e3e07a8b9f8fce5 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Thu, 3 Nov 2022 15:03:52 +0100 Subject: OpenMP/Fortran: 'target update' with DT components OpenMP 5.0 permits to use arrays with derived type components for the list items to the 'from'/'to' clauses of the 'target update' directive. gcc/fortran/ChangeLog: * openmp.cc (gfc_match_omp_clauses): Permit derived types for the 'to' and 'from' clauses of 'target update'. * trans-openmp.cc (gfc_trans_omp_clauses): Fixes for derived-type changes; fix size for scalars. libgomp/ChangeLog: * testsuite/libgomp.fortran/target-11.f90: New test. * testsuite/libgomp.fortran/target-13.f90: New test. --- gcc/fortran/openmp.cc | 10 ++++++---- gcc/fortran/trans-openmp.cc | 9 ++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 653c43f..e0e3b52 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -2499,9 +2499,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, true) == MATCH_YES) continue; if ((mask & OMP_CLAUSE_FROM) - && gfc_match_omp_variable_list ("from (", + && (gfc_match_omp_variable_list ("from (", &c->lists[OMP_LIST_FROM], false, - NULL, &head, true) == MATCH_YES) + NULL, &head, true, true) + == MATCH_YES)) continue; break; case 'g': @@ -3436,9 +3437,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, continue; } else if ((mask & OMP_CLAUSE_TO) - && gfc_match_omp_variable_list ("to (", + && (gfc_match_omp_variable_list ("to (", &c->lists[OMP_LIST_TO], false, - NULL, &head, true) == MATCH_YES) + NULL, &head, true, true) + == MATCH_YES)) continue; break; case 'u': diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 9bd4e6c..4bfdf85 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -3626,7 +3626,10 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, gcc_unreachable (); } tree node = build_omp_clause (input_location, clause_code); - if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL) + if (n->expr == NULL + || (n->expr->ref->type == REF_ARRAY + && n->expr->ref->u.ar.type == AR_FULL + && n->expr->ref->next == NULL)) { tree decl = gfc_trans_omp_variable (n->sym, false); if (gfc_omp_privatize_by_reference (decl)) @@ -3666,13 +3669,13 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, { tree ptr; gfc_init_se (&se, NULL); - if (n->expr->ref->u.ar.type == AR_ELEMENT) + if (n->expr->rank == 0) { gfc_conv_expr_reference (&se, n->expr); ptr = se.expr; gfc_add_block_to_block (block, &se.pre); OMP_CLAUSE_SIZE (node) - = TYPE_SIZE_UNIT (TREE_TYPE (ptr)); + = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr))); } else { -- cgit v1.1 From 5acc10a9ea66411e1712fabc94f9f29892b0d607 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 10:21:00 -0400 Subject: analyzer: fix ICE when pipe's arg isn't a pointer [PR107486] gcc/analyzer/ChangeLog: PR analyzer/107486 * analyzer.cc (is_pipe_call_p): New. * analyzer.h (is_pipe_call_p): New decl. * region-model.cc (region_model::on_call_pre): Use it. (region_model::on_call_post): Likewise. gcc/testsuite/ChangeLog: PR analyzer/107486 * gcc.dg/analyzer/pipe-pr107486.c: New test. * gcc.dg/analyzer/pipe-void-return.c: New test. Signed-off-by: David Malcolm --- gcc/analyzer/analyzer.cc | 16 ++++++++++++++++ gcc/analyzer/analyzer.h | 2 ++ gcc/analyzer/region-model.cc | 8 ++++---- gcc/testsuite/gcc.dg/analyzer/pipe-pr107486.c | 5 +++++ gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c | 11 +++++++++++ 5 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/pipe-pr107486.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c (limited to 'gcc') diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc index 8a2a773..6c7c969 100644 --- a/gcc/analyzer/analyzer.cc +++ b/gcc/analyzer/analyzer.cc @@ -379,6 +379,22 @@ is_longjmp_call_p (const gcall *call) return false; } +/* Return true if this is a "pipe" call. */ + +bool +is_pipe_call_p (const_tree fndecl, const char *funcname, + const gcall *call, unsigned int num_args) +{ + if (!is_named_call_p (fndecl, funcname, call, num_args)) + return false; + + /* We require a pointer for the initial argument. */ + if (!POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0)))) + return false; + + return true; +} + /* For a CALL that matched is_special_named_call_p or is_named_call_p for some name, return a name for the called function suitable for use in diagnostics (stripping the leading underscores). */ diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index a2d79e4..c41cfb0 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -324,6 +324,8 @@ extern bool is_std_named_call_p (const_tree fndecl, const char *funcname, const gcall *call, unsigned int num_args); extern bool is_setjmp_call_p (const gcall *call); extern bool is_longjmp_call_p (const gcall *call); +extern bool is_pipe_call_p (const_tree fndecl, const char *funcname, + const gcall *call, unsigned int num_args); extern const char *get_user_facing_name (const gcall *call); diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 7c44fc9..4713f0d 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -2315,8 +2315,8 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt, impl_call_memset (cd); return false; } - else if (is_named_call_p (callee_fndecl, "pipe", call, 1) - || is_named_call_p (callee_fndecl, "pipe2", call, 2)) + else if (is_pipe_call_p (callee_fndecl, "pipe", call, 1) + || is_pipe_call_p (callee_fndecl, "pipe2", call, 2)) { /* Handle in "on_call_post"; bail now so that fd array is left untouched so that we can detect use-of-uninit @@ -2403,8 +2403,8 @@ region_model::on_call_post (const gcall *call, impl_call_operator_delete (cd); return; } - else if (is_named_call_p (callee_fndecl, "pipe", call, 1) - || is_named_call_p (callee_fndecl, "pipe2", call, 2)) + else if (is_pipe_call_p (callee_fndecl, "pipe", call, 1) + || is_pipe_call_p (callee_fndecl, "pipe2", call, 2)) { impl_call_pipe (cd); return; diff --git a/gcc/testsuite/gcc.dg/analyzer/pipe-pr107486.c b/gcc/testsuite/gcc.dg/analyzer/pipe-pr107486.c new file mode 100644 index 0000000..e9fc7fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pipe-pr107486.c @@ -0,0 +1,5 @@ +void pipe(int); + +void f1(void) { + pipe(1); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c b/gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c new file mode 100644 index 0000000..0de6763 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pipe-void-return.c @@ -0,0 +1,11 @@ +extern void pipe(int pipefd[2]); +extern int close(int fd); + +void +test_unchecked (void) +{ + int fds[2]; + pipe (fds); /* { dg-message "when 'pipe' fails" } */ + close (fds[0]); /* { dg-warning "use of uninitialized value 'fds\\\[0\\\]'" } */ + close (fds[1]); /* { dg-warning "use of uninitialized value 'fds\\\[1\\\]'" } */ +} -- cgit v1.1 From 00d7c8ff16e6838273cea808ffbe22e98104f9d5 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 10:22:47 -0400 Subject: Add gcc/make-unique.h This patch adds gcc/make-unique.h, containing a minimal C++11 implementation of make_unique (std::make_unique is C++14). gcc/ChangeLog: * make-unique.h: New file. Signed-off-by: David Malcolm --- gcc/make-unique.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 gcc/make-unique.h (limited to 'gcc') diff --git a/gcc/make-unique.h b/gcc/make-unique.h new file mode 100644 index 0000000..c9a7d6e --- /dev/null +++ b/gcc/make-unique.h @@ -0,0 +1,44 @@ +/* Minimal implementation of make_unique for C++11 compatibility. + Copyright (C) 2022 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. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#ifndef GCC_MAKE_UNIQUE +#define GCC_MAKE_UNIQUE + +/* This header uses std::unique_ptr, but can't be directly + included due to issues with macros. Hence must be included + from system.h by defining INCLUDE_MEMORY in any source file using + make-unique.h. */ + +#ifndef INCLUDE_MEMORY +# error "You must define INCLUDE_MEMORY before including system.h to use make-unique.h" +#endif + +#include + +/* Minimal implementation of make_unique for C++11 compatibility + (std::make_unique is C++14). */ + +template +inline typename std::enable_if::value, std::unique_ptr>::type +make_unique(Args&&... args) +{ + return std::unique_ptr (new T (std::forward (args)...)); +} + +#endif /* ! GCC_MAKE_UNIQUE */ -- cgit v1.1 From 6fd485d15c1a2c427c39bcd45e03bed8cde689e6 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Wed, 2 Nov 2022 21:37:49 -0400 Subject: Update range query cache when a statement is updated. Add an update_stmt interface to range query, and hook into it with the ssa statement update call. gcc/ * gimple-range.cc (gimple_ranger::update_stmt): New. * gimple-range.h (gimple_ranger::update_stmt): New prototype. * tree-ssa-operands.cc (update_stmt_operands): Notify range query that stmt has changed. * value-query.h (range_query::update_stmt): New. gcc/testsuite/ * gcc.dg/tree-ssa/vrp-update.c: New. --- gcc/gimple-range.cc | 34 ++++++++++++++++++++++++++++++ gcc/gimple-range.h | 1 + gcc/testsuite/gcc.dg/tree-ssa/vrp-update.c | 21 ++++++++++++++++++ gcc/tree-ssa-operands.cc | 3 +++ gcc/value-query.h | 3 +++ 5 files changed, 62 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-update.c (limited to 'gcc') diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 110cf57..8063869 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -482,6 +482,40 @@ gimple_ranger::register_inferred_ranges (gimple *s) m_cache.apply_inferred_ranges (s); } +// When a statement S has changed since the result was cached, re-evaluate +// and update the global cache. + +void +gimple_ranger::update_stmt (gimple *s) +{ + tree lhs = gimple_get_lhs (s); + if (!lhs || !gimple_range_ssa_p (lhs)) + return; + Value_Range r (TREE_TYPE (lhs)); + // Only update if it already had a value. + if (m_cache.get_global_range (r, lhs)) + { + // Re-calculate a new value using just cache values. + Value_Range tmp (TREE_TYPE (lhs)); + fold_using_range f; + fur_depend src (s, &(gori ()), &m_cache); + f.fold_stmt (tmp, s, src, lhs); + + // Combine the new value with the old value to check for a change. + if (r.intersect (tmp)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + print_generic_expr (dump_file, lhs, TDF_SLIM); + fprintf (dump_file, " : global value re-evaluated to "); + r.dump (dump_file); + fputc ('\n', dump_file); + } + m_cache.set_global_range (lhs, r); + } + } +} + // This routine will export whatever global ranges are known to GCC // SSA_RANGE_NAME_INFO and SSA_NAME_PTR_INFO fields. diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index 4800bfb..22e05f6 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -51,6 +51,7 @@ public: virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override; virtual bool range_of_expr (vrange &r, tree name, gimple * = NULL) override; virtual bool range_on_edge (vrange &r, edge e, tree name) override; + virtual void update_stmt (gimple *) override; void range_on_entry (vrange &r, basic_block bb, tree name); void range_on_exit (vrange &r, basic_block bb, tree name); void export_global_ranges (); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-update.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-update.c new file mode 100644 index 0000000..9e5da88 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-update.c @@ -0,0 +1,21 @@ +/* { dg-options "-O2 -fdump-tree-vrp1 " } */ + +/* Tests that calls to update_stmt by the folder will also update ranger's + cache value and produce the correct result for the builtin_constant_p + function. */ + +void dead (); + +void foo( void *_thrdescr, int _result) +{ + const char *lossage = _result ? "constant string" : 0; + + if (__builtin_expect (lossage != ((void *)0) , 0)) + { + unsigned __message_length = __builtin_strlen (lossage); + if (! __builtin_constant_p (__message_length)) + dead (); + } +} + +/* { dg-final { scan-tree-dump-not "dead" "vrp1" } } */ diff --git a/gcc/tree-ssa-operands.cc b/gcc/tree-ssa-operands.cc index 4915622..9e85998 100644 --- a/gcc/tree-ssa-operands.cc +++ b/gcc/tree-ssa-operands.cc @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "stmt.h" #include "print-tree.h" #include "dumpfile.h" +#include "value-query.h" /* This file contains the code required to manage the operands cache of the @@ -1146,6 +1147,8 @@ update_stmt_operands (struct function *fn, gimple *stmt) gcc_assert (gimple_modified_p (stmt)); operands_scanner (fn, stmt).build_ssa_operands (); gimple_set_modified (stmt, false); + // Inform the active range query an update has happened. + get_range_query (fn)->update_stmt (stmt); timevar_pop (TV_TREE_OPS); } diff --git a/gcc/value-query.h b/gcc/value-query.h index fc638eb..b8e6fed 100644 --- a/gcc/value-query.h +++ b/gcc/value-query.h @@ -93,6 +93,9 @@ public: virtual bool range_on_edge (vrange &r, edge, tree expr); virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL); + // When the IL in a stmt is changed, call this for better results. + virtual void update_stmt (gimple *) { } + // Query if there is any relation between SSA1 and SSA2. relation_kind query_relation (gimple *s, tree ssa1, tree ssa2, bool get_range = true); -- cgit v1.1 From 6341f14e369a5cd5920bb91660cfea1b2594628f Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 13:47:01 -0400 Subject: analyzer: use std::unique_ptr for pending_diagnostic/note gcc/analyzer/ChangeLog: * call-info.cc: Add define of INCLUDE_MEMORY. * call-summary.cc: Likewise. * checker-path.cc: Likewise. * constraint-manager.cc: Likewise. * diagnostic-manager.cc: Likewise. (saved_diagnostic::saved_diagnostic): Use std::unique_ptr for param d and field m_d. (saved_diagnostic::~saved_diagnostic): Remove explicit delete of m_d. (saved_diagnostic::add_note): Use std::unique_ptr for param pn. (saved_diagnostic::get_pending_diagnostic): Update for conversion of m_sd.m_d to unique_ptr. (diagnostic_manager::add_diagnostic): Use std::unique_ptr for param d. Remove explicit deletion. (diagnostic_manager::add_note): Use std::unique_ptr for param pn. (diagnostic_manager::emit_saved_diagnostic): Update for conversion of m_sd.m_d to unique_ptr. (null_assignment_sm_context::warn): Use std::unique_ptr for param d. Remove explicit deletion. * diagnostic-manager.h (saved_diagnostic::saved_diagnostic): Use std::unique_ptr for param d. (saved_diagnostic::add_note): Likewise for param pn. (saved_diagnostic::m_d): Likewise. (diagnostic_manager::add_diagnostic): Use std::unique_ptr for param d. (diagnostic_manager::add_note): Use std::unique_ptr for param pn. * engine.cc: Include "make-unique.h". (impl_region_model_context::warn): Update to use std::unique_ptr for param, removing explicit deletion. (impl_region_model_context::add_note): Likewise. (impl_sm_context::warn): Update to use std::unique_ptr for param. (impl_region_model_context::on_state_leak): Likewise for result of on_leak. (exploded_node::on_longjmp): Use make_unique when creating pending_diagnostic. (exploded_graph::process_node): Likewise. * exploded-graph.h (impl_region_model_context::warn): Update to use std::unique_ptr for param. (impl_region_model_context::add_note): Likewise. * feasible-graph.cc: Add define of INCLUDE_MEMORY. * pending-diagnostic.cc: Likewise. * pending-diagnostic.h: Include analyzer.sm.h" * program-point.cc: Add define of INCLUDE_MEMORY. * program-state.cc: Likewise. * region-model-asm.cc: Likewise. * region-model-impl-calls.cc: Likewise. Include "make-unique.h". (region_model::impl_call_putenv): Use make_unique when creating pending_diagnostic. * region-model-manager.cc: Add define of INCLUDE_MEMORY. * region-model-reachability.cc: Likewise. * region-model.cc: Likewise. Include "make-unique.h". (region_model::get_gassign_result): Use make_unique when creating pending_diagnostic. (region_model::check_for_poison): Likewise. (region_model::on_stmt_pre): Likewise. (region_model::check_symbolic_bounds): Likewise. (region_model::check_region_bounds): Likewise. (annotating_ctxt: make_note): Use std::unique_ptr for result. (region_model::deref_rvalue): Use make_unique when creating pending_diagnostic. (region_model::check_for_writable_region): Likewise. (region_model::check_region_size): Likewise. (region_model::check_dynamic_size_for_floats): Likewise. (region_model::maybe_complain_about_infoleak): Likewise. (noop_region_model_context::add_note): Use std::unique_ptr for param. Remove explicit deletion. * region-model.h: Include "analyzer/pending-diagnostic.h". (region_model_context::warn): Convert param to std::unique_ptr. (region_model_context::add_note): Likewise. (noop_region_model_context::warn): Likewise. (noop_region_model_context::add_note): Likewise. (region_model_context_decorator::warn): Likewise. (region_model_context_decorator::add_note): Likewise. (note_adding_context::warn): Likewise. (note_adding_context::make_note): Likewise for return type. (test_region_model_context::warn): Convert param to std::unique_ptr. * region.cc: Add define of INCLUDE_MEMORY. * sm-fd.cc: Likewise. Include "make-unique.h". (fd_state_machine::check_for_fd_attrs): Use make_unique when creating pending_diagnostics. (fd_state_machine::on_open): Likewise. (fd_state_machine::on_creat): Likewise. (fd_state_machine::check_for_dup): Likewise. (fd_state_machine::on_close): Likewise. (fd_state_machine::check_for_open_fd): Likewise. (fd_state_machine::on_leak): Likewise, converting return type to std::unique_ptr. * sm-file.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (fileptr_state_machine::on_stmt): Use make_unique when creating pending_diagnostic. (fileptr_state_machine::on_leak): Likewise, converting return type to std::unique_ptr. * sm-malloc.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (malloc_state_machine::on_stmt): Use make_unique when creating pending_diagnostic. (malloc_state_machine::handle_free_of_non_heap): Likewise. (malloc_state_machine::on_deallocator_call): Likewise. (malloc_state_machine::on_realloc_call): Likewise. (malloc_state_machine::on_leak): Likewise, converting return type to std::unique_ptr. * sm-pattern-test.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (pattern_test_state_machine::on_condition): Use make_unique when creating pending_diagnostic. * sm-sensitive.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (sensitive_state_machine::warn_for_any_exposure): Use make_unique when creating pending_diagnostic. * sm-signal.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (signal_state_machine::on_stmt): Use make_unique when creating pending_diagnostic. * sm-taint.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (taint_state_machine::check_for_tainted_size_arg): Use make_unique when creating pending_diagnostic. (taint_state_machine::check_for_tainted_divisor): Likewise. (region_model::check_region_for_taint): Likewise. (region_model::check_dynamic_size_for_taint): Likewise. * sm.cc: Add define of INCLUDE_MEMORY. Include "analyzer/pending-diagnostic.h". (state_machine::on_leak): Move here from sm.h, changing return type to std::unique_ptr. * sm.h (state_machine::on_leak): Change return type to std::unique_ptr. Move defn of base impl to sm.cc (sm_context::warn): Convert param d to std_unique_ptr. * state-purge.cc: Add define of INCLUDE_MEMORY. * store.cc: Likewise. * svalue.cc: Likewise. * trimmed-graph.cc: Likewise. * varargs.cc: Likewise. Include "make-unique.h". (va_list_state_machine::check_for_ended_va_list): Use make_unique when creating pending_diagnostic. (va_list_state_machine::on_leak): Likewise, converting return type to std::unique_ptr. (region_model::impl_call_va_arg): Use make_unique when creating pending_diagnostic. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.c: Add define of INCLUDE_MEMORY. Include "make-unique.h". (gil_state_machine::check_for_pyobject_in_call): Use make_unique when creating pending_diagnostic. (gil_state_machine::on_stmt): Likewise. (gil_state_machine::check_for_pyobject_usage_without_gil): Likewise. * gcc.dg/plugin/analyzer_kernel_plugin.c: : Add define of INCLUDE_MEMORY. * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm --- gcc/analyzer/call-info.cc | 1 + gcc/analyzer/call-summary.cc | 1 + gcc/analyzer/checker-path.cc | 1 + gcc/analyzer/constraint-manager.cc | 1 + gcc/analyzer/diagnostic-manager.cc | 40 +++++----- gcc/analyzer/diagnostic-manager.h | 12 +-- gcc/analyzer/engine.cc | 41 +++++----- gcc/analyzer/exploded-graph.h | 4 +- gcc/analyzer/feasible-graph.cc | 1 + gcc/analyzer/pending-diagnostic.cc | 1 + gcc/analyzer/pending-diagnostic.h | 1 + gcc/analyzer/program-point.cc | 1 + gcc/analyzer/program-state.cc | 1 + gcc/analyzer/region-model-asm.cc | 1 + gcc/analyzer/region-model-impl-calls.cc | 4 +- gcc/analyzer/region-model-manager.cc | 1 + gcc/analyzer/region-model-reachability.cc | 1 + gcc/analyzer/region-model.cc | 87 +++++++++++++--------- gcc/analyzer/region-model.h | 31 ++++---- gcc/analyzer/region.cc | 1 + gcc/analyzer/sm-fd.cc | 58 +++++++++------ gcc/analyzer/sm-file.cc | 10 ++- gcc/analyzer/sm-malloc.cc | 53 ++++++------- gcc/analyzer/sm-pattern-test.cc | 6 +- gcc/analyzer/sm-sensitive.cc | 5 +- gcc/analyzer/sm-signal.cc | 6 +- gcc/analyzer/sm-taint.cc | 22 +++--- gcc/analyzer/sm.cc | 10 +++ gcc/analyzer/sm.h | 12 +-- gcc/analyzer/state-purge.cc | 1 + gcc/analyzer/store.cc | 1 + gcc/analyzer/svalue.cc | 1 + gcc/analyzer/trimmed-graph.cc | 1 + gcc/analyzer/varargs.cc | 24 +++--- gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c | 12 +-- .../gcc.dg/plugin/analyzer_kernel_plugin.c | 1 + .../gcc.dg/plugin/analyzer_known_fns_plugin.c | 1 + 37 files changed, 266 insertions(+), 190 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/call-info.cc b/gcc/analyzer/call-info.cc index 56059ac..3572e06 100644 --- a/gcc/analyzer/call-info.cc +++ b/gcc/analyzer/call-info.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc index 12ef82d..ebc7b50 100644 --- a/gcc/analyzer/call-summary.cc +++ b/gcc/analyzer/call-summary.cc @@ -18,6 +18,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc index 371111b..4cf28c2 100644 --- a/gcc/analyzer/checker-path.cc +++ b/gcc/analyzer/checker-path.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc index 96ae073..b4e51b0 100644 --- a/gcc/analyzer/constraint-manager.cc +++ b/gcc/analyzer/constraint-manager.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 695bde5..0444e52 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" @@ -638,14 +639,14 @@ saved_diagnostic::saved_diagnostic (const state_machine *sm, tree var, const svalue *sval, state_machine::state_t state, - pending_diagnostic *d, + std::unique_ptr d, unsigned idx) : m_sm (sm), m_enode (enode), m_snode (snode), m_stmt (stmt), /* stmt_finder could be on-stack; we want our own copy that can outlive that. */ m_stmt_finder (stmt_finder ? stmt_finder->clone () : NULL), m_var (var), m_sval (sval), m_state (state), - m_d (d), m_trailing_eedge (NULL), + m_d (std::move (d)), m_trailing_eedge (NULL), m_idx (idx), m_best_epath (NULL), m_problem (NULL), m_notes () @@ -662,7 +663,6 @@ saved_diagnostic::saved_diagnostic (const state_machine *sm, saved_diagnostic::~saved_diagnostic () { delete m_stmt_finder; - delete m_d; delete m_best_epath; delete m_problem; } @@ -689,10 +689,10 @@ saved_diagnostic::operator== (const saved_diagnostic &other) const /* Add PN to this diagnostic, taking ownership of it. */ void -saved_diagnostic::add_note (pending_note *pn) +saved_diagnostic::add_note (std::unique_ptr pn) { gcc_assert (pn); - m_notes.safe_push (pn); + m_notes.safe_push (pn.release ()); } /* Return a new json::object of the form @@ -896,7 +896,7 @@ public: pending_diagnostic *get_pending_diagnostic () const { - return m_sd.m_d; + return m_sd.m_d.get (); } bool reachable_from_p (const exploded_node *src_enode) const @@ -955,8 +955,7 @@ diagnostic_manager::diagnostic_manager (logger *logger, engine *eng, } /* Queue pending_diagnostic D at ENODE for later emission. - Return true/false signifying if the diagnostic was actually added. - Take ownership of D (or delete it). */ + Return true/false signifying if the diagnostic was actually added. */ bool diagnostic_manager::add_diagnostic (const state_machine *sm, @@ -966,7 +965,7 @@ diagnostic_manager::add_diagnostic (const state_machine *sm, tree var, const svalue *sval, state_machine::state_t state, - pending_diagnostic *d) + std::unique_ptr d) { LOG_FUNC (get_logger ()); @@ -987,7 +986,6 @@ diagnostic_manager::add_diagnostic (const state_machine *sm, if (get_logger ()) get_logger ()->log ("rejecting disabled warning %qs", d->get_kind ()); - delete d; m_num_disabled_diagnostics++; return false; } @@ -995,13 +993,13 @@ diagnostic_manager::add_diagnostic (const state_machine *sm, saved_diagnostic *sd = new saved_diagnostic (sm, enode, snode, stmt, finder, var, sval, - state, d, m_saved_diagnostics.length ()); + state, std::move (d), m_saved_diagnostics.length ()); m_saved_diagnostics.safe_push (sd); enode->add_diagnostic (sd); if (get_logger ()) log ("adding saved diagnostic %i at SN %i to EN %i: %qs", sd->get_index (), - snode->m_index, enode->m_index, d->get_kind ()); + snode->m_index, enode->m_index, sd->m_d->get_kind ()); return true; } @@ -1013,17 +1011,17 @@ bool diagnostic_manager::add_diagnostic (exploded_node *enode, const supernode *snode, const gimple *stmt, stmt_finder *finder, - pending_diagnostic *d) + std::unique_ptr d) { gcc_assert (enode); return add_diagnostic (NULL, enode, snode, stmt, finder, NULL_TREE, - NULL, 0, d); + NULL, 0, std::move (d)); } /* Add PN to the most recent saved_diagnostic. */ void -diagnostic_manager::add_note (pending_note *pn) +diagnostic_manager::add_note (std::unique_ptr pn) { LOG_FUNC (get_logger ()); gcc_assert (pn); @@ -1031,7 +1029,7 @@ diagnostic_manager::add_note (pending_note *pn) /* Get most recent saved_diagnostic. */ gcc_assert (m_saved_diagnostics.length () > 0); saved_diagnostic *sd = m_saved_diagnostics[m_saved_diagnostics.length () - 1]; - sd->add_note (pn); + sd->add_note (std::move (pn)); } /* Return a new json::object of the form @@ -1386,13 +1384,13 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg, emission_path.inject_any_inlined_call_events (get_logger ()); - emission_path.prepare_for_emission (sd.m_d); + emission_path.prepare_for_emission (sd.m_d.get ()); location_t loc = get_emission_location (sd.m_stmt, sd.m_snode->m_fun, *sd.m_d); /* Allow the pending_diagnostic to fix up the locations of events. */ - emission_path.fixup_locations (sd.m_d); + emission_path.fixup_locations (sd.m_d.get ()); gcc_rich_location rich_loc (loc); rich_loc.set_path (&emission_path); @@ -1783,14 +1781,12 @@ struct null_assignment_sm_context : public sm_context } void warn (const supernode *, const gimple *, - tree, pending_diagnostic *d) final override + tree, std::unique_ptr) final override { - delete d; } void warn (const supernode *, const gimple *, - const svalue *, pending_diagnostic *d) final override + const svalue *, std::unique_ptr) final override { - delete d; } tree get_diagnostic_tree (tree expr) final override diff --git a/gcc/analyzer/diagnostic-manager.h b/gcc/analyzer/diagnostic-manager.h index 266eed8..fdab038 100644 --- a/gcc/analyzer/diagnostic-manager.h +++ b/gcc/analyzer/diagnostic-manager.h @@ -36,13 +36,13 @@ public: stmt_finder *stmt_finder, tree var, const svalue *sval, state_machine::state_t state, - pending_diagnostic *d, + std::unique_ptr d, unsigned idx); ~saved_diagnostic (); bool operator== (const saved_diagnostic &other) const; - void add_note (pending_note *pn); + void add_note (std::unique_ptr pn); json::object *to_json () const; @@ -76,7 +76,7 @@ public: tree m_var; const svalue *m_sval; state_machine::state_t m_state; - pending_diagnostic *m_d; // owned + std::unique_ptr m_d; const exploded_edge *m_trailing_eedge; private: @@ -117,14 +117,14 @@ public: tree var, const svalue *sval, state_machine::state_t state, - pending_diagnostic *d); + std::unique_ptr d); bool add_diagnostic (exploded_node *enode, const supernode *snode, const gimple *stmt, stmt_finder *finder, - pending_diagnostic *d); + std::unique_ptr d); - void add_note (pending_note *pn); + void add_note (std::unique_ptr pn); void emit_saved_diagnostics (const exploded_graph &eg); diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 52978dd..fd532b1 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "fold-const.h" #include "gcc-rich-location.h" @@ -114,35 +115,29 @@ impl_region_model_context (program_state *state, } bool -impl_region_model_context::warn (pending_diagnostic *d) +impl_region_model_context::warn (std::unique_ptr d) { LOG_FUNC (get_logger ()); if (m_stmt == NULL && m_stmt_finder == NULL) { if (get_logger ()) get_logger ()->log ("rejecting diagnostic: no stmt"); - delete d; return false; } if (m_eg) return m_eg->get_diagnostic_manager ().add_diagnostic (m_enode_for_diag, m_enode_for_diag->get_supernode (), - m_stmt, m_stmt_finder, d); + m_stmt, m_stmt_finder, std::move (d)); else - { - delete d; - return false; - } + return false; } void -impl_region_model_context::add_note (pending_note *pn) +impl_region_model_context::add_note (std::unique_ptr pn) { LOG_FUNC (get_logger ()); if (m_eg) - m_eg->get_diagnostic_manager ().add_note (pn); - else - delete pn; + m_eg->get_diagnostic_manager ().add_note (std::move (pn)); } void @@ -401,10 +396,11 @@ public: } void warn (const supernode *snode, const gimple *stmt, - tree var, pending_diagnostic *d) final override + tree var, + std::unique_ptr d) final override { LOG_FUNC (get_logger ()); - gcc_assert (d); // take ownership + gcc_assert (d); impl_region_model_context old_ctxt (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL, NULL, NULL); @@ -416,14 +412,15 @@ public: : m_old_smap->get_global_state ()); m_eg.get_diagnostic_manager ().add_diagnostic (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder, - var, var_old_sval, current, d); + var, var_old_sval, current, std::move (d)); } void warn (const supernode *snode, const gimple *stmt, - const svalue *sval, pending_diagnostic *d) final override + const svalue *sval, + std::unique_ptr d) final override { LOG_FUNC (get_logger ()); - gcc_assert (d); // take ownership + gcc_assert (d); impl_region_model_context old_ctxt (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL, NULL, NULL); @@ -433,7 +430,7 @@ public: : m_old_smap->get_global_state ()); m_eg.get_diagnostic_manager ().add_diagnostic (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder, - NULL_TREE, sval, current, d); + NULL_TREE, sval, current, std::move (d)); } /* Hook for picking more readable trees for SSA names of temporaries, @@ -864,12 +861,12 @@ impl_region_model_context::on_state_leak (const state_machine &sm, } tree leaked_tree_for_diag = fixup_tree_for_diagnostic (leaked_tree); - pending_diagnostic *pd = sm.on_leak (leaked_tree_for_diag); + std::unique_ptr pd = sm.on_leak (leaked_tree_for_diag); if (pd) m_eg->get_diagnostic_manager ().add_diagnostic (&sm, m_enode_for_diag, m_enode_for_diag->get_supernode (), m_stmt, &stmt_finder, - leaked_tree_for_diag, sval, state, pd); + leaked_tree_for_diag, sval, state, std::move (pd)); } /* Implementation of region_model_context::on_condition vfunc. @@ -1845,7 +1842,9 @@ exploded_node::on_longjmp (exploded_graph &eg, /* Verify that the setjmp's call_stack hasn't been popped. */ if (!valid_longjmp_stack_p (longjmp_point, setjmp_point)) { - ctxt->warn (new stale_jmp_buf (setjmp_call, longjmp_call, setjmp_point)); + ctxt->warn (make_unique (setjmp_call, + longjmp_call, + setjmp_point)); return; } @@ -4243,7 +4242,7 @@ exploded_graph::process_node (exploded_node *node) const svalue *fn_ptr_sval = model->get_rvalue (fn_ptr, &ctxt); if (fn_ptr_sval->all_zeroes_p ()) - ctxt.warn (new jump_through_null (call)); + ctxt.warn (make_unique (call)); } /* An unknown function or a special function was called diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index 5996252..dae73da 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -56,8 +56,8 @@ class impl_region_model_context : public region_model_context uncertainty_t *uncertainty, logger *logger = NULL); - bool warn (pending_diagnostic *d) final override; - void add_note (pending_note *pn) final override; + bool warn (std::unique_ptr d) final override; + void add_note (std::unique_ptr pn) final override; void on_svalue_leak (const svalue *) override; void on_liveness_change (const svalue_set &live_svalues, const region_model *model) final override; diff --git a/gcc/analyzer/feasible-graph.cc b/gcc/analyzer/feasible-graph.cc index a946e4c..c5b0d62 100644 --- a/gcc/analyzer/feasible-graph.cc +++ b/gcc/analyzer/feasible-graph.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc index 50a8afc..a21c86f 100644 --- a/gcc/analyzer/pending-diagnostic.cc +++ b/gcc/analyzer/pending-diagnostic.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h index 4ea469e..6ca8ab9 100644 --- a/gcc/analyzer/pending-diagnostic.h +++ b/gcc/analyzer/pending-diagnostic.h @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #define GCC_ANALYZER_PENDING_DIAGNOSTIC_H #include "diagnostic-path.h" +#include "analyzer/sm.h" namespace ana { diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc index cfa4dda..23635a1 100644 --- a/gcc/analyzer/program-point.cc +++ b/gcc/analyzer/program-point.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index 7537dc0..d00fd5e 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/region-model-asm.cc b/gcc/analyzer/region-model-asm.cc index b4c1f91..171b249 100644 --- a/gcc/analyzer/region-model-asm.cc +++ b/gcc/analyzer/region-model-asm.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc index 52c4205..790dc64 100644 --- a/gcc/analyzer/region-model-impl-calls.cc +++ b/gcc/analyzer/region-model-impl-calls.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" @@ -54,6 +55,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-path.h" #include "analyzer/pending-diagnostic.h" #include "gimple-pretty-print.h" +#include "make-unique.h" #if ENABLE_ANALYZER @@ -745,7 +747,7 @@ region_model::impl_call_putenv (const call_details &cd) break; case MEMSPACE_STACK: if (ctxt) - ctxt->warn (new putenv_of_auto_var (fndecl, reg)); + ctxt->warn (make_unique (fndecl, reg)); break; } } diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index f5999e6..de01627 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/region-model-reachability.cc b/gcc/analyzer/region-model-reachability.cc index be1372c..6d2711a 100644 --- a/gcc/analyzer/region-model-reachability.cc +++ b/gcc/analyzer/region-model-reachability.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 4713f0d..37b113f 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -813,14 +814,17 @@ region_model::get_gassign_result (const gassign *assign, if (TREE_CODE (rhs2_cst) == INTEGER_CST) { if (tree_int_cst_sgn (rhs2_cst) < 0) - ctxt->warn (new shift_count_negative_diagnostic - (assign, rhs2_cst)); + ctxt->warn + (make_unique + (assign, rhs2_cst)); else if (compare_tree_int (rhs2_cst, TYPE_PRECISION (TREE_TYPE (rhs1))) >= 0) - ctxt->warn (new shift_count_overflow_diagnostic - (assign, TYPE_PRECISION (TREE_TYPE (rhs1)), - rhs2_cst)); + ctxt->warn + (make_unique + (assign, + int (TYPE_PRECISION (TREE_TYPE (rhs1))), + rhs2_cst)); } } @@ -1038,8 +1042,9 @@ region_model::check_for_poison (const svalue *sval, const region *src_region = NULL; if (pkind == POISON_KIND_UNINIT) src_region = get_region_for_poisoned_expr (expr); - if (ctxt->warn (new poisoned_value_diagnostic (diag_arg, pkind, - src_region))) + if (ctxt->warn (make_unique (diag_arg, + pkind, + src_region))) { /* We only want to report use of a poisoned value at the first place it gets used; return an unknown value to avoid generating @@ -1228,7 +1233,7 @@ region_model::on_stmt_pre (const gimple *stmt, { /* Handle the builtin "__analyzer_dump_path" by queuing a diagnostic at this exploded_node. */ - ctxt->warn (new dump_path_diagnostic ()); + ctxt->warn (make_unique ()); } else if (is_special_named_call_p (call, "__analyzer_dump_region_model", 0)) @@ -1784,16 +1789,18 @@ void region_model::check_symbolic_bounds (const region *base_reg, gcc_unreachable (); break; case DIR_READ: - ctxt->warn (new symbolic_buffer_overread (base_reg, diag_arg, - offset_tree, - num_bytes_tree, - capacity_tree)); + ctxt->warn (make_unique (base_reg, + diag_arg, + offset_tree, + num_bytes_tree, + capacity_tree)); break; case DIR_WRITE: - ctxt->warn (new symbolic_buffer_overflow (base_reg, diag_arg, - offset_tree, - num_bytes_tree, - capacity_tree)); + ctxt->warn (make_unique (base_reg, + diag_arg, + offset_tree, + num_bytes_tree, + capacity_tree)); break; } } @@ -1884,10 +1891,10 @@ region_model::check_region_bounds (const region *reg, gcc_unreachable (); break; case DIR_READ: - ctxt->warn (new buffer_underread (reg, diag_arg, out)); + ctxt->warn (make_unique (reg, diag_arg, out)); break; case DIR_WRITE: - ctxt->warn (new buffer_underflow (reg, diag_arg, out)); + ctxt->warn (make_unique (reg, diag_arg, out)); break; } } @@ -1912,10 +1919,12 @@ region_model::check_region_bounds (const region *reg, gcc_unreachable (); break; case DIR_READ: - ctxt->warn (new buffer_overread (reg, diag_arg, out, byte_bound)); + ctxt->warn (make_unique (reg, diag_arg, + out, byte_bound)); break; case DIR_WRITE: - ctxt->warn (new buffer_overflow (reg, diag_arg, out, byte_bound)); + ctxt->warn (make_unique (reg, diag_arg, + out, byte_bound)); break; } } @@ -2564,9 +2573,10 @@ check_external_function_for_access_attr (const gcall *call, m_access (access) { } - pending_note *make_note () final override + std::unique_ptr make_note () final override { - return new reason_attr_access (m_callee_fndecl, m_access); + return make_unique + (m_callee_fndecl, m_access); } private: tree m_callee_fndecl; @@ -3374,7 +3384,8 @@ region_model::deref_rvalue (const svalue *ptr_sval, tree ptr_tree, const poisoned_svalue *poisoned_sval = as_a (ptr_sval); enum poison_kind pkind = poisoned_sval->get_poison_kind (); - ctxt->warn (new poisoned_value_diagnostic (ptr, pkind, NULL)); + ctxt->warn (make_unique + (ptr, pkind, NULL)); } } } @@ -3531,14 +3542,16 @@ region_model::check_for_writable_region (const region* dest_reg, { const function_region *func_reg = as_a (base_reg); tree fndecl = func_reg->get_fndecl (); - ctxt->warn (new write_to_const_diagnostic (func_reg, fndecl)); + ctxt->warn (make_unique + (func_reg, fndecl)); } break; case RK_LABEL: { const label_region *label_reg = as_a (base_reg); tree label = label_reg->get_label (); - ctxt->warn (new write_to_const_diagnostic (label_reg, label)); + ctxt->warn (make_unique + (label_reg, label)); } break; case RK_DECL: @@ -3551,11 +3564,11 @@ region_model::check_for_writable_region (const region* dest_reg, "this" param is "T* const"). */ if (TREE_READONLY (decl) && is_global_var (decl)) - ctxt->warn (new write_to_const_diagnostic (dest_reg, decl)); + ctxt->warn (make_unique (dest_reg, decl)); } break; case RK_STRING: - ctxt->warn (new write_to_string_literal_diagnostic (dest_reg)); + ctxt->warn (make_unique (dest_reg)); break; } } @@ -4031,8 +4044,8 @@ region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval, if (TREE_CODE (cst_cap) == INTEGER_CST && !capacity_compatible_with_type (cst_cap, pointee_size_tree, is_struct)) - ctxt->warn (new dubious_allocation_size (lhs_reg, rhs_reg, - cst_cap)); + ctxt->warn (make_unique (lhs_reg, rhs_reg, + cst_cap)); } break; default: @@ -4043,8 +4056,9 @@ region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval, if (!v.get_result ()) { tree expr = get_representative_tree (capacity); - ctxt->warn (new dubious_allocation_size (lhs_reg, rhs_reg, - expr)); + ctxt->warn (make_unique (lhs_reg, + rhs_reg, + expr)); } } break; @@ -5766,7 +5780,7 @@ region_model::check_dynamic_size_for_floats (const svalue *size_in_bytes, if (const svalue *float_sval = v.get_svalue_to_report ()) { tree diag_arg = get_representative_tree (float_sval); - ctxt->warn (new float_as_size_arg (diag_arg)); + ctxt->warn (make_unique (diag_arg)); } } @@ -6389,17 +6403,16 @@ region_model::maybe_complain_about_infoleak (const region *dst_reg, { /* Check for exposure. */ if (contains_uninit_p (copied_sval)) - ctxt->warn (new exposure_through_uninit_copy (src_reg, - dst_reg, - copied_sval)); + ctxt->warn (make_unique (src_reg, + dst_reg, + copied_sval)); } /* class noop_region_model_context : public region_model_context. */ void -noop_region_model_context::add_note (pending_note *pn) +noop_region_model_context::add_note (std::unique_ptr) { - delete pn; } void diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index 19e8043..91b17ce2ad9 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/region.h" #include "analyzer/known-function-manager.h" #include "analyzer/region-model-manager.h" +#include "analyzer/pending-diagnostic.h" using namespace ana; @@ -671,11 +672,11 @@ class region_model_context public: /* Hook for clients to store pending diagnostics. Return true if the diagnostic was stored, or false if it was deleted. */ - virtual bool warn (pending_diagnostic *d) = 0; + virtual bool warn (std::unique_ptr d) = 0; - /* Hook for clients to add a note to the last previously stored pending diagnostic. - Takes ownership of the pending_node (or deletes it). */ - virtual void add_note (pending_note *pn) = 0; + /* Hook for clients to add a note to the last previously stored + pending diagnostic. */ + virtual void add_note (std::unique_ptr pn) = 0; /* Hook for clients to be notified when an SVAL that was reachable in a previous state is no longer live, so that clients can emit warnings @@ -774,8 +775,8 @@ class region_model_context class noop_region_model_context : public region_model_context { public: - bool warn (pending_diagnostic *) override { return false; } - void add_note (pending_note *pn) override; + bool warn (std::unique_ptr) override { return false; } + void add_note (std::unique_ptr) override; void on_svalue_leak (const svalue *) override {} void on_liveness_change (const svalue_set &, const region_model *) override {} @@ -847,14 +848,14 @@ private: class region_model_context_decorator : public region_model_context { public: - bool warn (pending_diagnostic *d) override + bool warn (std::unique_ptr d) override { - return m_inner->warn (d); + return m_inner->warn (std::move (d)); } - void add_note (pending_note *pn) override + void add_note (std::unique_ptr pn) override { - m_inner->add_note (pn); + m_inner->add_note (std::move (pn)); } void on_svalue_leak (const svalue *sval) override @@ -961,9 +962,9 @@ protected: class note_adding_context : public region_model_context_decorator { public: - bool warn (pending_diagnostic *d) override + bool warn (std::unique_ptr d) override { - if (m_inner->warn (d)) + if (m_inner->warn (std::move (d))) { add_note (make_note ()); return true; @@ -973,7 +974,7 @@ public: } /* Hook to make the new note. */ - virtual pending_note *make_note () = 0; + virtual std::unique_ptr make_note () = 0; protected: note_adding_context (region_model_context *inner) @@ -1116,9 +1117,9 @@ using namespace ::selftest; class test_region_model_context : public noop_region_model_context { public: - bool warn (pending_diagnostic *d) final override + bool warn (std::unique_ptr d) final override { - m_diagnostics.safe_push (d); + m_diagnostics.safe_push (d.release ()); return true; } diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index da5a13e..4bc1918 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc index ae846cd..da0e92b 100644 --- a/gcc/analyzer/sm-fd.cc +++ b/gcc/analyzer/sm-fd.cc @@ -19,8 +19,10 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -110,7 +112,7 @@ public: const svalue *rhs) const final override; bool can_purge_p (state_t s) const final override; - pending_diagnostic *on_leak (tree var) const final override; + std::unique_ptr on_leak (tree var) const final override; bool is_unchecked_fd_p (state_t s) const; bool is_valid_fd_p (state_t s) const; @@ -885,9 +887,10 @@ fd_state_machine::check_for_fd_attrs ( { sm_ctxt->warn (node, stmt, arg, - new fd_use_after_close (*this, diag_arg, - callee_fndecl, attr_name, - arg_idx)); + make_unique + (*this, diag_arg, + callee_fndecl, attr_name, + arg_idx)); continue; } @@ -895,9 +898,10 @@ fd_state_machine::check_for_fd_attrs ( { if (!is_constant_fd_p (state)) sm_ctxt->warn (node, stmt, arg, - new fd_use_without_check (*this, diag_arg, - callee_fndecl, attr_name, - arg_idx)); + make_unique + (*this, diag_arg, + callee_fndecl, attr_name, + arg_idx)); } switch (fd_attr_access_dir) @@ -910,8 +914,11 @@ fd_state_machine::check_for_fd_attrs ( { sm_ctxt->warn ( node, stmt, arg, - new fd_access_mode_mismatch (*this, diag_arg, DIRS_WRITE, - callee_fndecl, attr_name, arg_idx)); + make_unique (*this, diag_arg, + DIRS_WRITE, + callee_fndecl, + attr_name, + arg_idx)); } break; @@ -921,8 +928,11 @@ fd_state_machine::check_for_fd_attrs ( { sm_ctxt->warn ( node, stmt, arg, - new fd_access_mode_mismatch (*this, diag_arg, DIRS_READ, - callee_fndecl, attr_name, arg_idx)); + make_unique (*this, diag_arg, + DIRS_READ, + callee_fndecl, + attr_name, + arg_idx)); } break; @@ -963,7 +973,8 @@ fd_state_machine::on_open (sm_context *sm_ctxt, const supernode *node, } else { - sm_ctxt->warn (node, stmt, NULL_TREE, new fd_leak (*this, NULL_TREE)); + sm_ctxt->warn (node, stmt, NULL_TREE, + make_unique (*this, NULL_TREE)); } } @@ -975,7 +986,8 @@ fd_state_machine::on_creat (sm_context *sm_ctxt, const supernode *node, if (lhs) sm_ctxt->on_transition (node, stmt, lhs, m_start, m_unchecked_write_only); else - sm_ctxt->warn (node, stmt, NULL_TREE, new fd_leak (*this, NULL_TREE)); + sm_ctxt->warn (node, stmt, NULL_TREE, + make_unique (*this, NULL_TREE)); } void @@ -1021,7 +1033,8 @@ fd_state_machine::check_for_dup (sm_context *sm_ctxt, const supernode *node, { sm_ctxt->warn ( node, stmt, arg_2, - new fd_use_without_check (*this, diag_arg_2, callee_fndecl)); + make_unique (*this, diag_arg_2, + callee_fndecl)); return; } /* dup2 returns value of its second argument on success.But, the @@ -1059,7 +1072,8 @@ fd_state_machine::on_close (sm_context *sm_ctxt, const supernode *node, if (is_closed_fd_p (state)) { - sm_ctxt->warn (node, stmt, arg, new fd_double_close (*this, diag_arg)); + sm_ctxt->warn (node, stmt, arg, + make_unique (*this, diag_arg)); sm_ctxt->set_next_state (stmt, arg, m_stop); } } @@ -1091,7 +1105,8 @@ fd_state_machine::check_for_open_fd ( if (is_closed_fd_p (state)) { sm_ctxt->warn (node, stmt, arg, - new fd_use_after_close (*this, diag_arg, callee_fndecl)); + make_unique (*this, diag_arg, + callee_fndecl)); } else @@ -1101,7 +1116,8 @@ fd_state_machine::check_for_open_fd ( if (!is_constant_fd_p (state)) sm_ctxt->warn ( node, stmt, arg, - new fd_use_without_check (*this, diag_arg, callee_fndecl)); + make_unique (*this, diag_arg, + callee_fndecl)); } switch (callee_fndecl_dir) { @@ -1112,7 +1128,7 @@ fd_state_machine::check_for_open_fd ( { tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, - new fd_access_mode_mismatch ( + make_unique ( *this, diag_arg, DIRS_WRITE, callee_fndecl)); } @@ -1123,7 +1139,7 @@ fd_state_machine::check_for_open_fd ( { tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, - new fd_access_mode_mismatch ( + make_unique ( *this, diag_arg, DIRS_READ, callee_fndecl)); } break; @@ -1195,10 +1211,10 @@ fd_state_machine::can_purge_p (state_t s) const return true; } -pending_diagnostic * +std::unique_ptr fd_state_machine::on_leak (tree var) const { - return new fd_leak (*this, var); + return make_unique (*this, var); } } // namespace diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc index 13f2507..cbd1788 100644 --- a/gcc/analyzer/sm-file.cc +++ b/gcc/analyzer/sm-file.cc @@ -19,8 +19,10 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -79,7 +81,7 @@ public: const svalue *rhs) const final override; bool can_purge_p (state_t s) const final override; - pending_diagnostic *on_leak (tree var) const final override; + std::unique_ptr on_leak (tree var) const final override; /* State for a FILE * returned from fopen that hasn't been checked for NULL. @@ -404,7 +406,7 @@ fileptr_state_machine::on_stmt (sm_context *sm_ctxt, { tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, - new double_fclose (*this, diag_arg)); + make_unique (*this, diag_arg)); sm_ctxt->set_next_state (stmt, arg, m_stop); } return true; @@ -471,10 +473,10 @@ fileptr_state_machine::can_purge_p (state_t s) const fileptr_state_machine, for complaining about leaks of FILE * in state 'unchecked' and 'nonnull'. */ -pending_diagnostic * +std::unique_ptr fileptr_state_machine::on_leak (tree var) const { - return new file_leak (*this, var); + return make_unique (*this, var); } } // anonymous namespace diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index fef6e63..d050ef8 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -19,8 +19,10 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -383,7 +385,7 @@ public: const svalue *rhs) const final override; bool can_purge_p (state_t s) const final override; - pending_diagnostic *on_leak (tree var) const final override; + std::unique_ptr on_leak (tree var) const final override; bool reset_when_passed_to_unknown_fn_p (state_t s, bool is_mutable) const final override; @@ -1726,9 +1728,8 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, { tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, - new possible_null_arg (*this, diag_arg, - callee_fndecl, - i)); + make_unique + (*this, diag_arg, callee_fndecl, i)); const allocation_state *astate = as_a_allocation_state (state); sm_ctxt->set_next_state (stmt, arg, @@ -1738,8 +1739,8 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, { tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, - new null_arg (*this, diag_arg, - callee_fndecl, i)); + make_unique + (*this, diag_arg, callee_fndecl, i)); sm_ctxt->set_next_state (stmt, arg, m_stop); } } @@ -1781,7 +1782,8 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, { tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, - new possible_null_deref (*this, diag_arg)); + make_unique (*this, + diag_arg)); const allocation_state *astate = as_a_allocation_state (state); sm_ctxt->set_next_state (stmt, arg, astate->get_nonnull ()); } @@ -1789,7 +1791,7 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, { tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, - new null_deref (*this, diag_arg)); + make_unique (*this, diag_arg)); sm_ctxt->set_next_state (stmt, arg, m_stop); } else if (freed_p (state)) @@ -1797,8 +1799,8 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); const allocation_state *astate = as_a_allocation_state (state); sm_ctxt->warn (node, stmt, arg, - new use_after_free (*this, diag_arg, - astate->m_deallocator)); + make_unique + (*this, diag_arg, astate->m_deallocator)); sm_ctxt->set_next_state (stmt, arg, m_stop); } } @@ -1850,8 +1852,8 @@ malloc_state_machine::handle_free_of_non_heap (sm_context *sm_ctxt, freed_reg = old_model->deref_rvalue (ptr_sval, arg, NULL); } sm_ctxt->warn (node, call, arg, - new free_of_non_heap (*this, diag_arg, freed_reg, - d->m_name)); + make_unique + (*this, diag_arg, freed_reg, d->m_name)); sm_ctxt->set_next_state (call, arg, m_stop); } @@ -1879,11 +1881,11 @@ malloc_state_machine::on_deallocator_call (sm_context *sm_ctxt, { /* Wrong allocator. */ tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); - pending_diagnostic *pd - = new mismatching_deallocation (*this, diag_arg, - astate->m_deallocators, - d); - sm_ctxt->warn (node, call, arg, pd); + sm_ctxt->warn (node, call, arg, + make_unique + (*this, diag_arg, + astate->m_deallocators, + d)); } sm_ctxt->set_next_state (call, arg, d->m_freed); } @@ -1895,7 +1897,7 @@ malloc_state_machine::on_deallocator_call (sm_context *sm_ctxt, /* freed -> stop, with warning. */ tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, call, arg, - new double_free (*this, diag_arg, d->m_name)); + make_unique (*this, diag_arg, d->m_name)); sm_ctxt->set_next_state (call, arg, m_stop); } else if (state == m_non_heap) @@ -1933,11 +1935,10 @@ malloc_state_machine::on_realloc_call (sm_context *sm_ctxt, { /* Wrong allocator. */ tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); - pending_diagnostic *pd - = new mismatching_deallocation (*this, diag_arg, - astate->m_deallocators, - d); - sm_ctxt->warn (node, call, arg, pd); + sm_ctxt->warn (node, call, arg, + make_unique + (*this, diag_arg, + astate->m_deallocators, d)); sm_ctxt->set_next_state (call, arg, m_stop); if (path_context *path_ctxt = sm_ctxt->get_path_context ()) path_ctxt->terminate_path (); @@ -1948,7 +1949,7 @@ malloc_state_machine::on_realloc_call (sm_context *sm_ctxt, /* freed -> stop, with warning. */ tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, call, arg, - new double_free (*this, diag_arg, "free")); + make_unique (*this, diag_arg, "free")); sm_ctxt->set_next_state (call, arg, m_stop); if (path_context *path_ctxt = sm_ctxt->get_path_context ()) path_ctxt->terminate_path (); @@ -2030,10 +2031,10 @@ malloc_state_machine::can_purge_p (state_t s) const (for complaining about leaks of pointers in state 'unchecked' and 'nonnull'). */ -pending_diagnostic * +std::unique_ptr malloc_state_machine::on_leak (tree var) const { - return new malloc_leak (*this, var); + return make_unique (*this, var); } /* Implementation of state_machine::reset_when_passed_to_unknown_fn_p vfunc diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc index 3208132..704f628 100644 --- a/gcc/analyzer/sm-pattern-test.cc +++ b/gcc/analyzer/sm-pattern-test.cc @@ -21,8 +21,10 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -139,8 +141,8 @@ pattern_test_state_machine::on_condition (sm_context *sm_ctxt, if (tree lhs_expr = sm_ctxt->get_diagnostic_tree (lhs)) { - pending_diagnostic *diag = new pattern_match (lhs_expr, op, rhs_cst); - sm_ctxt->warn (node, stmt, lhs_expr, diag); + sm_ctxt->warn (node, stmt, lhs_expr, + make_unique (lhs_expr, op, rhs_cst)); } } diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc index cb5f859..d19765f 100644 --- a/gcc/analyzer/sm-sensitive.cc +++ b/gcc/analyzer/sm-sensitive.cc @@ -20,8 +20,10 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -181,7 +183,8 @@ sensitive_state_machine::warn_for_any_exposure (sm_context *sm_ctxt, { tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, - new exposure_through_output_file (*this, diag_arg)); + make_unique (*this, + diag_arg)); } } diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index e3b08c3..737ec4a 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -21,8 +21,10 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -351,8 +353,8 @@ signal_state_machine::on_stmt (sm_context *sm_ctxt, if (signal_unsafe_p (callee_fndecl)) if (sm_ctxt->get_global_state () == m_in_signal_handler) sm_ctxt->warn (node, stmt, NULL_TREE, - new signal_unsafe_call (*this, call, - callee_fndecl)); + make_unique + (*this, call, callee_fndecl)); } return false; diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc index bc27533..d4ee6c4 100644 --- a/gcc/analyzer/sm-taint.cc +++ b/gcc/analyzer/sm-taint.cc @@ -21,8 +21,10 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -1163,10 +1165,11 @@ taint_state_machine::check_for_tainted_size_arg (sm_context *sm_ctxt, TREE_STRING_POINTER (access->to_external_string ()); tree diag_size = sm_ctxt->get_diagnostic_tree (size_arg); sm_ctxt->warn (node, call, size_arg, - new tainted_access_attrib_size (*this, diag_size, b, - callee_fndecl, - access->sizarg, - access_str)); + make_unique + (*this, diag_size, b, + callee_fndecl, + access->sizarg, + access_str)); } } } @@ -1201,7 +1204,7 @@ taint_state_machine::check_for_tainted_divisor (sm_context *sm_ctxt, tree diag_divisor = sm_ctxt->get_diagnostic_tree (divisor_expr); sm_ctxt->warn (node, assign, divisor_expr, - new tainted_divisor (*this, diag_divisor, b)); + make_unique (*this, diag_divisor, b)); sm_ctxt->set_next_state (assign, divisor_sval, m_stop); } } @@ -1264,7 +1267,7 @@ region_model::check_region_for_taint (const region *reg, if (taint_sm.get_taint (state, index->get_type (), &b)) { tree arg = get_representative_tree (index); - ctxt->warn (new tainted_array_index (taint_sm, arg, b)); + ctxt->warn (make_unique (taint_sm, arg, b)); } } break; @@ -1286,7 +1289,7 @@ region_model::check_region_for_taint (const region *reg, if (taint_sm.get_taint (state, effective_type, &b)) { tree arg = get_representative_tree (offset); - ctxt->warn (new tainted_offset (taint_sm, arg, b)); + ctxt->warn (make_unique (taint_sm, arg, b)); } } break; @@ -1311,7 +1314,7 @@ region_model::check_region_for_taint (const region *reg, if (taint_sm.get_taint (state, size_sval->get_type (), &b)) { tree arg = get_representative_tree (size_sval); - ctxt->warn (new tainted_size (taint_sm, arg, b)); + ctxt->warn (make_unique (taint_sm, arg, b)); } } break; @@ -1357,7 +1360,8 @@ region_model::check_dynamic_size_for_taint (enum memory_space mem_space, if (taint_sm.get_taint (state, size_in_bytes->get_type (), &b)) { tree arg = get_representative_tree (size_in_bytes); - ctxt->warn (new tainted_allocation_size (taint_sm, arg, b, mem_space)); + ctxt->warn (make_unique + (taint_sm, arg, b, mem_space)); } } diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc index 1ab4c21..1f329cb 100644 --- a/gcc/analyzer/sm.cc +++ b/gcc/analyzer/sm.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" @@ -39,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/store.h" #include "analyzer/svalue.h" #include "analyzer/program-state.h" +#include "analyzer/pending-diagnostic.h" #if ENABLE_ANALYZER @@ -121,6 +123,14 @@ state_machine::get_state_by_name (const char *name) const gcc_unreachable (); } +/* Base implementation of state_machine::on_leak. */ + +std::unique_ptr +state_machine::on_leak (tree var ATTRIBUTE_UNUSED) const +{ + return NULL; +} + /* Dump a multiline representation of this state machine to PP. */ void diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h index 87ab11c..0171474 100644 --- a/gcc/analyzer/sm.h +++ b/gcc/analyzer/sm.h @@ -123,10 +123,8 @@ public: virtual bool can_purge_p (state_t s) const = 0; /* Called when VAR leaks (and !can_purge_p). */ - virtual pending_diagnostic *on_leak (tree var ATTRIBUTE_UNUSED) const - { - return NULL; - } + virtual std::unique_ptr + on_leak (tree var ATTRIBUTE_UNUSED) const; /* Return true if S should be reset to "start" for values passed (or reachable from) calls to unknown functions. IS_MUTABLE is true for pointers as @@ -250,9 +248,11 @@ public: /* Called by state_machine in response to pattern matches: issue a diagnostic D using NODE and STMT for location information. */ virtual void warn (const supernode *node, const gimple *stmt, - tree var, pending_diagnostic *d) = 0; + tree var, + std::unique_ptr d) = 0; virtual void warn (const supernode *node, const gimple *stmt, - const svalue *var, pending_diagnostic *d) = 0; + const svalue *var, + std::unique_ptr d) = 0; /* For use when generating trees when creating pending_diagnostics, so that rather than e.g. diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc index d3f516a..6fac18a 100644 --- a/gcc/analyzer/state-purge.cc +++ b/gcc/analyzer/state-purge.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index 2631ea2..c0f5ed1 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc index 4b00a81..aa03b04 100644 --- a/gcc/analyzer/svalue.cc +++ b/gcc/analyzer/svalue.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/trimmed-graph.cc b/gcc/analyzer/trimmed-graph.cc index 9fdb4a9..9a42248 100644 --- a/gcc/analyzer/trimmed-graph.cc +++ b/gcc/analyzer/trimmed-graph.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc index e4dbad7..8b1d809 100644 --- a/gcc/analyzer/varargs.cc +++ b/gcc/analyzer/varargs.cc @@ -19,8 +19,10 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "tree.h" #include "function.h" #include "basic-block.h" @@ -212,7 +214,7 @@ public: { return s != m_started; } - pending_diagnostic *on_leak (tree var) const final override; + std::unique_ptr on_leak (tree var) const final override; /* State for a va_list that the result of a va_start or va_copy. */ state_t m_started; @@ -553,8 +555,8 @@ va_list_state_machine::check_for_ended_va_list (sm_context *sm_ctxt, { if (sm_ctxt->get_state (call, arg) == m_ended) sm_ctxt->warn (node, call, arg, - new va_list_use_after_va_end (*this, arg, NULL_TREE, - usage_fnname)); + make_unique + (*this, arg, NULL_TREE, usage_fnname)); } /* Get the svalue with associated va_list_state_machine state for @@ -629,10 +631,10 @@ va_list_state_machine::on_va_end (sm_context *sm_ctxt, /* Implementation of state_machine::on_leak vfunc for va_list_state_machine (for complaining about leaks of values in state 'started'). */ -pending_diagnostic * +std::unique_ptr va_list_state_machine::on_leak (tree var) const { - return new va_list_leak (*this, NULL, var); + return make_unique (*this, NULL, var); } } // anonymous namespace @@ -1000,17 +1002,19 @@ region_model::impl_call_va_arg (const call_details &cd) else { if (ctxt) - ctxt->warn (new va_arg_type_mismatch (va_list_tree, - arg_reg, - lhs_type, - arg_type)); + ctxt->warn (make_unique + (va_list_tree, + arg_reg, + lhs_type, + arg_type)); saw_problem = true; } } else { if (ctxt) - ctxt->warn (new va_list_exhausted (va_list_tree, arg_reg)); + ctxt->warn (make_unique (va_list_tree, + arg_reg)); saw_problem = true; } } diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c index 2a8bf11..cf0baa5 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c @@ -4,10 +4,12 @@ */ /* { dg-options "-g" } */ +#define INCLUDE_MEMORY #include "gcc-plugin.h" #include "config.h" #include "system.h" #include "coretypes.h" +#include "make-unique.h" #include "diagnostic.h" #include "tree.h" #include "gimple.h" @@ -309,9 +311,9 @@ gil_state_machine::check_for_pyobject_in_call (sm_context *sm_ctxt, if (type_based_on_pyobject_p (type)) { sm_ctxt->warn (node, call, NULL_TREE, - new fncall_without_gil (*this, call, - callee_fndecl, - i)); + make_unique (*this, call, + callee_fndecl, + i)); sm_ctxt->set_global_state (m_stop); } } @@ -337,7 +339,7 @@ gil_state_machine::on_stmt (sm_context *sm_ctxt, if (global_state == m_released_gil) { sm_ctxt->warn (node, stmt, NULL_TREE, - new double_save_thread (*this, call)); + make_unique (*this, call)); sm_ctxt->set_global_state (m_stop); } else @@ -393,7 +395,7 @@ gil_state_machine::check_for_pyobject_usage_without_gil (sm_context *sm_ctxt, if (type_based_on_pyobject_p (type)) { sm_ctxt->warn (node, stmt, NULL_TREE, - new pyobject_usage_without_gil (*this, op)); + make_unique (*this, op)); sm_ctxt->set_global_state (m_stop); } } diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c index 6ec08bf..d1c2913 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c @@ -1,6 +1,7 @@ /* Proof-of-concept of a -fanalyzer plugin for the Linux kernel. */ /* { dg-options "-g" } */ +#define INCLUDE_MEMORY #include "gcc-plugin.h" #include "config.h" #include "system.h" diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c index 060a308..ccf69ed 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c @@ -1,6 +1,7 @@ /* Proof-of-concept of a -fanalyzer plugin to handle known functions. */ /* { dg-options "-g" } */ +#define INCLUDE_MEMORY #include "gcc-plugin.h" #include "config.h" #include "system.h" -- cgit v1.1 From 2a9b395b1e4542c79b250b756346816a9b72d859 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 13:47:01 -0400 Subject: analyzer: use std::unique_ptr for saved_diagnostic::m_stmt_finder gcc/analyzer/ChangeLog: * diagnostic-manager.cc (saved_diagnostic::saved_diagnostic): Make stmt_finder const. (saved_diagnostic::~saved_diagnostic): Remove explicit delete of m_stmt_finder. (diagnostic_manager::add_diagnostic): Make stmt_finder const. * diagnostic-manager.h (saved_diagnostic::saved_diagnostic): Likewise. (saved_diagnostic::m_stmt_finder): Convert to std::unique_ptr. (diagnostic_manager::add_diagnostic): Make stmt_finder const. * engine.cc (impl_sm_context::impl_sm_context): Likewise. (impl_sm_context::m_stmt_finder): Likewise. (leak_stmt_finder::clone): Convert return type to std::unique_ptr. * exploded-graph.h (stmt_finder::clone): Likewise. Signed-off-by: David Malcolm --- gcc/analyzer/diagnostic-manager.cc | 7 +++---- gcc/analyzer/diagnostic-manager.h | 8 ++++---- gcc/analyzer/engine.cc | 8 ++++---- gcc/analyzer/exploded-graph.h | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 0444e52..bb8584a 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -635,7 +635,7 @@ epath_finder::dump_feasible_path (const exploded_node *target_enode, saved_diagnostic::saved_diagnostic (const state_machine *sm, const exploded_node *enode, const supernode *snode, const gimple *stmt, - stmt_finder *stmt_finder, + const stmt_finder *stmt_finder, tree var, const svalue *sval, state_machine::state_t state, @@ -662,7 +662,6 @@ saved_diagnostic::saved_diagnostic (const state_machine *sm, saved_diagnostic::~saved_diagnostic () { - delete m_stmt_finder; delete m_best_epath; delete m_problem; } @@ -961,7 +960,7 @@ bool diagnostic_manager::add_diagnostic (const state_machine *sm, exploded_node *enode, const supernode *snode, const gimple *stmt, - stmt_finder *finder, + const stmt_finder *finder, tree var, const svalue *sval, state_machine::state_t state, @@ -1010,7 +1009,7 @@ diagnostic_manager::add_diagnostic (const state_machine *sm, bool diagnostic_manager::add_diagnostic (exploded_node *enode, const supernode *snode, const gimple *stmt, - stmt_finder *finder, + const stmt_finder *finder, std::unique_ptr d) { gcc_assert (enode); diff --git a/gcc/analyzer/diagnostic-manager.h b/gcc/analyzer/diagnostic-manager.h index fdab038..c87f215 100644 --- a/gcc/analyzer/diagnostic-manager.h +++ b/gcc/analyzer/diagnostic-manager.h @@ -33,7 +33,7 @@ public: saved_diagnostic (const state_machine *sm, const exploded_node *enode, const supernode *snode, const gimple *stmt, - stmt_finder *stmt_finder, + const stmt_finder *stmt_finder, tree var, const svalue *sval, state_machine::state_t state, std::unique_ptr d, @@ -72,7 +72,7 @@ public: const exploded_node *m_enode; const supernode *m_snode; const gimple *m_stmt; - stmt_finder *m_stmt_finder; + std::unique_ptr m_stmt_finder; tree m_var; const svalue *m_sval; state_machine::state_t m_state; @@ -113,7 +113,7 @@ public: bool add_diagnostic (const state_machine *sm, exploded_node *enode, const supernode *snode, const gimple *stmt, - stmt_finder *finder, + const stmt_finder *finder, tree var, const svalue *sval, state_machine::state_t state, @@ -121,7 +121,7 @@ public: bool add_diagnostic (exploded_node *enode, const supernode *snode, const gimple *stmt, - stmt_finder *finder, + const stmt_finder *finder, std::unique_ptr d); void add_note (std::unique_ptr pn); diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index fd532b1..553957a 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -282,7 +282,7 @@ public: const sm_state_map *old_smap, sm_state_map *new_smap, path_context *path_ctxt, - stmt_finder *stmt_finder = NULL, + const stmt_finder *stmt_finder = NULL, bool unknown_side_effects = false) : sm_context (sm_idx, sm), m_logger (eg.get_logger ()), @@ -523,7 +523,7 @@ public: const sm_state_map *m_old_smap; sm_state_map *m_new_smap; path_context *m_path_ctxt; - stmt_finder *m_stmt_finder; + const stmt_finder *m_stmt_finder; /* Are we handling an external function with unknown side effects? */ bool m_unknown_side_effects; @@ -538,9 +538,9 @@ public: leak_stmt_finder (const exploded_graph &eg, tree var) : m_eg (eg), m_var (var) {} - stmt_finder *clone () const final override + std::unique_ptr clone () const final override { - return new leak_stmt_finder (m_eg, m_var); + return make_unique (m_eg, m_var); } const gimple *find_stmt (const exploded_path &epath) diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index dae73da..7947f50 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -991,7 +991,7 @@ class stmt_finder { public: virtual ~stmt_finder () {} - virtual stmt_finder *clone () const = 0; + virtual std::unique_ptr clone () const = 0; virtual const gimple *find_stmt (const exploded_path &epath) = 0; }; -- cgit v1.1 From ca5ff10546e612eff3d5e225b62b44ddf656cfbf Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 13:47:01 -0400 Subject: analyzer: use std::unique_ptr for custom_edge_info pointers gcc/analyzer/ChangeLog: * checker-path.cc (rewind_event::rewind_event): Update for usage of std::unique_ptr on custom_edge_info. * engine.cc (exploded_node::on_longjmp): Likewise. (exploded_edge::exploded_edge): Likewise. (exploded_edge::~exploded_edge): Delete. (exploded_graph::add_function_entry): Update for usage of std::unique_ptr on custom_edge_info. (exploded_graph::add_edge): Likewise. (add_tainted_args_callback): Likewise. (exploded_graph::maybe_create_dynamic_call): Likewise. (exploded_graph::process_node): Likewise. * exploded-graph.h (exploded_edge::~exploded_edge): Delete. (exploded_edge::m_custom_info): Use std::unique_ptr. (exploded_edge::add_edge): Likewise. * sm-signal.cc (register_signal_handler::impl_transition): Use make_unique. Signed-off-by: David Malcolm --- gcc/analyzer/checker-path.cc | 2 +- gcc/analyzer/engine.cc | 52 ++++++++++++++++--------------------------- gcc/analyzer/exploded-graph.h | 11 ++++----- gcc/analyzer/sm-signal.cc | 2 +- 4 files changed, 25 insertions(+), 42 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc index 4cf28c2..49940ce 100644 --- a/gcc/analyzer/checker-path.cc +++ b/gcc/analyzer/checker-path.cc @@ -1037,7 +1037,7 @@ rewind_event::rewind_event (const exploded_edge *eedge, m_rewind_info (rewind_info), m_eedge (eedge) { - gcc_assert (m_eedge->m_custom_info == m_rewind_info); + gcc_assert (m_eedge->m_custom_info.get () == m_rewind_info); } /* class rewind_from_longjmp_event : public rewind_event. */ diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 553957a..c7bc63e 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1878,7 +1878,7 @@ exploded_node::on_longjmp (exploded_graph &eg, { exploded_edge *eedge = eg.add_edge (const_cast (this), next, NULL, - new rewind_info_t (tmp_setjmp_record, longjmp_call)); + make_unique (tmp_setjmp_record, longjmp_call)); /* For any diagnostics that were queued here (such as leaks) we want the checker_path to show the rewinding events after the "final event" @@ -2089,19 +2089,12 @@ rewind_info_t::add_events_to_path (checker_path *emission_path, exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest, const superedge *sedge, - custom_edge_info *custom_info) + std::unique_ptr custom_info) : dedge (src, dest), m_sedge (sedge), - m_custom_info (custom_info) + m_custom_info (std::move (custom_info)) { } -/* exploded_edge's dtor. */ - -exploded_edge::~exploded_edge () -{ - delete m_custom_info; -} - /* Implementation of dedge::dump_dot vfunc for exploded_edge. Use the label of the underlying superedge, if any. */ @@ -2709,12 +2702,12 @@ exploded_graph::add_function_entry (function *fun) program_state state (m_ext_state); state.push_frame (m_ext_state, fun); - custom_edge_info *edge_info = NULL; + std::unique_ptr edge_info = NULL; if (lookup_attribute ("tainted_args", DECL_ATTRIBUTES (fun->decl))) { if (mark_params_as_tainted (&state, fun->decl, m_ext_state)) - edge_info = new tainted_args_function_info (fun->decl); + edge_info = make_unique (fun->decl); } if (!state.m_valid) @@ -2722,12 +2715,9 @@ exploded_graph::add_function_entry (function *fun) exploded_node *enode = get_or_create_node (point, state, NULL); if (!enode) - { - delete edge_info; - return NULL; - } + return NULL; - add_edge (m_origin, enode, NULL, edge_info); + add_edge (m_origin, enode, NULL, std::move (edge_info)); m_functions_with_enodes.add (fun); @@ -2925,18 +2915,19 @@ exploded_graph::get_or_create_node (const program_point &point, /* Add an exploded_edge from SRC to DEST, recording its association with SEDGE (which may be NULL), and, if non-NULL, taking ownership - of REWIND_INFO. + of CUSTOM_INFO. Return the newly-created eedge. */ exploded_edge * exploded_graph::add_edge (exploded_node *src, exploded_node *dest, const superedge *sedge, - custom_edge_info *custom_info) + std::unique_ptr custom_info) { if (get_logger ()) get_logger ()->log ("creating edge EN: %i -> EN: %i", src->m_index, dest->m_index); - exploded_edge *e = new exploded_edge (src, dest, sedge, custom_info); + exploded_edge *e = new exploded_edge (src, dest, sedge, + std::move (custom_info)); digraph::add_edge (e); return e; } @@ -3183,9 +3174,8 @@ add_tainted_args_callback (exploded_graph *eg, tree field, tree fndecl, } } - tainted_args_call_info *info - = new tainted_args_call_info (field, fndecl, loc); - eg->add_edge (eg->get_origin (), enode, NULL, info); + eg->add_edge (eg->get_origin (), enode, NULL, + make_unique (field, fndecl, loc)); } /* Callback for walk_tree for finding callbacks within initializers; @@ -3782,7 +3772,7 @@ exploded_graph::maybe_create_dynamic_call (const gcall *call, node); if (enode) add_edge (node,enode, NULL, - new dynamic_call_info_t (call)); + make_unique (call)); return true; } } @@ -4108,8 +4098,10 @@ exploded_graph::process_node (exploded_node *node) instances. For example, to handle a "realloc" call, we might split into 3 states, for the "failure", "resizing in place", and "moving to a new buffer" cases. */ - for (auto edge_info : path_ctxt.get_custom_eedge_infos ()) + for (auto edge_info_iter : path_ctxt.get_custom_eedge_infos ()) { + /* Take ownership of the edge infos from the path_ctxt. */ + std::unique_ptr edge_info (edge_info_iter); if (logger) { logger->start_log_line (); @@ -4136,18 +4128,12 @@ exploded_graph::process_node (exploded_node *node) exploded_node *next2 = get_or_create_node (next_point, bifurcated_new_state, node); if (next2) - { - /* Take ownership of edge_info. */ - add_edge (node, next2, NULL, edge_info); - } - else - delete edge_info; + add_edge (node, next2, NULL, std::move (edge_info)); } else { if (logger) logger->log ("infeasible state, not adding node"); - delete edge_info; } } } @@ -4303,7 +4289,7 @@ exploded_graph::process_node (exploded_node *node) node); if (enode) add_edge (node, enode, NULL, - new dynamic_call_info_t (call, true)); + make_unique (call, true)); } } } diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index 7947f50..27e6881 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -367,8 +367,7 @@ class exploded_edge : public dedge public: exploded_edge (exploded_node *src, exploded_node *dest, const superedge *sedge, - custom_edge_info *custom_info); - ~exploded_edge (); + std::unique_ptr custom_info); void dump_dot (graphviz_out *gv, const dump_args_t &args) const final override; void dump_dot_label (pretty_printer *pp) const; @@ -380,10 +379,8 @@ class exploded_edge : public dedge /* NULL for most edges; will be non-NULL for special cases such as an unwind from a longjmp to a setjmp, or when - a signal is delivered to a signal-handler. - - Owned by this class. */ - custom_edge_info *m_custom_info; + a signal is delivered to a signal-handler. */ + std::unique_ptr m_custom_info; private: DISABLE_COPY_AND_ASSIGN (exploded_edge); @@ -801,7 +798,7 @@ public: exploded_node *enode_for_diag); exploded_edge *add_edge (exploded_node *src, exploded_node *dest, const superedge *sedge, - custom_edge_info *custom = NULL); + std::unique_ptr custom = NULL); per_program_point_data * get_or_create_per_program_point_data (const program_point &); diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index 737ec4a..08476b6 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -279,7 +279,7 @@ public: src_enode); if (dst_enode) eg->add_edge (src_enode, dst_enode, NULL, /*state_change (),*/ - new signal_delivery_edge_info_t ()); + make_unique ()); } const signal_state_machine &m_sm; -- cgit v1.1 From e031c5a17a33f19ccae1e0e7972c97d2b2eb8250 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 13:47:01 -0400 Subject: analyzer: use std::unique_ptr for feasibility_problems and exploded_path gcc/analyzer/ChangeLog: * diagnostic-manager.cc: Include "make-unique.h". Use std::unique_ptr for feasibility_problems and exploded_path. Delete explicit saved_diagnostic dtor. * diagnostic-manager.h: Likewise. * engine.cc: Likewise. * exploded-graph.h: Likewise. * feasible-graph.cc: Likewise. * feasible-graph.h: Likewise. Signed-off-by: David Malcolm --- gcc/analyzer/diagnostic-manager.cc | 64 ++++++++++++++++++-------------------- gcc/analyzer/diagnostic-manager.h | 9 +++--- gcc/analyzer/engine.cc | 9 +++--- gcc/analyzer/exploded-graph.h | 2 +- gcc/analyzer/feasible-graph.cc | 4 +-- gcc/analyzer/feasible-graph.h | 2 +- 6 files changed, 43 insertions(+), 47 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index bb8584a..0a8a2e8 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/feasible-graph.h" #include "analyzer/checker-path.h" #include "analyzer/reachability.h" +#include "make-unique.h" #if ENABLE_ANALYZER @@ -85,21 +86,24 @@ public: logger *get_logger () const { return m_eg.get_logger (); } - exploded_path *get_best_epath (const exploded_node *target_enode, - const char *desc, unsigned diag_idx, - feasibility_problem **out_problem); + std::unique_ptr + get_best_epath (const exploded_node *target_enode, + const char *desc, unsigned diag_idx, + std::unique_ptr *out_problem); private: DISABLE_COPY_AND_ASSIGN(epath_finder); - exploded_path *explore_feasible_paths (const exploded_node *target_enode, - const char *desc, unsigned diag_idx); - bool process_worklist_item (feasible_worklist *worklist, - const trimmed_graph &tg, - feasible_graph *fg, - const exploded_node *target_enode, - unsigned diag_idx, - exploded_path **out_best_path) const; + std::unique_ptr + explore_feasible_paths (const exploded_node *target_enode, + const char *desc, unsigned diag_idx); + bool + process_worklist_item (feasible_worklist *worklist, + const trimmed_graph &tg, + feasible_graph *fg, + const exploded_node *target_enode, + unsigned diag_idx, + std::unique_ptr *out_best_path) const; void dump_trimmed_graph (const exploded_node *target_enode, const char *desc, unsigned diag_idx, const trimmed_graph &tg, @@ -132,10 +136,10 @@ private: Write any feasibility_problem to *OUT_PROBLEM. */ -exploded_path * +std::unique_ptr epath_finder::get_best_epath (const exploded_node *enode, const char *desc, unsigned diag_idx, - feasibility_problem **out_problem) + std::unique_ptr *out_problem) { logger *logger = get_logger (); LOG_SCOPE (logger); @@ -156,7 +160,8 @@ epath_finder::get_best_epath (const exploded_node *enode, /* Attempt to find the shortest feasible path using feasible_graph. */ if (logger) logger->log ("trying to find shortest feasible path"); - if (exploded_path *epath = explore_feasible_paths (enode, desc, diag_idx)) + if (std::unique_ptr epath + = explore_feasible_paths (enode, desc, diag_idx)) { if (logger) logger->log ("accepting %qs at EN: %i, SN: %i (sd: %i)" @@ -184,8 +189,8 @@ epath_finder::get_best_epath (const exploded_node *enode, if (logger) logger->log ("trying to find shortest path ignoring feasibility"); gcc_assert (m_sep); - exploded_path *epath - = new exploded_path (m_sep->get_shortest_path (enode)); + std::unique_ptr epath + = make_unique (m_sep->get_shortest_path (enode)); if (epath->feasible_p (logger, out_problem, m_eg.get_engine (), &m_eg)) { if (logger) @@ -367,7 +372,7 @@ private: continue forever without reaching the target), or - getting monotonically closer to the termination threshold. */ -exploded_path * +std::unique_ptr epath_finder::explore_feasible_paths (const exploded_node *target_enode, const char *desc, unsigned diag_idx) { @@ -405,7 +410,7 @@ epath_finder::explore_feasible_paths (const exploded_node *target_enode, a limit. */ /* Set this if we find a feasible path to TARGET_ENODE. */ - exploded_path *best_path = NULL; + std::unique_ptr best_path = NULL; { auto_checking_feasibility sentinel (mgr); @@ -447,12 +452,13 @@ epath_finder::explore_feasible_paths (const exploded_node *target_enode, to TARGET_ENODE. */ bool -epath_finder::process_worklist_item (feasible_worklist *worklist, - const trimmed_graph &tg, - feasible_graph *fg, - const exploded_node *target_enode, - unsigned diag_idx, - exploded_path **out_best_path) const +epath_finder:: +process_worklist_item (feasible_worklist *worklist, + const trimmed_graph &tg, + feasible_graph *fg, + const exploded_node *target_enode, + unsigned diag_idx, + std::unique_ptr *out_best_path) const { logger *logger = get_logger (); @@ -658,14 +664,6 @@ saved_diagnostic::saved_diagnostic (const state_machine *sm, gcc_assert (m_enode); } -/* saved_diagnostic's dtor. */ - -saved_diagnostic::~saved_diagnostic () -{ - delete m_best_epath; - delete m_problem; -} - bool saved_diagnostic::operator== (const saved_diagnostic &other) const { @@ -808,8 +806,6 @@ saved_diagnostic::calc_best_epath (epath_finder *pf) { logger *logger = pf->get_logger (); LOG_SCOPE (logger); - delete m_best_epath; - delete m_problem; m_problem = NULL; m_best_epath = pf->get_best_epath (m_enode, m_d->get_kind (), m_idx, diff --git a/gcc/analyzer/diagnostic-manager.h b/gcc/analyzer/diagnostic-manager.h index c87f215..4862cf4 100644 --- a/gcc/analyzer/diagnostic-manager.h +++ b/gcc/analyzer/diagnostic-manager.h @@ -38,7 +38,6 @@ public: state_machine::state_t state, std::unique_ptr d, unsigned idx); - ~saved_diagnostic (); bool operator== (const saved_diagnostic &other) const; @@ -51,11 +50,11 @@ public: const feasibility_problem *get_feasibility_problem () const { - return m_problem; + return m_problem.get (); } bool calc_best_epath (epath_finder *pf); - const exploded_path *get_best_epath () const { return m_best_epath; } + const exploded_path *get_best_epath () const { return m_best_epath.get (); } unsigned get_epath_length () const; void add_duplicate (saved_diagnostic *other); @@ -83,8 +82,8 @@ private: DISABLE_COPY_AND_ASSIGN (saved_diagnostic); unsigned m_idx; - exploded_path *m_best_epath; // owned - feasibility_problem *m_problem; // owned + std::unique_ptr m_best_epath; + std::unique_ptr m_problem; auto_vec m_duplicates; auto_delete_vec m_notes; diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index c7bc63e..a727553 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -4599,8 +4599,9 @@ exploded_path::get_final_enode () const feasibility_problem to *OUT. */ bool -exploded_path::feasible_p (logger *logger, feasibility_problem **out, - engine *eng, const exploded_graph *eg) const +exploded_path::feasible_p (logger *logger, + std::unique_ptr *out, + engine *eng, const exploded_graph *eg) const { LOG_SCOPE (logger); @@ -4627,8 +4628,8 @@ exploded_path::feasible_p (logger *logger, feasibility_problem **out, const program_point &src_point = src_enode.get_point (); const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt (); - *out = new feasibility_problem (edge_idx, *eedge, - last_stmt, rc); + *out = make_unique (edge_idx, *eedge, + last_stmt, rc); } else delete rc; diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index 27e6881..6a25003 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -923,7 +923,7 @@ public: void dump_to_file (const char *filename, const extrinsic_state &ext_state) const; - bool feasible_p (logger *logger, feasibility_problem **out, + bool feasible_p (logger *logger, std::unique_ptr *out, engine *eng, const exploded_graph *eg) const; auto_vec m_edges; diff --git a/gcc/analyzer/feasible-graph.cc b/gcc/analyzer/feasible-graph.cc index c5b0d62..7c3dcf8 100644 --- a/gcc/analyzer/feasible-graph.cc +++ b/gcc/analyzer/feasible-graph.cc @@ -190,10 +190,10 @@ feasible_graph::add_feasibility_problem (feasible_node *src_fnode, /* Make an exploded_path from the origin to FNODE's exploded_node, following the edges in the feasible_graph. */ -exploded_path * +std::unique_ptr feasible_graph::make_epath (feasible_node *fnode) const { - exploded_path *epath = new exploded_path (); + std::unique_ptr epath (new exploded_path ()); /* FG is actually a tree. Built the path backwards, by walking backwards from FNODE until we reach the origin. */ diff --git a/gcc/analyzer/feasible-graph.h b/gcc/analyzer/feasible-graph.h index 2530119..9f37b08 100644 --- a/gcc/analyzer/feasible-graph.h +++ b/gcc/analyzer/feasible-graph.h @@ -195,7 +195,7 @@ class feasible_graph : public digraph const exploded_edge *eedge, rejected_constraint *rc); - exploded_path *make_epath (feasible_node *fnode) const; + std::unique_ptr make_epath (feasible_node *fnode) const; void dump_feasible_path (const feasible_node &dst_fnode, const char *filename) const; -- cgit v1.1 From d60b40b86b166fbdb68523c4164c0003c8244192 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 13:47:02 -0400 Subject: analyzer: use std::unique_ptr for checker_event gcc/analyzer/ChangeLog: * call-info.cc: Use std::unique_ptr for checker_event. * checker-path.cc: Likewise. * checker-path.h: Likewise. * diagnostic-manager.cc: Likewise. * engine.cc: Likewise. * pending-diagnostic.cc: Likewise. * sm-signal.cc: Likewise. * varargs.cc: Likewise. Signed-off-by: David Malcolm --- gcc/analyzer/call-info.cc | 9 ++- gcc/analyzer/checker-path.cc | 25 ++++--- gcc/analyzer/checker-path.h | 4 +- gcc/analyzer/diagnostic-manager.cc | 146 +++++++++++++++++++------------------ gcc/analyzer/engine.cc | 40 +++++----- gcc/analyzer/pending-diagnostic.cc | 13 ++-- gcc/analyzer/sm-signal.cc | 2 +- gcc/analyzer/varargs.cc | 14 ++-- 8 files changed, 133 insertions(+), 120 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/call-info.cc b/gcc/analyzer/call-info.cc index 3572e06..ffdab73 100644 --- a/gcc/analyzer/call-info.cc +++ b/gcc/analyzer/call-info.cc @@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/diagnostic-manager.h" #include "analyzer/exploded-graph.h" #include "analyzer/call-info.h" +#include "make-unique.h" #if ENABLE_ANALYZER @@ -113,10 +114,10 @@ call_info::add_events_to_path (checker_path *emission_path, tree caller_fndecl = src_point.get_fndecl (); const int stack_depth = src_point.get_stack_depth (); - emission_path->add_event (new call_event (get_call_stmt ()->location, - caller_fndecl, - stack_depth, - this)); + emission_path->add_event (make_unique (get_call_stmt ()->location, + caller_fndecl, + stack_depth, + this)); } /* Recreate a call_details instance from this call_info. */ diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc index 49940ce..40f9ccfe 100644 --- a/gcc/analyzer/checker-path.cc +++ b/gcc/analyzer/checker-path.cc @@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/diagnostic-manager.h" #include "analyzer/checker-path.h" #include "analyzer/exploded-graph.h" +#include "make-unique.h" #if ENABLE_ANALYZER @@ -1262,16 +1263,16 @@ checker_path::add_region_creation_events (const region *reg, if (const svalue *capacity_sval = model->get_capacity (reg)) capacity = model->get_representative_tree (capacity_sval); - add_event (new region_creation_event (reg, capacity, RCE_MEM_SPACE, - loc, fndecl, depth)); + add_event (make_unique (reg, capacity, RCE_MEM_SPACE, + loc, fndecl, depth)); if (capacity) - add_event (new region_creation_event (reg, capacity, RCE_CAPACITY, - loc, fndecl, depth)); + add_event (make_unique (reg, capacity, RCE_CAPACITY, + loc, fndecl, depth)); if (debug) - add_event (new region_creation_event (reg, capacity, RCE_DEBUG, - loc, fndecl, depth)); + add_event (make_unique (reg, capacity, RCE_DEBUG, + loc, fndecl, depth)); } /* Add a warning_event to the end of this path. */ @@ -1281,12 +1282,12 @@ checker_path::add_final_event (const state_machine *sm, const exploded_node *enode, const gimple *stmt, tree var, state_machine::state_t state) { - checker_event *end_of_path - = new warning_event (get_stmt_location (stmt, enode->get_function ()), - enode->get_function ()->decl, - enode->get_stack_depth (), - sm, var, state); - add_event (end_of_path); + add_event + (make_unique (get_stmt_location (stmt, + enode->get_function ()), + enode->get_function ()->decl, + enode->get_stack_depth (), + sm, var, state)); } void diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h index 5d00934..c8de5c9 100644 --- a/gcc/analyzer/checker-path.h +++ b/gcc/analyzer/checker-path.h @@ -631,9 +631,9 @@ public: void maybe_log (logger *logger, const char *desc) const; - void add_event (checker_event *event) + void add_event (std::unique_ptr event) { - m_events.safe_push (event); + m_events.safe_push (event.release ()); } void delete_event (int idx) diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 0a8a2e8..e775475 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -1559,15 +1559,16 @@ public: int stack_depth = src_stack_depth; - m_emission_path->add_event (new state_change_event (supernode, - stmt, - stack_depth, - sm, - NULL, - src_sm_val, - dst_sm_val, - NULL, - dst_state)); + m_emission_path->add_event + (make_unique (supernode, + stmt, + stack_depth, + sm, + NULL, + src_sm_val, + dst_sm_val, + NULL, + dst_state)); return false; } @@ -1602,15 +1603,16 @@ public: if (!stmt) return false; - m_emission_path->add_event (new state_change_event (supernode, - stmt, - stack_depth, - sm, - sval, - src_sm_val, - dst_sm_val, - dst_origin_sval, - dst_state)); + m_emission_path->add_event + (make_unique (supernode, + stmt, + stack_depth, + sm, + sval, + src_sm_val, + dst_sm_val, + dst_origin_sval, + dst_state)); return false; } @@ -1743,14 +1745,15 @@ struct null_assignment_sm_context : public sm_context const supernode *supernode = m_point->get_supernode (); int stack_depth = m_point->get_stack_depth (); - m_emission_path->add_event (new state_change_event (supernode, - m_stmt, - stack_depth, - m_sm, - var_new_sval, - from, to, - NULL, - *m_new_state)); + m_emission_path->add_event + (make_unique (supernode, + m_stmt, + stack_depth, + m_sm, + var_new_sval, + from, to, + NULL, + *m_new_state)); } void set_next_state (const gimple *stmt, @@ -1765,14 +1768,15 @@ struct null_assignment_sm_context : public sm_context const supernode *supernode = m_point->get_supernode (); int stack_depth = m_point->get_stack_depth (); - m_emission_path->add_event (new state_change_event (supernode, - m_stmt, - stack_depth, - m_sm, - sval, - from, to, - NULL, - *m_new_state)); + m_emission_path->add_event + (make_unique (supernode, + m_stmt, + stack_depth, + m_sm, + sval, + from, to, + NULL, + *m_new_state)); } void warn (const supernode *, const gimple *, @@ -1907,7 +1911,7 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb, if (dst_point.get_supernode ()->entry_p ()) { emission_path->add_event - (new function_entry_event + (make_unique (dst_point.get_supernode ()->get_start_location (), dst_point.get_fndecl (), dst_stack_depth)); @@ -1943,16 +1947,16 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb, const gcall *call = dyn_cast (stmt); if (call && is_setjmp_call_p (call)) emission_path->add_event - (new setjmp_event (stmt->location, - dst_node, - dst_point.get_fndecl (), - dst_stack_depth, - call)); + (make_unique (stmt->location, + dst_node, + dst_point.get_fndecl (), + dst_stack_depth, + call)); else emission_path->add_event - (new statement_event (stmt, - dst_point.get_fndecl (), - dst_stack_depth, dst_state)); + (make_unique (stmt, + dst_point.get_fndecl (), + dst_stack_depth, dst_state)); /* Create state change events for assignment to NULL. Iterate through the stmts in dst_enode, adding state change @@ -2042,11 +2046,12 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb, "this path would have been rejected as infeasible" " at this edge: "); pb.get_feasibility_problem ()->dump_to_pp (&pp); - emission_path->add_event (new precanned_custom_event - (dst_point.get_location (), - dst_point.get_fndecl (), - dst_stack_depth, - pp_formatted_text (&pp))); + emission_path->add_event + (make_unique + (dst_point.get_location (), + dst_point.get_fndecl (), + dst_stack_depth, + pp_formatted_text (&pp))); } } @@ -2157,17 +2162,18 @@ diagnostic_manager::add_events_for_superedge (const path_builder &pb, case SUPEREDGE_CFG_EDGE: { emission_path->add_event - (new start_cfg_edge_event (eedge, - (last_stmt - ? last_stmt->location - : UNKNOWN_LOCATION), - src_point.get_fndecl (), - src_stack_depth)); + (make_unique (eedge, + (last_stmt + ? last_stmt->location + : UNKNOWN_LOCATION), + src_point.get_fndecl (), + src_stack_depth)); emission_path->add_event - (new end_cfg_edge_event (eedge, - dst_point.get_supernode ()->get_start_location (), - dst_point.get_fndecl (), - dst_stack_depth)); + (make_unique + (eedge, + dst_point.get_supernode ()->get_start_location (), + dst_point.get_fndecl (), + dst_stack_depth)); } break; @@ -2180,12 +2186,12 @@ diagnostic_manager::add_events_for_superedge (const path_builder &pb, /* TODO: add a subclass for this, or generate events for the summary. */ emission_path->add_event - (new debug_event ((last_stmt - ? last_stmt->location - : UNKNOWN_LOCATION), - src_point.get_fndecl (), - src_stack_depth, - "call summary")); + (make_unique ((last_stmt + ? last_stmt->location + : UNKNOWN_LOCATION), + src_point.get_fndecl (), + src_stack_depth, + "call summary")); } break; @@ -2196,12 +2202,12 @@ diagnostic_manager::add_events_for_superedge (const path_builder &pb, const gcall *call_stmt = return_edge->get_call_stmt (); emission_path->add_event - (new return_event (eedge, - (call_stmt - ? call_stmt->location - : UNKNOWN_LOCATION), - dst_point.get_fndecl (), - dst_stack_depth)); + (make_unique (eedge, + (call_stmt + ? call_stmt->location + : UNKNOWN_LOCATION), + dst_point.get_fndecl (), + dst_stack_depth)); } break; } diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index a727553..59a4e6f 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1772,7 +1772,8 @@ public: src_point.get_fndecl (), src_stack_depth, "stack frame is popped here, invalidating saved environment"); - emission_path->add_event (m_stack_pop_event); + emission_path->add_event + (std::unique_ptr (m_stack_pop_event)); return false; } return false; @@ -2015,19 +2016,21 @@ dynamic_call_info_t::add_events_to_path (checker_path *emission_path, const int dest_stack_depth = dest_point.get_stack_depth (); if (m_is_returning_call) - emission_path->add_event (new return_event (eedge, - (m_dynamic_call - ? m_dynamic_call->location - : UNKNOWN_LOCATION), - dest_point.get_fndecl (), - dest_stack_depth)); + emission_path->add_event + (make_unique (eedge, + (m_dynamic_call + ? m_dynamic_call->location + : UNKNOWN_LOCATION), + dest_point.get_fndecl (), + dest_stack_depth)); else - emission_path->add_event (new call_event (eedge, - (m_dynamic_call - ? m_dynamic_call->location - : UNKNOWN_LOCATION), - src_point.get_fndecl (), - src_stack_depth)); + emission_path->add_event + (make_unique (eedge, + (m_dynamic_call + ? m_dynamic_call->location + : UNKNOWN_LOCATION), + src_point.get_fndecl (), + src_stack_depth)); } /* class rewind_info_t : public custom_edge_info. */ @@ -2072,12 +2075,12 @@ rewind_info_t::add_events_to_path (checker_path *emission_path, const int dst_stack_depth = dst_point.get_stack_depth (); emission_path->add_event - (new rewind_from_longjmp_event + (make_unique (&eedge, get_longjmp_call ()->location, src_point.get_fndecl (), src_stack_depth, this)); emission_path->add_event - (new rewind_to_setjmp_event + (make_unique (&eedge, get_setjmp_call ()->location, dst_point.get_fndecl (), dst_stack_depth, this)); @@ -2666,7 +2669,7 @@ public: const exploded_edge &) const final override { emission_path->add_event - (new tainted_args_function_custom_event + (make_unique (DECL_SOURCE_LOCATION (m_fndecl), m_fndecl, 0)); } @@ -3111,14 +3114,15 @@ public: /* Show the field in the struct declaration, e.g. "(1) field 'store' is marked with '__attribute__((tainted_args))'" */ emission_path->add_event - (new tainted_args_field_custom_event (m_field)); + (make_unique (m_field)); /* Show the callback in the initializer e.g. "(2) function 'gadget_dev_desc_UDC_store' used as initializer for field 'store' marked with '__attribute__((tainted_args))'". */ emission_path->add_event - (new tainted_args_callback_custom_event (m_loc, m_fndecl, 0, m_field)); + (make_unique (m_loc, m_fndecl, + 0, m_field)); } private: diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc index a21c86f..fdbe615 100644 --- a/gcc/analyzer/pending-diagnostic.cc +++ b/gcc/analyzer/pending-diagnostic.cc @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/exploded-graph.h" #include "diagnostic-path.h" #include "analyzer/checker-path.h" +#include "make-unique.h" #if ENABLE_ANALYZER @@ -178,12 +179,12 @@ pending_diagnostic::add_call_event (const exploded_edge &eedge, const int src_stack_depth = src_point.get_stack_depth (); const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt (); emission_path->add_event - (new call_event (eedge, - (last_stmt - ? last_stmt->location - : UNKNOWN_LOCATION), - src_point.get_fndecl (), - src_stack_depth)); + (make_unique (eedge, + (last_stmt + ? last_stmt->location + : UNKNOWN_LOCATION), + src_point.get_fndecl (), + src_stack_depth)); } } // namespace ana diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index 08476b6..87e21a4 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -234,7 +234,7 @@ public: const final override { emission_path->add_event - (new precanned_custom_event + (make_unique (UNKNOWN_LOCATION, NULL_TREE, 0, "later on," " when the signal is delivered to the process")); diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc index 8b1d809..f7d4838 100644 --- a/gcc/analyzer/varargs.cc +++ b/gcc/analyzer/varargs.cc @@ -788,13 +788,13 @@ public: = get_num_variadic_arguments (dst_node->get_function ()->decl, call_stmt); emission_path->add_event - (new va_arg_call_event (eedge, - (last_stmt - ? last_stmt->location - : UNKNOWN_LOCATION), - src_point.get_fndecl (), - src_stack_depth, - num_variadic_arguments)); + (make_unique (eedge, + (last_stmt + ? last_stmt->location + : UNKNOWN_LOCATION), + src_point.get_fndecl (), + src_stack_depth, + num_variadic_arguments)); } else pending_diagnostic::add_call_event (eedge, emission_path); -- cgit v1.1 From accece8c9543e4f3f7bbf24989755dd0453658b7 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 13:47:02 -0400 Subject: analyzer: use std::unique_ptr during bifurcation gcc/analyzer/ChangeLog: * analysis-plan.cc: Define INCLUDE_MEMORY before including system.h. * analyzer-pass.cc: Likewise. * analyzer-selftests.cc: Likewise. * analyzer.cc: Likewise. * analyzer.h: Use std::unique_ptr in bifurcation code. * call-string.cc: Define INCLUDE_MEMORY before including system.h. * complexity.cc: Likewise. * engine.cc: Use std::unique_ptr in bifurcation code. * exploded-graph.h: Likewise. * known-function-manager.cc: Define INCLUDE_MEMORY before including system.h. * region-model-impl-calls.cc: Use std::unique_ptr in bifurcation code. * region-model.cc: Likewise. * region-model.h: Likewise. * supergraph.cc: Define INCLUDE_MEMORY before including system.h. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c: Include "make-unique.h". Use std::unique_ptr in bifurcation code. * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm --- gcc/analyzer/analysis-plan.cc | 1 + gcc/analyzer/analyzer-pass.cc | 1 + gcc/analyzer/analyzer-selftests.cc | 1 + gcc/analyzer/analyzer.cc | 1 + gcc/analyzer/analyzer.h | 5 ++--- gcc/analyzer/call-string.cc | 1 + gcc/analyzer/complexity.cc | 1 + gcc/analyzer/engine.cc | 18 ++++++++---------- gcc/analyzer/exploded-graph.h | 2 +- gcc/analyzer/known-function-manager.cc | 1 + gcc/analyzer/region-model-impl-calls.cc | 12 ++++++------ gcc/analyzer/region-model.cc | 3 +-- gcc/analyzer/region-model.h | 11 +++++------ gcc/analyzer/supergraph.cc | 1 + gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c | 3 ++- .../gcc.dg/plugin/analyzer_known_fns_plugin.c | 3 ++- 16 files changed, 35 insertions(+), 30 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/analysis-plan.cc b/gcc/analyzer/analysis-plan.cc index a4a42c5..aa75bd6 100644 --- a/gcc/analyzer/analysis-plan.cc +++ b/gcc/analyzer/analysis-plan.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/analyzer-pass.cc b/gcc/analyzer/analyzer-pass.cc index fc7098d..423595f 100644 --- a/gcc/analyzer/analyzer-pass.cc +++ b/gcc/analyzer/analyzer-pass.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "context.h" diff --git a/gcc/analyzer/analyzer-selftests.cc b/gcc/analyzer/analyzer-selftests.cc index 278c245..028cc5e 100644 --- a/gcc/analyzer/analyzer-selftests.cc +++ b/gcc/analyzer/analyzer-selftests.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc index 6c7c969..899202b 100644 --- a/gcc/analyzer/analyzer.cc +++ b/gcc/analyzer/analyzer.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index c41cfb0..d8d3e78 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -300,9 +300,8 @@ class path_context public: virtual ~path_context () {} - /* Hook for clients to split state with a non-standard path. - Take ownership of INFO. */ - virtual void bifurcate (custom_edge_info *info) = 0; + /* Hook for clients to split state with a non-standard path. */ + virtual void bifurcate (std::unique_ptr info) = 0; /* Hook for clients to terminate the standard path. */ virtual void terminate_path () = 0; diff --git a/gcc/analyzer/call-string.cc b/gcc/analyzer/call-string.cc index f0a30d9..5caf921 100644 --- a/gcc/analyzer/call-string.cc +++ b/gcc/analyzer/call-string.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "pretty-print.h" diff --git a/gcc/analyzer/complexity.cc b/gcc/analyzer/complexity.cc index 39fbbc1..2756f96 100644 --- a/gcc/analyzer/complexity.cc +++ b/gcc/analyzer/complexity.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 59a4e6f..d770c6f 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -193,12 +193,10 @@ impl_region_model_context::purge_state_involving (const svalue *sval) } void -impl_region_model_context::bifurcate (custom_edge_info *info) +impl_region_model_context::bifurcate (std::unique_ptr info) { if (m_path_ctxt) - m_path_ctxt->bifurcate (info); - else - delete info; + m_path_ctxt->bifurcate (std::move (info)); } void @@ -1646,10 +1644,10 @@ exploded_node::replay_call_summary (exploded_graph &eg, call_summary_replay r (cd, called_fn, summary, ext_state); if (path_ctxt) - path_ctxt->bifurcate (new call_summary_edge_info (cd, - called_fn, - summary, - ext_state)); + path_ctxt->bifurcate (make_unique (cd, + called_fn, + summary, + ext_state)); } @@ -3807,7 +3805,7 @@ public: } void - bifurcate (custom_edge_info *info) final override + bifurcate (std::unique_ptr info) final override { if (m_state_at_bifurcation) /* Verify that the state at bifurcation is consistent when we @@ -3820,7 +3818,7 @@ public: = std::unique_ptr (new program_state (*m_cur_state)); /* Take ownership of INFO. */ - m_custom_eedge_infos.safe_push (info); + m_custom_eedge_infos.safe_push (info.release ()); } void terminate_path () final override diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index 6a25003..8e3c160 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -90,7 +90,7 @@ class impl_region_model_context : public region_model_context void purge_state_involving (const svalue *sval) final override; - void bifurcate (custom_edge_info *info) final override; + void bifurcate (std::unique_ptr info) final override; void terminate_path () final override; const extrinsic_state *get_ext_state () const final override { diff --git a/gcc/analyzer/known-function-manager.cc b/gcc/analyzer/known-function-manager.cc index 48fb005..42dfe3a 100644 --- a/gcc/analyzer/known-function-manager.cc +++ b/gcc/analyzer/known-function-manager.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc index 790dc64..30fa765 100644 --- a/gcc/analyzer/region-model-impl-calls.cc +++ b/gcc/analyzer/region-model-impl-calls.cc @@ -629,8 +629,8 @@ region_model::impl_call_pipe (const call_details &cd) /* Body of region_model::impl_call_pipe. */ if (cd.get_ctxt ()) { - cd.get_ctxt ()->bifurcate (new failure (cd)); - cd.get_ctxt ()->bifurcate (new success (cd)); + cd.get_ctxt ()->bifurcate (make_unique (cd)); + cd.get_ctxt ()->bifurcate (make_unique (cd)); cd.get_ctxt ()->terminate_path (); } } @@ -1006,9 +1006,9 @@ region_model::impl_call_realloc (const call_details &cd) if (cd.get_ctxt ()) { - cd.get_ctxt ()->bifurcate (new failure (cd)); - cd.get_ctxt ()->bifurcate (new success_no_move (cd)); - cd.get_ctxt ()->bifurcate (new success_with_move (cd)); + cd.get_ctxt ()->bifurcate (make_unique (cd)); + cd.get_ctxt ()->bifurcate (make_unique (cd)); + cd.get_ctxt ()->bifurcate (make_unique (cd)); cd.get_ctxt ()->terminate_path (); } } @@ -1077,7 +1077,7 @@ region_model::impl_call_strchr (const call_details &cd) /* Bifurcate state, creating a "not found" out-edge. */ if (cd.get_ctxt ()) - cd.get_ctxt ()->bifurcate (new strchr_call_info (cd, false)); + cd.get_ctxt ()->bifurcate (make_unique (cd, false)); /* The "unbifurcated" state is the "found" case. */ strchr_call_info found (cd, true); diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 37b113f..edf3412 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -6416,9 +6416,8 @@ noop_region_model_context::add_note (std::unique_ptr) } void -noop_region_model_context::bifurcate (custom_edge_info *info) +noop_region_model_context::bifurcate (std::unique_ptr) { - delete info; } void diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index 91b17ce2ad9..5c0bc44 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -729,9 +729,8 @@ class region_model_context /* Hook for clients to purge state involving SVAL. */ virtual void purge_state_involving (const svalue *sval) = 0; - /* Hook for clients to split state with a non-standard path. - Take ownership of INFO. */ - virtual void bifurcate (custom_edge_info *info) = 0; + /* Hook for clients to split state with a non-standard path. */ + virtual void bifurcate (std::unique_ptr info) = 0; /* Hook for clients to terminate the standard path. */ virtual void terminate_path () = 0; @@ -806,7 +805,7 @@ public: void purge_state_involving (const svalue *sval ATTRIBUTE_UNUSED) override {} - void bifurcate (custom_edge_info *info) override; + void bifurcate (std::unique_ptr info) override; void terminate_path () override; const extrinsic_state *get_ext_state () const override { return NULL; } @@ -918,9 +917,9 @@ class region_model_context_decorator : public region_model_context m_inner->purge_state_involving (sval); } - void bifurcate (custom_edge_info *info) override + void bifurcate (std::unique_ptr info) override { - m_inner->bifurcate (info); + m_inner->bifurcate (std::move (info)); } void terminate_path () override diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc index 0e9a325..8195fe8 100644 --- a/gcc/analyzer/supergraph.cc +++ b/gcc/analyzer/supergraph.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c index d1c2913..dfa30c8 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c @@ -42,6 +42,7 @@ #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/call-info.h" +#include "make-unique.h" int plugin_is_GPL_compatible; @@ -95,7 +96,7 @@ class copy_across_boundary_fn : public known_function if (ctxt) { /* Bifurcate state, creating a "failure" out-edge. */ - ctxt->bifurcate (new copy_failure (cd)); + ctxt->bifurcate (make_unique (cd)); /* The "unbifurcated" state is the "success" case. */ copy_success success (cd, diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c index ccf69ed..5c1f398 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c @@ -42,6 +42,7 @@ #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/call-info.h" +#include "make-unique.h" int plugin_is_GPL_compatible; @@ -152,7 +153,7 @@ public: if (cd.get_ctxt ()) { /* Bifurcate state, creating a "failure" out-edge. */ - cd.get_ctxt ()->bifurcate (new copy_failure (cd)); + cd.get_ctxt ()->bifurcate (make_unique (cd)); /* The "unbifurcated" state is the "success" case. */ copy_success success (cd, -- cgit v1.1 From 76dd2c4f2d46f16e8f9a89487e5b3c2b7d4a1369 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 13:47:02 -0400 Subject: analyzer: use std::unique_ptr for known functions gcc/analyzer/ChangeLog: * analyzer.h: Use std::unique_ptr for known functions. * engine.cc: Likewise. * known-function-manager.cc: Likewise. * known-function-manager.h: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c: Use std::unique_ptr for known functions. * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm --- gcc/analyzer/analyzer.h | 2 +- gcc/analyzer/engine.cc | 4 ++-- gcc/analyzer/known-function-manager.cc | 5 +++-- gcc/analyzer/known-function-manager.h | 2 +- gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c | 7 ++++--- gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c | 7 ++++--- 6 files changed, 15 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index d8d3e78..88fdc1d 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -244,7 +244,7 @@ class plugin_analyzer_init_iface public: virtual void register_state_machine (state_machine *) = 0; virtual void register_known_function (const char *name, - known_function *) = 0; + std::unique_ptr) = 0; virtual logger *get_logger () const = 0; }; diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index d770c6f..fe17f8f 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -5960,10 +5960,10 @@ public: } void register_known_function (const char *name, - known_function *kf) final override + std::unique_ptr kf) final override { LOG_SCOPE (m_logger); - m_known_fn_mgr->add (name, kf); + m_known_fn_mgr->add (name, std::move (kf)); } logger *get_logger () const final override diff --git a/gcc/analyzer/known-function-manager.cc b/gcc/analyzer/known-function-manager.cc index 42dfe3a..7341b06 100644 --- a/gcc/analyzer/known-function-manager.cc +++ b/gcc/analyzer/known-function-manager.cc @@ -48,11 +48,12 @@ known_function_manager::~known_function_manager () } void -known_function_manager::add (const char *name, known_function *kf) +known_function_manager::add (const char *name, + std::unique_ptr kf) { LOG_FUNC_1 (get_logger (), "registering %s", name); tree id = get_identifier (name); - m_map_id_to_kf.put (id, kf); + m_map_id_to_kf.put (id, kf.release ()); } const known_function * diff --git a/gcc/analyzer/known-function-manager.h b/gcc/analyzer/known-function-manager.h index 2b95b7e..daf1bc5 100644 --- a/gcc/analyzer/known-function-manager.h +++ b/gcc/analyzer/known-function-manager.h @@ -30,7 +30,7 @@ class known_function_manager : public log_user public: known_function_manager (logger *logger); ~known_function_manager (); - void add (const char *name, known_function *kf); + void add (const char *name, std::unique_ptr kf); const known_function *get_by_identifier (tree identifier); const known_function *get_by_fndecl (tree fndecl); diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c index dfa30c8..92b4dfb 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.c @@ -210,10 +210,11 @@ kernel_analyzer_init_cb (void *gcc_data, void */*user_data*/) LOG_SCOPE (iface->get_logger ()); if (0) inform (input_location, "got here: kernel_analyzer_init_cb"); - iface->register_known_function ("copy_from_user", - new known_function_copy_from_user ()); + iface->register_known_function + ("copy_from_user", + make_unique ()); iface->register_known_function ("copy_to_user", - new known_function_copy_to_user ()); + make_unique ()); } } // namespace ana diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c index 5c1f398..e9f607f 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.c @@ -175,9 +175,10 @@ known_fn_analyzer_init_cb (void *gcc_data, void */*user_data*/) if (0) inform (input_location, "got here: known_fn_analyzer_init_cb"); iface->register_known_function ("returns_42", - new known_function_returns_42 ()); - iface->register_known_function ("attempt_to_copy", - new known_function_attempt_to_copy ()); + make_unique ()); + iface->register_known_function + ("attempt_to_copy", + make_unique ()); } } // namespace ana -- cgit v1.1 From e177be86c7d327b9abd2441d52e3f240b3a488cd Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 3 Nov 2022 13:47:02 -0400 Subject: analyzer: use std::unique_ptr for state machines from plugins gcc/analyzer/ChangeLog: * analyzer.h: Use std::unique_ptr for state machines from plugins. * engine.cc: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.c: Use std::unique_ptr for state machines from plugins. Signed-off-by: David Malcolm --- gcc/analyzer/analyzer.h | 2 +- gcc/analyzer/engine.cc | 4 ++-- gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index 88fdc1d..c0041c3 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -242,7 +242,7 @@ public: class plugin_analyzer_init_iface { public: - virtual void register_state_machine (state_machine *) = 0; + virtual void register_state_machine (std::unique_ptr) = 0; virtual void register_known_function (const char *name, std::unique_ptr) = 0; virtual logger *get_logger () const = 0; diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index fe17f8f..9c32afc 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -5953,10 +5953,10 @@ public: m_logger (logger) {} - void register_state_machine (state_machine *sm) final override + void register_state_machine (std::unique_ptr sm) final override { LOG_SCOPE (m_logger); - m_checkers->safe_push (sm); + m_checkers->safe_push (sm.release ()); } void register_known_function (const char *name, diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c index cf0baa5..b72856b 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c @@ -410,7 +410,8 @@ gil_analyzer_init_cb (void *gcc_data, void */*user_data*/) LOG_SCOPE (iface->get_logger ()); if (0) inform (input_location, "got here: gil_analyzer_init_cb"); - iface->register_state_machine (new gil_state_machine (iface->get_logger ())); + iface->register_state_machine + (make_unique (iface->get_logger ())); } } // namespace ana -- cgit v1.1 From db6a9fe39ab08526b920af2b233b06860d286943 Mon Sep 17 00:00:00 2001 From: Kwok Cheung Yeung Date: Thu, 3 Nov 2022 17:19:11 +0000 Subject: amdgcn: Fix instruction generation for exp2 and log2 operations The GCN instructions for the exp2 and log2 operations are v_exp_* and v_log_* respectively, which unfortunately do not line up with the RTL naming convention. To deal with this, a new set of int attributes is now used when generating the assembly for these instructions. 2022-11-03 Kwok Cheung Yeung gcc/ * config/gcn/gcn-valu.md (math_unop_insn): New attribute. (2, 2, 2, 2, *2_insn, *2_insn): Use math_unop_insn to generate assembler output. gcc/testsuite/ * gcc.target/gcn/unsafe-math-1.c: New. --- gcc/config/gcn/gcn-valu.md | 20 ++++++++++++++------ gcc/testsuite/gcc.target/gcn/unsafe-math-1.c | 10 ++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/gcn/unsafe-math-1.c (limited to 'gcc') diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md index 3b61951..9f43538 100644 --- a/gcc/config/gcn/gcn-valu.md +++ b/gcc/config/gcn/gcn-valu.md @@ -2549,13 +2549,21 @@ (UNSPEC_SIN "sin") (UNSPEC_COS "cos")]) +(define_int_attr math_unop_insn + [(UNSPEC_FLOOR "floor") + (UNSPEC_CEIL "ceil") + (UNSPEC_EXP2 "exp") + (UNSPEC_LOG2 "log") + (UNSPEC_SIN "sin") + (UNSPEC_COS "cos")]) + (define_insn "2" [(set (match_operand:FP 0 "register_operand" "= v") (unspec:FP [(match_operand:FP 1 "gcn_alu_operand" "vSvB")] MATH_UNOP_1OR2REG))] "" - "v_%i0\t%0, %1" + "v_%i0\t%0, %1" [(set_attr "type" "vop1") (set_attr "length" "8")]) @@ -2565,7 +2573,7 @@ [(match_operand:V_FP 1 "gcn_alu_operand" "vSvB")] MATH_UNOP_1OR2REG))] "" - "v_%i0\t%0, %1" + "v_%i0\t%0, %1" [(set_attr "type" "vop1") (set_attr "length" "8")]) @@ -2575,7 +2583,7 @@ [(match_operand:FP_1REG 1 "gcn_alu_operand" "vSvB")] MATH_UNOP_1REG))] "flag_unsafe_math_optimizations" - "v_%i0\t%0, %1" + "v_%i0\t%0, %1" [(set_attr "type" "vop1") (set_attr "length" "8")]) @@ -2585,7 +2593,7 @@ [(match_operand:V_FP_1REG 1 "gcn_alu_operand" "vSvB")] MATH_UNOP_1REG))] "flag_unsafe_math_optimizations" - "v_%i0\t%0, %1" + "v_%i0\t%0, %1" [(set_attr "type" "vop1") (set_attr "length" "8")]) @@ -2595,7 +2603,7 @@ [(match_operand:FP_1REG 1 "gcn_alu_operand" "vSvB")] MATH_UNOP_TRIG))] "flag_unsafe_math_optimizations" - "v_%i0\t%0, %1" + "v_%i0\t%0, %1" [(set_attr "type" "vop1") (set_attr "length" "8")]) @@ -2605,7 +2613,7 @@ [(match_operand:V_FP_1REG 1 "gcn_alu_operand" "vSvB")] MATH_UNOP_TRIG))] "flag_unsafe_math_optimizations" - "v_%i0\t%0, %1" + "v_%i0\t%0, %1" [(set_attr "type" "vop1") (set_attr "length" "8")]) diff --git a/gcc/testsuite/gcc.target/gcn/unsafe-math-1.c b/gcc/testsuite/gcc.target/gcn/unsafe-math-1.c new file mode 100644 index 0000000..2b54fa2 --- /dev/null +++ b/gcc/testsuite/gcc.target/gcn/unsafe-math-1.c @@ -0,0 +1,10 @@ +/* { dg-do link } */ +/* { dg-options "-O0 -ffast-math" } */ + +int main (void) +{ + float x = 0.123456f; + + float r1 = __builtin_exp2f (x); + float r2 = __builtin_log2f (x); +} -- cgit v1.1 From c0b38e9fec71dc4cc5e99b1f0cb159c15a8da9ba Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Thu, 3 Nov 2022 14:55:35 -0400 Subject: c++: constexpr error with defaulted virtual dtor [PR93413] We're rejecting the below testcase with error: 'virtual constexpr Base::~Base()' used before its definition error: 'virtual constexpr Derived::~Derived()' used before its definition due to special handling in mark_used added by r181272 to defer synthesis of virtual destructors until EOF (where we can set their linkage), which in turn makes them effectively unusable during constexpr evaluation. Fortunately it seems this special handling is unnecessary ever since r208030 enabled us to tentatively set linkage of all defaulted virtual destructors, including templated ones. So this patch gets rid of this special handling. PR c++/93413 gcc/cp/ChangeLog: * decl2.cc (mark_used): Don't defer synthesis of virtual functions. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/constexpr-virtual21.C: New test. --- gcc/cp/decl2.cc | 8 -------- gcc/testsuite/g++.dg/cpp2a/constexpr-virtual21.C | 10 ++++++++++ 2 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-virtual21.C (limited to 'gcc') diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index e677926..eeb59ea 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -5788,14 +5788,6 @@ mark_used (tree decl, tsubst_flags_t complain /* = tf_warning_or_error */) && !DECL_DEFAULTED_OUTSIDE_CLASS_P (decl) && ! DECL_INITIAL (decl)) { - /* Defer virtual destructors so that thunks get the right - linkage. */ - if (DECL_VIRTUAL_P (decl) && !at_eof) - { - note_vague_linkage_fn (decl); - return true; - } - /* Remember the current location for a function we will end up synthesizing. Then we can inform the user where it was required in the case of error. */ diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual21.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual21.C new file mode 100644 index 0000000..8b70c5f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual21.C @@ -0,0 +1,10 @@ +// PR c++/93413 +// { dg-do compile { target c++20 } } + +struct Base { + virtual ~Base() = default; +}; +constexpr Base b; + +struct Derived : Base { }; +constexpr Derived d; -- cgit v1.1 From a4cd2389276a30c39034a83d640ce68fa407bac1 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 3 Nov 2022 10:51:40 -0400 Subject: c++: change -fconcepts to mean C++20 concepts It was always weird that -fconcepts in C++17 mode meant the same thing as -fconcepts-ts in C++20 mode; this patch harmonizes the flags so that for TS concepts you always need to write -fconcepts-ts. In the unlikely event anyone is still using -fconcepts in C++17 mode, they can either fix their code to work with C++20 concepts or adjust the compiler flag. gcc/c-family/ChangeLog: * c-opts.cc (c_common_post_options): -fconcepts no longer implies -fconcepts-ts before C++20. gcc/ChangeLog: * doc/invoke.texi: -fconcepts no longer implies -fconcepts-ts before C++20. gcc/cp/ChangeLog: * parser.cc (cp_parser_template_declaration_after_parameters): Fix concept parsing below C++20. gcc/testsuite/ChangeLog: * g++.dg/concepts/auto1.C: * g++.dg/concepts/auto3.C: * g++.dg/concepts/auto4.C: * g++.dg/concepts/class-deduction1.C: * g++.dg/concepts/class5.C: * g++.dg/concepts/class6.C: * g++.dg/concepts/debug1.C: * g++.dg/concepts/decl-diagnose.C: * g++.dg/concepts/deduction-constraint1.C: * g++.dg/concepts/diagnostic1.C: * g++.dg/concepts/dr1430.C: * g++.dg/concepts/equiv.C: * g++.dg/concepts/equiv2.C: * g++.dg/concepts/expression.C: * g++.dg/concepts/expression2.C: * g++.dg/concepts/expression3.C: * g++.dg/concepts/fn-concept1.C: * g++.dg/concepts/fn-concept2.C: * g++.dg/concepts/fn-concept3.C: * g++.dg/concepts/fn1.C: * g++.dg/concepts/fn10.C: * g++.dg/concepts/fn2.C: * g++.dg/concepts/fn3.C: * g++.dg/concepts/fn4.C: * g++.dg/concepts/fn5.C: * g++.dg/concepts/fn6.C: * g++.dg/concepts/fn8.C: * g++.dg/concepts/fn9.C: * g++.dg/concepts/generic-fn-err.C: * g++.dg/concepts/generic-fn.C: * g++.dg/concepts/inherit-ctor1.C: * g++.dg/concepts/inherit-ctor3.C: * g++.dg/concepts/intro1.C: * g++.dg/concepts/intro2.C: * g++.dg/concepts/intro3.C: * g++.dg/concepts/intro4.C: * g++.dg/concepts/intro5.C: * g++.dg/concepts/intro6.C: * g++.dg/concepts/intro7.C: * g++.dg/concepts/locations1.C: * g++.dg/concepts/partial-concept-id1.C: * g++.dg/concepts/partial-concept-id2.C: * g++.dg/concepts/partial-spec5.C: * g++.dg/concepts/placeholder2.C: * g++.dg/concepts/placeholder3.C: * g++.dg/concepts/placeholder4.C: * g++.dg/concepts/placeholder5.C: * g++.dg/concepts/placeholder6.C: * g++.dg/concepts/pr65634.C: * g++.dg/concepts/pr65636.C: * g++.dg/concepts/pr65681.C: * g++.dg/concepts/pr65848.C: * g++.dg/concepts/pr67249.C: * g++.dg/concepts/pr67595.C: * g++.dg/concepts/pr68434.C: * g++.dg/concepts/pr71127.C: * g++.dg/concepts/pr71128.C: * g++.dg/concepts/pr71131.C: * g++.dg/concepts/pr71385.C: * g++.dg/concepts/pr85065.C: * g++.dg/concepts/template-parm11.C: * g++.dg/concepts/template-parm12.C: * g++.dg/concepts/template-parm2.C: * g++.dg/concepts/template-parm3.C: * g++.dg/concepts/template-parm4.C: * g++.dg/concepts/template-template-parm1.C: * g++.dg/concepts/var-concept1.C: * g++.dg/concepts/var-concept2.C: * g++.dg/concepts/var-concept3.C: * g++.dg/concepts/var-concept4.C: * g++.dg/concepts/var-concept5.C: * g++.dg/concepts/var-concept6.C: * g++.dg/concepts/var-concept7.C: * g++.dg/concepts/var-templ2.C: * g++.dg/concepts/var-templ3.C: * g++.dg/concepts/variadic1.C: * g++.dg/concepts/variadic2.C: * g++.dg/concepts/variadic3.C: * g++.dg/concepts/variadic4.C: * g++.dg/cpp2a/concepts-pr65575.C: * g++.dg/cpp2a/concepts-pr66091.C: * g++.dg/cpp2a/concepts-pr84980.C: * g++.dg/cpp2a/concepts-pr85265.C: Pass -fconcepts-ts. * g++.dg/cpp2a/concepts-pr84979-2.C: * g++.dg/cpp2a/concepts-pr84979-3.C: Same diagnostics in C++20 and below. --- gcc/c-family/c-opts.cc | 3 --- gcc/cp/parser.cc | 7 ++++--- gcc/doc/invoke.texi | 16 ++++++++-------- gcc/testsuite/g++.dg/concepts/auto1.C | 2 +- gcc/testsuite/g++.dg/concepts/auto3.C | 2 +- gcc/testsuite/g++.dg/concepts/auto4.C | 2 +- gcc/testsuite/g++.dg/concepts/class-deduction1.C | 2 +- gcc/testsuite/g++.dg/concepts/class5.C | 2 +- gcc/testsuite/g++.dg/concepts/class6.C | 2 +- gcc/testsuite/g++.dg/concepts/debug1.C | 2 +- gcc/testsuite/g++.dg/concepts/decl-diagnose.C | 2 +- gcc/testsuite/g++.dg/concepts/deduction-constraint1.C | 2 +- gcc/testsuite/g++.dg/concepts/diagnostic1.C | 2 +- gcc/testsuite/g++.dg/concepts/dr1430.C | 2 +- gcc/testsuite/g++.dg/concepts/equiv.C | 2 +- gcc/testsuite/g++.dg/concepts/equiv2.C | 2 +- gcc/testsuite/g++.dg/concepts/expression.C | 2 +- gcc/testsuite/g++.dg/concepts/expression2.C | 2 +- gcc/testsuite/g++.dg/concepts/expression3.C | 2 +- gcc/testsuite/g++.dg/concepts/fn-concept1.C | 2 +- gcc/testsuite/g++.dg/concepts/fn-concept2.C | 2 +- gcc/testsuite/g++.dg/concepts/fn-concept3.C | 2 +- gcc/testsuite/g++.dg/concepts/fn1.C | 2 +- gcc/testsuite/g++.dg/concepts/fn10.C | 2 +- gcc/testsuite/g++.dg/concepts/fn2.C | 2 +- gcc/testsuite/g++.dg/concepts/fn3.C | 2 +- gcc/testsuite/g++.dg/concepts/fn4.C | 2 +- gcc/testsuite/g++.dg/concepts/fn5.C | 2 +- gcc/testsuite/g++.dg/concepts/fn6.C | 2 +- gcc/testsuite/g++.dg/concepts/fn8.C | 2 +- gcc/testsuite/g++.dg/concepts/fn9.C | 2 +- gcc/testsuite/g++.dg/concepts/generic-fn-err.C | 2 +- gcc/testsuite/g++.dg/concepts/generic-fn.C | 2 +- gcc/testsuite/g++.dg/concepts/inherit-ctor1.C | 2 +- gcc/testsuite/g++.dg/concepts/inherit-ctor3.C | 2 +- gcc/testsuite/g++.dg/concepts/intro1.C | 2 +- gcc/testsuite/g++.dg/concepts/intro2.C | 2 +- gcc/testsuite/g++.dg/concepts/intro3.C | 2 +- gcc/testsuite/g++.dg/concepts/intro4.C | 2 +- gcc/testsuite/g++.dg/concepts/intro5.C | 2 +- gcc/testsuite/g++.dg/concepts/intro6.C | 2 +- gcc/testsuite/g++.dg/concepts/intro7.C | 2 +- gcc/testsuite/g++.dg/concepts/locations1.C | 2 +- gcc/testsuite/g++.dg/concepts/partial-concept-id1.C | 2 +- gcc/testsuite/g++.dg/concepts/partial-concept-id2.C | 2 +- gcc/testsuite/g++.dg/concepts/partial-spec5.C | 2 +- gcc/testsuite/g++.dg/concepts/placeholder2.C | 2 +- gcc/testsuite/g++.dg/concepts/placeholder3.C | 2 +- gcc/testsuite/g++.dg/concepts/placeholder4.C | 2 +- gcc/testsuite/g++.dg/concepts/placeholder5.C | 2 +- gcc/testsuite/g++.dg/concepts/placeholder6.C | 2 +- gcc/testsuite/g++.dg/concepts/pr65634.C | 2 +- gcc/testsuite/g++.dg/concepts/pr65636.C | 2 +- gcc/testsuite/g++.dg/concepts/pr65681.C | 2 +- gcc/testsuite/g++.dg/concepts/pr65848.C | 2 +- gcc/testsuite/g++.dg/concepts/pr67249.C | 2 +- gcc/testsuite/g++.dg/concepts/pr67595.C | 2 +- gcc/testsuite/g++.dg/concepts/pr68434.C | 2 +- gcc/testsuite/g++.dg/concepts/pr71127.C | 2 +- gcc/testsuite/g++.dg/concepts/pr71128.C | 2 +- gcc/testsuite/g++.dg/concepts/pr71131.C | 2 +- gcc/testsuite/g++.dg/concepts/pr71385.C | 2 +- gcc/testsuite/g++.dg/concepts/pr85065.C | 2 +- gcc/testsuite/g++.dg/concepts/template-parm11.C | 2 +- gcc/testsuite/g++.dg/concepts/template-parm12.C | 2 +- gcc/testsuite/g++.dg/concepts/template-parm2.C | 2 +- gcc/testsuite/g++.dg/concepts/template-parm3.C | 2 +- gcc/testsuite/g++.dg/concepts/template-parm4.C | 2 +- gcc/testsuite/g++.dg/concepts/template-template-parm1.C | 2 +- gcc/testsuite/g++.dg/concepts/var-concept1.C | 2 +- gcc/testsuite/g++.dg/concepts/var-concept2.C | 2 +- gcc/testsuite/g++.dg/concepts/var-concept3.C | 2 +- gcc/testsuite/g++.dg/concepts/var-concept4.C | 2 +- gcc/testsuite/g++.dg/concepts/var-concept5.C | 2 +- gcc/testsuite/g++.dg/concepts/var-concept6.C | 2 +- gcc/testsuite/g++.dg/concepts/var-concept7.C | 2 +- gcc/testsuite/g++.dg/concepts/var-templ2.C | 2 +- gcc/testsuite/g++.dg/concepts/var-templ3.C | 2 +- gcc/testsuite/g++.dg/concepts/variadic1.C | 2 +- gcc/testsuite/g++.dg/concepts/variadic2.C | 2 +- gcc/testsuite/g++.dg/concepts/variadic3.C | 2 +- gcc/testsuite/g++.dg/concepts/variadic4.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-pr65575.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-pr66091.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C | 5 ++--- gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C | 5 ++--- gcc/testsuite/g++.dg/cpp2a/concepts-pr84980.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-pr85265.C | 2 +- 88 files changed, 99 insertions(+), 103 deletions(-) (limited to 'gcc') diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index 32b929e..9e0494b 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -1090,9 +1090,6 @@ c_common_post_options (const char **pfilename) work with the standard. */ if (cxx_dialect >= cxx20 || flag_concepts_ts) flag_concepts = 1; - else if (flag_concepts) - /* For -std=c++17 -fconcepts, imply -fconcepts-ts. */ - flag_concepts_ts = 1; if (num_in_fnames > 1) error ("too many filenames given; type %<%s %s%> for usage", diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index fd59de4..9523f73 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -31450,10 +31450,11 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, else if (cxx_dialect >= cxx11 && cp_lexer_next_token_is_keyword (parser->lexer, RID_USING)) decl = cp_parser_alias_declaration (parser); - else if (cxx_dialect >= cxx20 /* Implies flag_concept. */ + else if (flag_concepts && cp_lexer_next_token_is_keyword (parser->lexer, RID_CONCEPT) - && !cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_BOOL)) - /* Allow 'concept bool' to be handled as per the TS. */ + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + /* -fconcept-ts 'concept bool' syntax is handled below, in + cp_parser_single_declaration. */ decl = cp_parser_concept_definition (parser); else { diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index c6323a5..2b29db8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -3075,14 +3075,14 @@ exhaustion is signalled by throwing @code{std::bad_alloc}. See also @itemx -fconcepts-ts @opindex fconcepts @opindex fconcepts-ts -Below @option{-std=c++20}, @option{-fconcepts} enables support for the -C++ Extensions for Concepts Technical Specification, ISO 19217 (2015). - -With @option{-std=c++20} and above, Concepts are part of the language -standard, so @option{-fconcepts} defaults to on. But the standard -specification of Concepts differs significantly from the TS, so some -constructs that were allowed in the TS but didn't make it into the -standard can still be enabled by @option{-fconcepts-ts}. +Enable support for the C++ Concepts feature for constraining template +arguments. With @option{-std=c++20} and above, Concepts are part of +the language standard, so @option{-fconcepts} defaults to on. + +Some constructs that were allowed by the earlier C++ Extensions for +Concepts Technical Specification, ISO 19217 (2015), but didn't make it +into the standard, can additionally be enabled by +@option{-fconcepts-ts}. @item -fconstexpr-depth=@var{n} @opindex fconstexpr-depth diff --git a/gcc/testsuite/g++.dg/concepts/auto1.C b/gcc/testsuite/g++.dg/concepts/auto1.C index e053306..abf7886 100644 --- a/gcc/testsuite/g++.dg/concepts/auto1.C +++ b/gcc/testsuite/g++.dg/concepts/auto1.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template class A { }; diff --git a/gcc/testsuite/g++.dg/concepts/auto3.C b/gcc/testsuite/g++.dg/concepts/auto3.C index 27a6afa..868a56c 100644 --- a/gcc/testsuite/g++.dg/concepts/auto3.C +++ b/gcc/testsuite/g++.dg/concepts/auto3.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template class tuple {}; diff --git a/gcc/testsuite/g++.dg/concepts/auto4.C b/gcc/testsuite/g++.dg/concepts/auto4.C index 8bf3fa9..6c98455 100644 --- a/gcc/testsuite/g++.dg/concepts/auto4.C +++ b/gcc/testsuite/g++.dg/concepts/auto4.C @@ -1,6 +1,6 @@ // PR c++/85006 // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template struct A {}; diff --git a/gcc/testsuite/g++.dg/concepts/class-deduction1.C b/gcc/testsuite/g++.dg/concepts/class-deduction1.C index 3359700..7f427d0 100644 --- a/gcc/testsuite/g++.dg/concepts/class-deduction1.C +++ b/gcc/testsuite/g++.dg/concepts/class-deduction1.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool Isint = __is_same_as(T,int); diff --git a/gcc/testsuite/g++.dg/concepts/class5.C b/gcc/testsuite/g++.dg/concepts/class5.C index ac9d7e8..5f8ece9 100644 --- a/gcc/testsuite/g++.dg/concepts/class5.C +++ b/gcc/testsuite/g++.dg/concepts/class5.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool One() { return sizeof(T) >= 4; } diff --git a/gcc/testsuite/g++.dg/concepts/class6.C b/gcc/testsuite/g++.dg/concepts/class6.C index f2345b1..a1c5e16 100644 --- a/gcc/testsuite/g++.dg/concepts/class6.C +++ b/gcc/testsuite/g++.dg/concepts/class6.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool One() { return sizeof(T) >= 4; } diff --git a/gcc/testsuite/g++.dg/concepts/debug1.C b/gcc/testsuite/g++.dg/concepts/debug1.C index b9a5444..fb48567 100644 --- a/gcc/testsuite/g++.dg/concepts/debug1.C +++ b/gcc/testsuite/g++.dg/concepts/debug1.C @@ -1,6 +1,6 @@ // PR c++/84551 // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C() { return true; } diff --git a/gcc/testsuite/g++.dg/concepts/decl-diagnose.C b/gcc/testsuite/g++.dg/concepts/decl-diagnose.C index 6a461a5..96038fd 100644 --- a/gcc/testsuite/g++.dg/concepts/decl-diagnose.C +++ b/gcc/testsuite/g++.dg/concepts/decl-diagnose.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } typedef concept int CINT; // { dg-error "'concept' cannot appear in a typedef declaration" } diff --git a/gcc/testsuite/g++.dg/concepts/deduction-constraint1.C b/gcc/testsuite/g++.dg/concepts/deduction-constraint1.C index eba5771..d510fe0 100644 --- a/gcc/testsuite/g++.dg/concepts/deduction-constraint1.C +++ b/gcc/testsuite/g++.dg/concepts/deduction-constraint1.C @@ -1,6 +1,6 @@ // PR c++/67007 // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool A = diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic1.C b/gcc/testsuite/g++.dg/concepts/diagnostic1.C index 29c78c4..207c36c 100644 --- a/gcc/testsuite/g++.dg/concepts/diagnostic1.C +++ b/gcc/testsuite/g++.dg/concepts/diagnostic1.C @@ -1,6 +1,6 @@ // PR c++/67159 // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts -fconcepts-diagnostics-depth=2" } +// { dg-options "-fconcepts-ts -fconcepts-diagnostics-depth=2" } template concept bool SameAs = __is_same_as(T, U); diff --git a/gcc/testsuite/g++.dg/concepts/dr1430.C b/gcc/testsuite/g++.dg/concepts/dr1430.C index 05c9152..c22a782 100644 --- a/gcc/testsuite/g++.dg/concepts/dr1430.C +++ b/gcc/testsuite/g++.dg/concepts/dr1430.C @@ -1,6 +1,6 @@ // PR c++/66092 // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } #include diff --git a/gcc/testsuite/g++.dg/concepts/equiv.C b/gcc/testsuite/g++.dg/concepts/equiv.C index 640c2b5..a5d0c18 100644 --- a/gcc/testsuite/g++.dg/concepts/equiv.C +++ b/gcc/testsuite/g++.dg/concepts/equiv.C @@ -1,5 +1,5 @@ // { dg-do link { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } // Check equivalence of short- and longhand declarations. diff --git a/gcc/testsuite/g++.dg/concepts/equiv2.C b/gcc/testsuite/g++.dg/concepts/equiv2.C index dff719b..48a2664 100644 --- a/gcc/testsuite/g++.dg/concepts/equiv2.C +++ b/gcc/testsuite/g++.dg/concepts/equiv2.C @@ -1,5 +1,5 @@ // { dg-do link { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } // template diff --git a/gcc/testsuite/g++.dg/concepts/expression.C b/gcc/testsuite/g++.dg/concepts/expression.C index ba4c48d..3da0c96 100644 --- a/gcc/testsuite/g++.dg/concepts/expression.C +++ b/gcc/testsuite/g++.dg/concepts/expression.C @@ -1,5 +1,5 @@ // { dg-do run { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } // TODO: ICE on gimplify 16? diff --git a/gcc/testsuite/g++.dg/concepts/expression2.C b/gcc/testsuite/g++.dg/concepts/expression2.C index 4bb5bc7..2f7aafc 100644 --- a/gcc/testsuite/g++.dg/concepts/expression2.C +++ b/gcc/testsuite/g++.dg/concepts/expression2.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C1() diff --git a/gcc/testsuite/g++.dg/concepts/expression3.C b/gcc/testsuite/g++.dg/concepts/expression3.C index 67646811..a2d340d 100644 --- a/gcc/testsuite/g++.dg/concepts/expression3.C +++ b/gcc/testsuite/g++.dg/concepts/expression3.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C() diff --git a/gcc/testsuite/g++.dg/concepts/fn-concept1.C b/gcc/testsuite/g++.dg/concepts/fn-concept1.C index d1b4c0c..4908d11 100644 --- a/gcc/testsuite/g++.dg/concepts/fn-concept1.C +++ b/gcc/testsuite/g++.dg/concepts/fn-concept1.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool Tuple() { // { dg-error "multiple statements" } diff --git a/gcc/testsuite/g++.dg/concepts/fn-concept2.C b/gcc/testsuite/g++.dg/concepts/fn-concept2.C index 899988c..2876505 100644 --- a/gcc/testsuite/g++.dg/concepts/fn-concept2.C +++ b/gcc/testsuite/g++.dg/concepts/fn-concept2.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept auto C1() { return 0; } // { dg-error "16:concept .concept auto C1\\(\\). declared with a deduced return type" } diff --git a/gcc/testsuite/g++.dg/concepts/fn-concept3.C b/gcc/testsuite/g++.dg/concepts/fn-concept3.C index ecb7f6b..88ed5a8 100644 --- a/gcc/testsuite/g++.dg/concepts/fn-concept3.C +++ b/gcc/testsuite/g++.dg/concepts/fn-concept3.C @@ -1,6 +1,6 @@ // PR c++/92746 // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C3() { return true; } static_assert(noexcept(C3()), "function concept should be treated as if noexcept(true) specified"); diff --git a/gcc/testsuite/g++.dg/concepts/fn1.C b/gcc/testsuite/g++.dg/concepts/fn1.C index f23c057..e22cbf7 100644 --- a/gcc/testsuite/g++.dg/concepts/fn1.C +++ b/gcc/testsuite/g++.dg/concepts/fn1.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C() { return __is_class(T); } diff --git a/gcc/testsuite/g++.dg/concepts/fn10.C b/gcc/testsuite/g++.dg/concepts/fn10.C index 8d0a2e1..83099de 100644 --- a/gcc/testsuite/g++.dg/concepts/fn10.C +++ b/gcc/testsuite/g++.dg/concepts/fn10.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } // Test that constraint satisfaction checks work even when // processing template declarations. diff --git a/gcc/testsuite/g++.dg/concepts/fn2.C b/gcc/testsuite/g++.dg/concepts/fn2.C index 1c1280c..e0ac36f 100644 --- a/gcc/testsuite/g++.dg/concepts/fn2.C +++ b/gcc/testsuite/g++.dg/concepts/fn2.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C() { return __is_class(T); } diff --git a/gcc/testsuite/g++.dg/concepts/fn3.C b/gcc/testsuite/g++.dg/concepts/fn3.C index 07b8e3a..3e076f6 100644 --- a/gcc/testsuite/g++.dg/concepts/fn3.C +++ b/gcc/testsuite/g++.dg/concepts/fn3.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } #include diff --git a/gcc/testsuite/g++.dg/concepts/fn4.C b/gcc/testsuite/g++.dg/concepts/fn4.C index bbaac46..6418677 100644 --- a/gcc/testsuite/g++.dg/concepts/fn4.C +++ b/gcc/testsuite/g++.dg/concepts/fn4.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C() { return __is_class(T); } diff --git a/gcc/testsuite/g++.dg/concepts/fn5.C b/gcc/testsuite/g++.dg/concepts/fn5.C index bf27713..3decf4e 100644 --- a/gcc/testsuite/g++.dg/concepts/fn5.C +++ b/gcc/testsuite/g++.dg/concepts/fn5.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } // Check shorthand notation. diff --git a/gcc/testsuite/g++.dg/concepts/fn6.C b/gcc/testsuite/g++.dg/concepts/fn6.C index 031e87f..57c4cfb 100644 --- a/gcc/testsuite/g++.dg/concepts/fn6.C +++ b/gcc/testsuite/g++.dg/concepts/fn6.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } // Redefinition errors. diff --git a/gcc/testsuite/g++.dg/concepts/fn8.C b/gcc/testsuite/g++.dg/concepts/fn8.C index 32df5a5..594270f 100644 --- a/gcc/testsuite/g++.dg/concepts/fn8.C +++ b/gcc/testsuite/g++.dg/concepts/fn8.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool Class() { return __is_class(T); } diff --git a/gcc/testsuite/g++.dg/concepts/fn9.C b/gcc/testsuite/g++.dg/concepts/fn9.C index 2f5e88b..51edd2f 100644 --- a/gcc/testsuite/g++.dg/concepts/fn9.C +++ b/gcc/testsuite/g++.dg/concepts/fn9.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } #include diff --git a/gcc/testsuite/g++.dg/concepts/generic-fn-err.C b/gcc/testsuite/g++.dg/concepts/generic-fn-err.C index 816072d..e4909eb 100644 --- a/gcc/testsuite/g++.dg/concepts/generic-fn-err.C +++ b/gcc/testsuite/g++.dg/concepts/generic-fn-err.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C() { return __is_class(T); } diff --git a/gcc/testsuite/g++.dg/concepts/generic-fn.C b/gcc/testsuite/g++.dg/concepts/generic-fn.C index 257608a..983b370 100644 --- a/gcc/testsuite/g++.dg/concepts/generic-fn.C +++ b/gcc/testsuite/g++.dg/concepts/generic-fn.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } #include #include diff --git a/gcc/testsuite/g++.dg/concepts/inherit-ctor1.C b/gcc/testsuite/g++.dg/concepts/inherit-ctor1.C index b137791..98c260c 100644 --- a/gcc/testsuite/g++.dg/concepts/inherit-ctor1.C +++ b/gcc/testsuite/g++.dg/concepts/inherit-ctor1.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C = __is_class(T); diff --git a/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C b/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C index 6b7a7a4..76308ff 100644 --- a/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C +++ b/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C() { return __is_class(T); } diff --git a/gcc/testsuite/g++.dg/concepts/intro1.C b/gcc/testsuite/g++.dg/concepts/intro1.C index 5f9bb7e..0dd9b64 100644 --- a/gcc/testsuite/g++.dg/concepts/intro1.C +++ b/gcc/testsuite/g++.dg/concepts/intro1.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C = __is_class(T); diff --git a/gcc/testsuite/g++.dg/concepts/intro2.C b/gcc/testsuite/g++.dg/concepts/intro2.C index 206777d..5c6906c 100644 --- a/gcc/testsuite/g++.dg/concepts/intro2.C +++ b/gcc/testsuite/g++.dg/concepts/intro2.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } #include diff --git a/gcc/testsuite/g++.dg/concepts/intro3.C b/gcc/testsuite/g++.dg/concepts/intro3.C index f02f1be..c92338e 100644 --- a/gcc/testsuite/g++.dg/concepts/intro3.C +++ b/gcc/testsuite/g++.dg/concepts/intro3.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C1 = true; diff --git a/gcc/testsuite/g++.dg/concepts/intro4.C b/gcc/testsuite/g++.dg/concepts/intro4.C index 0b275e1..5ddd162 100644 --- a/gcc/testsuite/g++.dg/concepts/intro4.C +++ b/gcc/testsuite/g++.dg/concepts/intro4.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C1 = true; diff --git a/gcc/testsuite/g++.dg/concepts/intro5.C b/gcc/testsuite/g++.dg/concepts/intro5.C index bbfef7b..cb1c5da 100644 --- a/gcc/testsuite/g++.dg/concepts/intro5.C +++ b/gcc/testsuite/g++.dg/concepts/intro5.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template concept bool C() diff --git a/gcc/testsuite/g++.dg/concepts/intro6.C b/gcc/testsuite/g++.dg/concepts/intro6.C index 233c5bc..b718d13 100644 --- a/gcc/testsuite/g++.dg/concepts/intro6.C +++ b/gcc/testsuite/g++.dg/concepts/intro6.C @@ -1,6 +1,6 @@ // PR c++/67003 // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } namespace X { template diff --git a/gcc/testsuite/g++.dg/concepts/intro7.C b/gcc/testsuite/g++.dg/concepts/intro7.C index 343fe7a..0c452a7 100644 --- a/gcc/testsuite/g++.dg/concepts/intro7.C +++ b/gcc/testsuite/g++.dg/concepts/intro7.C @@ -1,6 +1,6 @@ // PR c++/66985 // { dg-do compile { target c++17_only } } -// { dg-options "-fconcepts" } +// { dg-options "-fconcepts-ts" } template