diff options
Diffstat (limited to 'gcc')
69 files changed, 2419 insertions, 517 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d975768..b600551 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,223 @@ +2025-08-06 Uros Bizjak <ubizjak@gmail.com> + + PR target/96226 + * config/i386/predicates.md (and_operator): New operator. + * config/i386/i386.md (splitter after *<rotate_insn><mode>3_mask): + Use and_operator to match AND RTX and use its mode + in the split pattern. + +2025-08-06 Gerald Pfeifer <gerald@pfeifer.com> + + PR target/69374 + * doc/install.texi (Prerequisites): Replace bzip2 by xz. + +2025-08-06 Yangyu Chen <cyy@cyyself.name> + + * config/i386/i386.h (PTA_BDVER1): + Add missing PTA_POPCNT and PTA_LZCNT with PTA_ABM. + (PTA_ZNVER1): Ditto. + (PTA_BTVER1): Ditto. + (PTA_LUJIAZUI): Ditto. + (PTA_YONGFENG): Do not include extra PTA_LZCNT. + +2025-08-06 Sam James <sam@gentoo.org> + + PR libstdc++/29286 + * Makefile.in (ALIASING_FLAGS): Drop. + * configure: Regenerate. + * configure.ac: Drop -fno-strict-aliasing workaround for < GCC 4.3. + +2025-08-06 Richard Biener <rguenther@suse.de> + + * tree-vect-data-refs.cc (vect_supportable_dr_alignment): + Prune dead code. + +2025-08-06 Patrick Palka <ppalka@redhat.com> + + PR c++/121231 + PR c++/119688 + PR c++/94511 + * common.opt: Document additional ABI version 21 change. + * doc/invoke.texi: Likewise. + +2025-08-06 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (_slp_tree::gs_scale): New. + (_slp_tree::gs_base): Likewise. + (SLP_TREE_GS_SCALE): Likewise. + (SLP_TREE_GS_BASE): Likewise. + (vect_describe_gather_scatter_call): Declare. + * tree-vect-slp.cc (_slp_tree::_slp_tree): Initialize + new members. + (vect_build_slp_tree_2): Record gather/scatter base and scale. + (vect_get_and_check_slp_defs): For gather/scatter IFNs + describe the call to first_gs_info. + * tree-vect-data-refs.cc (vect_gather_scatter_fn_p): Add + mode of operation with fixed offset vector type. + (vect_describe_gather_scatter_call): Export. + * tree-vect-stmts.cc (get_load_store_type): Do not call + vect_check_gather_scatter to fill gs_info, instead populate + from the SLP tree. Check which of, IFN, decl or fallback + is supported and record that decision. + +2025-08-06 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.cc (vectorizable_store): Build proper + alias + align pointer value for gather/scatter and SLP + and use it. + (vectorizable_load): Likewise. + +2025-08-06 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.cc (check_load_store_for_partial_vectors): + Remove redundant gather/scatter target support check, instead + check the recorded ifns. Also allow legacy gather/scatter + with loop masking. + +2025-08-06 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/121413 + * gimple-lower-bitint.cc (gimple_lower_bitint): Fix up last + commit, cast limb_prec to unsigned before comparison. + +2025-08-06 Yang Yujie <yangyujie@loongson.cn> + + * match.pd: Preserve conversion to _BitInt before a VCE + if the _BitInt is extended. + +2025-08-06 Yang Yujie <yangyujie@loongson.cn> + + * gimple-lower-bitint.cc (bitint_large_huge::lower_mergeable_stmt): + Zero-extend the partial limb of any unsigned _BitInt LHS assigned + with a widening sign-extension. + +2025-08-06 Yang Yujie <yangyujie@loongson.cn> + + * gimple-lower-bitint.cc (bitint_large_huge::limb_access): + Add a parameter abi_load_p. If set, load a limb directly + in its actual precision without casting from m_limb_type. + (struct bitint_large_huge): Same. + (bitint_large_huge::handle_load): Use. + +2025-08-06 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/121413 + * gimple-lower-bitint.cc (abi_limb_prec): New variable + (bitint_precision_kind): Initialize it. + (gimple_lower_bitint): Clear it at the start. For + min_prec > limb_prec descreased precision vars for + INTEGER_CST PHI arguments ensure min_prec is either + prec or multiple of abi_limb_prec. + +2025-08-06 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/121127 + * gimple-lower-bitint.cc (bitint_large_huge::handle_operand_addr): For + uninitialized SSA_NAME, set *prec_stored to 0 rather than *prec. + Handle that case in narrowing casts. If prec_stored is non-NULL, + set *prec_stored to prec_stored_val. + +2025-08-06 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/121386 + * Makefile.in (gengtype-lex.cc): Append #define FLEX_SCANNER, + #include "system.h" and #undef FLEX_SCANNER to the prepended lines. + * gengtype-lex.l: Remove inclusion of config.h or bconfig.h, system.h + and definition of malloc/realloc from %{} section. + +2025-08-06 Kito Cheng <kito.cheng@sifive.com> + + * config/riscv/arch-canonicalize: Read extension data from + riscv-ext*.def and adding unittest. + +2025-08-06 Kito Cheng <kito.cheng@sifive.com> + + * common/config/riscv/riscv-common.cc (riscv_expand_arch): + Ignore `unset`. + * config/riscv/riscv.h (OPTION_DEFAULT_SPECS): Handle + `-march=unset`. + (ARCH_UNSET_CLEANUP_SPECS): New. + (DRIVER_SELF_SPECS): Handle -march=unset. + * doc/invoke.texi (RISC-V Options): Update documentation for + `-march=unset`. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + + * gimplify.cc (remove_unused_omp_iterator_vars): Display unused + variable warning for 'to' and 'from' clauses. + (gimplify_scan_omp_clauses): Add argument for iterator loop sequence. + Gimplify the clause decl and size into the iterator loop if iterators + are used. + (gimplify_omp_workshare): Add argument for iterator loops sequence + in call to gimplify_scan_omp_clauses. + (gimplify_omp_target_update): Call remove_unused_omp_iterator_vars and + build_omp_iterators_loops. Add loop sequence as argument when calling + gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses and building + the Gimple statement. + * tree-pretty-print.cc (dump_omp_clause): Call dump_omp_iterators + for to/from clauses with iterators. + * tree.cc (omp_clause_num_ops): Add extra operand for OMP_CLAUSE_FROM + and OMP_CLAUSE_TO. + * tree.h (OMP_CLAUSE_HAS_ITERATORS): Add check for OMP_CLAUSE_TO and + OMP_CLAUSE_FROM. + (OMP_CLAUSE_ITERATORS): Likewise. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + Andrew Stubbs <ams@baylibre.com> + + * gimple-pretty-print.cc (dump_gimple_omp_target): Print expanded + iterator loops. + * gimple.cc (gimple_build_omp_target): Add argument for iterator + loops sequence. Initialize iterator loops field. + * gimple.def (GIMPLE_OMP_TARGET): Set GSS symbol to GSS_OMP_TARGET. + * gimple.h (gomp_target): Set GSS symbol to GSS_OMP_TARGET. Add extra + field for iterator loops. + (gimple_build_omp_target): Add argument for iterator loops sequence. + (gimple_omp_target_iterator_loops): New. + (gimple_omp_target_iterator_loops_ptr): New. + (gimple_omp_target_set_iterator_loops): New. + * gimplify.cc (find_var_decl): New. + (copy_omp_iterator): New. + (remap_omp_iterator_var_1): New. + (remap_omp_iterator_var): New. + (remove_unused_omp_iterator_vars): New. + (struct iterator_loop_info_t): New type. + (iterator_loop_info_map_t): New type. + (build_omp_iterators_loops): New. + (enter_omp_iterator_loop_context_1): New. + (enter_omp_iterator_loop_context): New. + (enter_omp_iterator_loop_context): New. + (exit_omp_iterator_loop_context): New. + (gimplify_adjust_omp_clauses): Add argument for iterator loop + sequence. Gimplify the clause decl and size into the iterator + loop if iterators are used. + (gimplify_omp_workshare): Call remove_unused_omp_iterator_vars and + build_omp_iterators_loops for OpenMP target expressions. Add + loop sequence as argument when calling gimplify_adjust_omp_clauses + and building the Gimple statement. + * gimplify.h (enter_omp_iterator_loop_context): New prototype. + (exit_omp_iterator_loop_context): New prototype. + * gsstruct.def (GSS_OMP_TARGET): New. + * omp-low.cc (lower_omp_map_iterator_expr): New. + (lower_omp_map_iterator_size): New. + (finish_omp_map_iterators): New. + (lower_omp_target): Add sorry if iterators used with deep mapping. + Call lower_omp_map_iterator_expr before assigning to sender ref. + Call lower_omp_map_iterator_size before setting the size. Insert + iterator loop sequence before the statements for the target clause. + * tree-nested.cc (convert_nonlocal_reference_stmt): Walk the iterator + loop sequence of OpenMP target statements. + (convert_local_reference_stmt): Likewise. + (convert_tramp_reference_stmt): Likewise. + * tree-pretty-print.cc (dump_omp_iterators): Dump extra iterator + information if present. + (dump_omp_clause): Call dump_omp_iterators for iterators in map + clauses. + * tree.cc (omp_clause_num_ops): Add operand for OMP_CLAUSE_MAP. + (walk_tree_1): Do not walk last operand of OMP_CLAUSE_MAP. + * tree.h (OMP_CLAUSE_HAS_ITERATORS): New. + (OMP_CLAUSE_ITERATORS): New. + 2025-08-05 H.J. Lu <hjl.tools@gmail.com> PR target/121410 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index cf43af9..d4024d7 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20250806 +20250807 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index d7d5cbe..cc79595 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -187,8 +187,6 @@ C_STRICT_WARN = @c_strict_warn@ NOEXCEPTION_FLAGS = @noexception_flags@ -ALIASING_FLAGS = @aliasing_flags@ - # This is set by --disable-maintainer-mode (default) to "#" # FIXME: 'MAINT' will always be set to an empty string, no matter if # --disable-maintainer-mode is used or not. This is because the @@ -3402,6 +3400,9 @@ gengtype-lex.cc : gengtype-lex.l echo '#else' >> $@.tmp; \ echo '#include "bconfig.h"' >> $@.tmp; \ echo '#endif' >> $@.tmp; \ + echo '#define FLEX_SCANNER' >> $@.tmp; \ + echo '#include "system.h"' >> $@.tmp; \ + echo '#undef FLEX_SCANNER' >> $@.tmp; \ cat $@ >> $@.tmp; \ mv $@.tmp $@; \ } diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index c9ab153..2abe6df 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2025-08-06 Alexandre Oliva <oliva@adacore.com> + + * c-attribs.cc (handle_hardbool_attribute): Create distinct + enumeration types, with structural equality. Handle + base type qualifiers. + 2025-08-02 Martin Uecker <uecker@tugraz.at> * c-attribs.cc (handle_argspec_attribute): Update. diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index a0d832b..041a004 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -1128,11 +1128,16 @@ handle_hardbool_attribute (tree *node, tree name, tree args, } tree orig = *node; - *node = build_duplicate_type (orig); + /* Drop qualifiers from the base type. Keep attributes, so that, in the odd + chance attributes are applicable and relevant to the base type, if they + are specified first, or through a typedef, they wouldn't be dropped on the + floor here. */ + tree unqual = build_qualified_type (orig, TYPE_UNQUALIFIED); + *node = build_distinct_type_copy (unqual); TREE_SET_CODE (*node, ENUMERAL_TYPE); - ENUM_UNDERLYING_TYPE (*node) = orig; - TYPE_CANONICAL (*node) = TYPE_CANONICAL (orig); + ENUM_UNDERLYING_TYPE (*node) = unqual; + SET_TYPE_STRUCTURAL_EQUALITY (*node); tree false_value; if (args) @@ -1191,7 +1196,13 @@ handle_hardbool_attribute (tree *node, tree name, tree args, gcc_checking_assert (!TYPE_CACHED_VALUES_P (*node)); TYPE_VALUES (*node) = values; - TYPE_NAME (*node) = orig; + TYPE_NAME (*node) = unqual; + + if (TYPE_QUALS (orig) != TYPE_QUALS (*node)) + { + *node = build_qualified_type (*node, TYPE_QUALS (orig)); + TYPE_NAME (*node) = orig; + } return NULL_TREE; } diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 464e5a1..2e5c896 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,45 @@ +2025-08-06 Alexandre Oliva <oliva@adacore.com> + + * c-tree.h (C_BOOLEAN_TYPE_P): Cover hardbools as well. + * c-typeck.cc (convert_lvalue_to_rvalue): New overload and + wrapper. + (build_atomic_assign, build_modify_expr): Use it. + (build_asm_expr, handle_omp-array_sections_1): Simplify with + it. + (build_unary_op): Handle hardbools. + +2025-08-06 Martin Uecker <uecker@tugraz.at> + + PR c/108931 + * c-typeck.cc (composite_type_cond): Renamed from + composite_type with argument for condition + (composite_type): New function. + (composite_type_internal): Implement new logic. + (build_conditional_expr): Pass condition. + (common_pointer_type): Adapt. + (pointer_diff): Adapt. + (build_binary_op): Adapt. + +2025-08-06 Martin Uecker <uecker@tugraz.at> + + PR c/121217 + * c-typeck.cc (tagged_types_tu_compatible_p): Add check. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + + * c-parser.cc (c_parser_omp_clause_from_to): Parse 'iterator' modifier. + * c-typeck.cc (c_finish_omp_clauses): Finish iterators for to/from + clauses. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + Andrew Stubbs <ams@baylibre.com> + + * c-parser.cc (c_parser_omp_variable_list): Use location of the + map expression as the clause location. + (c_parser_omp_clause_map): Parse 'iterator' modifier. + * c-typeck.cc (c_finish_omp_clauses): Finish iterators. Apply + iterators to generated clauses. + 2025-08-02 Martin Uecker <uecker@tugraz.at> * c-decl.cc (get_parm_array_spec): Remove. diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 5ddeeb2..814accf 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -20576,8 +20576,11 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list) to ( variable-list ) OpenMP 5.1: - from ( [present :] variable-list ) - to ( [present :] variable-list ) */ + from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + + motion-modifier: + present | iterator (iterators-definition) */ static tree c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, @@ -20588,18 +20591,85 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, if (!parens.require_open (parser)) return list; + int pos = 1, colon_pos = 0; + int iterator_length = 0; + + while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME) + { + const char *identifier = + IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value); + if (c_parser_peek_nth_token_raw (parser, pos + 1)->type + == CPP_OPEN_PAREN) + { + unsigned int npos = pos + 2; + if (c_parser_check_balanced_raw_token_sequence (parser, &npos) + && (c_parser_peek_nth_token_raw (parser, npos)->type + == CPP_CLOSE_PAREN)) + { + if (strcmp (identifier, "iterator") == 0) + iterator_length = npos - pos + 1; + pos = npos; + } + } + if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA) + pos += 2; + else + pos++; + if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON) + { + colon_pos = pos; + break; + } + } + bool present = false; - c_token *token = c_parser_peek_token (parser); + tree iterators = NULL_TREE; - if (token->type == CPP_NAME - && strcmp (IDENTIFIER_POINTER (token->value), "present") == 0 - && c_parser_peek_2nd_token (parser)->type == CPP_COLON) + for (int pos = 1; pos < colon_pos; ++pos) { - present = true; - c_parser_consume_token (parser); - c_parser_consume_token (parser); + c_token *token = c_parser_peek_token (parser); + if (token->type == CPP_COMMA) + { + c_parser_consume_token (parser); + continue; + } + const char *p = IDENTIFIER_POINTER (token->value); + if (strcmp ("present", p) == 0) + { + if (present) + { + c_parser_error (parser, "too many %<present%> modifiers"); + parens.skip_until_found_close (parser); + return list; + } + present = true; + c_parser_consume_token (parser); + } + else if (strcmp ("iterator", p) == 0) + { + if (iterators) + { + c_parser_error (parser, "too many %<iterator%> modifiers"); + parens.skip_until_found_close (parser); + return list; + } + iterators = c_parser_omp_iterators (parser); + pos += iterator_length - 1; + } + else + { + error_at (token->location, + "%qs clause with modifier other than %<iterator%> or " + "%<present%>", + kind == OMP_CLAUSE_TO ? "to" : "from"); + parens.skip_until_found_close (parser); + return list; + } } + if (colon_pos) + c_parser_require (parser, CPP_COLON, "expected %<:%>"); + tree nl = c_parser_omp_variable_list (parser, loc, kind, list); parens.skip_until_found_close (parser); @@ -20607,6 +20677,19 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_MOTION_PRESENT (c) = 1; + if (iterators) + { + tree block = pop_scope (); + if (iterators == error_mark_node) + iterators = NULL_TREE; + else + TREE_VEC_ELT (iterators, 5) = block; + } + + if (iterators) + for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ITERATORS (c) = iterators; + return nl; } diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index bb0b113..dba94ab 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -163,7 +163,8 @@ along with GCC; see the file COPYING3. If not see (TREE_CODE (TYPE) == BOOLEAN_TYPE \ || (TREE_CODE (TYPE) == ENUMERAL_TYPE \ && ENUM_UNDERLYING_TYPE (TYPE) != NULL_TREE \ - && TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE)) + && (TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE \ + || c_hardbool_type_attr (TYPE)))) /* Record parser information about an expression that is irrelevant for code generation alongside a tree representing its value. */ diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 6c8df7d..7a95f72 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -641,7 +641,8 @@ struct composite_cache { }; tree -composite_type_internal (tree t1, tree t2, struct composite_cache* cache) +composite_type_internal (tree t1, tree t2, tree cond, + struct composite_cache* cache) { enum tree_code code1; enum tree_code code2; @@ -686,8 +687,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) { tree pointed_to_1 = TREE_TYPE (t1); tree pointed_to_2 = TREE_TYPE (t2); - tree target = composite_type_internal (pointed_to_1, - pointed_to_2, cache); + tree target = composite_type_internal (pointed_to_1, pointed_to_2, + cond, cache); t1 = c_build_pointer_type_for_mode (target, TYPE_MODE (t1), false); t1 = c_build_type_attribute_variant (t1, attributes); return qualify_type (t1, t2); @@ -695,25 +696,20 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) case ARRAY_TYPE: { - tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2), - cache); - int quals; - tree unqual_elt; tree d1 = TYPE_DOMAIN (t1); tree d2 = TYPE_DOMAIN (t2); - bool d1_variable, d2_variable; - bool d1_zero, d2_zero; - bool t1_complete, t2_complete; /* We should not have any type quals on arrays at all. */ gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1) && !TYPE_QUALS_NO_ADDR_SPACE (t2)); - t1_complete = COMPLETE_TYPE_P (t1); - t2_complete = COMPLETE_TYPE_P (t2); + bool t1_complete = COMPLETE_TYPE_P (t1); + bool t2_complete = COMPLETE_TYPE_P (t2); - d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1); - d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2); + bool d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1); + bool d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2); + + bool d1_variable, d2_variable; d1_variable = (!d1_zero && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST @@ -722,10 +718,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); - bool use1 = TYPE_DOMAIN (t1) - && (d2_variable || d2_zero || !d1_variable); - bool use2 = TYPE_DOMAIN (t2) - && (d1_variable || d1_zero || !d2_variable); + bool use1 = d1 && (d2_variable || d2_zero || !d1_variable); + bool use2 = d2 && (d1_variable || d1_zero || !d2_variable); /* If the first is an unspecified size pick the other one. */ if (d2_variable && c_type_unspecified_p (t1)) @@ -734,25 +728,53 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) use1 = false; } - /* Save space: see if the result is identical to one of the args. */ - if (elt == TREE_TYPE (t1) && use1) - return c_build_type_attribute_variant (t1, attributes); - if (elt == TREE_TYPE (t2) && use2) - return c_build_type_attribute_variant (t2, attributes); + /* If both are VLAs but not unspecified and we are in the + conditional operator, we create a conditional to select + the size of the active branch. */ + bool use0 = cond && d1_variable && !c_type_unspecified_p (t1) + && d2_variable && !c_type_unspecified_p (t2); + + tree td; + tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2), + cond, cache); + + if (!use0) + { + /* Save space: see if the result is identical to one of the args. */ + if (elt == TREE_TYPE (t1) && use1) + return c_build_type_attribute_variant (t1, attributes); + if (elt == TREE_TYPE (t2) && use2) + return c_build_type_attribute_variant (t2, attributes); + + if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) + return c_build_type_attribute_variant (t1, attributes); + if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) + return c_build_type_attribute_variant (t2, attributes); + + td = TYPE_DOMAIN (use1 ? t1 : t2); + } + else + { + /* Not used in C. */ + gcc_assert (size_zero_node == TYPE_MIN_VALUE (d1)); + gcc_assert (size_zero_node == TYPE_MIN_VALUE (d2)); - if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) - return c_build_type_attribute_variant (t1, attributes); - if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) - return c_build_type_attribute_variant (t2, attributes); + tree d = fold_build3_loc (UNKNOWN_LOCATION, COND_EXPR, sizetype, + cond, TYPE_MAX_VALUE (d1), + TYPE_MAX_VALUE (d2)); + + td = build_index_type (d); + } /* Merge the element types, and have a size if either arg has one. We may have qualifiers on the element types. To set up TYPE_MAIN_VARIANT correctly, we need to form the composite of the unqualified types and add the qualifiers back at the end. */ - quals = TYPE_QUALS (strip_array_types (elt)); - unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); - t1 = c_build_array_type (unqual_elt, TYPE_DOMAIN (use1 ? t1 : t2)); + int quals = TYPE_QUALS (strip_array_types (elt)); + tree unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); + + t1 = c_build_array_type (unqual_elt, td); /* Check that a type which has a varying outermost dimension got marked has having a variable size. */ @@ -819,7 +841,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) gcc_assert (DECL_NAME (a) == DECL_NAME (b)); gcc_checking_assert (!DECL_NAME (a) || comptypes (ta, tb)); - tree t = composite_type_internal (ta, tb, cache); + tree t = composite_type_internal (ta, tb, cond, cache); tree f = build_decl (input_location, FIELD_DECL, DECL_NAME (a), t); DECL_PACKED (f) = DECL_PACKED (a); @@ -876,8 +898,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) /* Function types: prefer the one that specified arg types. If both do, merge the arg types. Also merge the return types. */ { - tree valtype = composite_type_internal (TREE_TYPE (t1), - TREE_TYPE (t2), cache); + tree valtype = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2), + cond, cache); tree p1 = TYPE_ARG_TYPES (t1); tree p2 = TYPE_ARG_TYPES (t2); int len; @@ -956,7 +978,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) { TREE_VALUE (n) = composite_type_internal (TREE_TYPE (memb), TREE_VALUE (p2), - cache); + cond, cache); pedwarn (input_location, OPT_Wpedantic, "function types not truly compatible in ISO C"); goto parm_done; @@ -979,14 +1001,14 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) TREE_VALUE (n) = composite_type_internal (TREE_TYPE (memb), TREE_VALUE (p1), - cache); + cond, cache); pedwarn (input_location, OPT_Wpedantic, "function types not truly compatible in ISO C"); goto parm_done; } } } - TREE_VALUE (n) = composite_type_internal (mv1, mv2, cache); + TREE_VALUE (n) = composite_type_internal (mv1, mv2, cond, cache); parm_done: ; } @@ -1001,18 +1023,25 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) } tree -composite_type (tree t1, tree t2) +composite_type_cond (tree t1, tree t2, tree cond) { gcc_checking_assert (comptypes_check_for_composite (t1, t2)); struct composite_cache cache = { }; - tree n = composite_type_internal (t1, t2, &cache); + tree n = composite_type_internal (t1, t2, cond, &cache); gcc_checking_assert (comptypes_check_for_composite (n, t1)); gcc_checking_assert (comptypes_check_for_composite (n, t2)); return n; } + +tree +composite_type (tree t1, tree t2) +{ + return composite_type_cond (t1, t2, NULL_TREE); +} + /* Return the type of a conditional expression between pointers to possibly differently qualified versions of compatible types. @@ -1020,7 +1049,7 @@ composite_type (tree t1, tree t2) true; if that isn't so, this may crash. */ static tree -common_pointer_type (tree t1, tree t2) +common_pointer_type (tree t1, tree t2, tree cond) { tree attributes; unsigned target_quals; @@ -1047,8 +1076,8 @@ common_pointer_type (tree t1, tree t2) qualifiers of the two types' targets. */ tree pointed_to_1 = TREE_TYPE (t1); tree pointed_to_2 = TREE_TYPE (t2); - tree target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1), - TYPE_MAIN_VARIANT (pointed_to_2)); + tree target = composite_type_cond (TYPE_MAIN_VARIANT (pointed_to_1), + TYPE_MAIN_VARIANT (pointed_to_2), cond); /* Strip array types to get correct qualifier for pointers to arrays */ quals1 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_1)); @@ -1970,6 +1999,9 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, ft2 = DECL_BIT_FIELD_TYPE (s2); } + if (!ft1 || !ft2) + return false; + if (TREE_CODE (ft1) == ERROR_MARK || TREE_CODE (ft2) == ERROR_MARK) return false; @@ -2648,6 +2680,20 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp, return exp; } +/* Wrapper for the overload above, same arguments but for tree rather than + c_expr. This is important for hardbools to decay to bools. */ + +static inline tree +convert_lvalue_to_rvalue (location_t loc, tree val, + bool convert_p, bool read_p, bool for_init = false) +{ + struct c_expr expr; + memset (&expr, 0, sizeof (expr)); + expr.value = val; + expr = convert_lvalue_to_rvalue (loc, expr, convert_p, read_p, for_init); + return expr.value; +} + /* EXP is an expression of integer type. Apply the integer promotions to it and return the promoted value. */ @@ -4926,7 +4972,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr) if (!addr_space_superset (as0, as1, &as_common)) gcc_unreachable (); - common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1)); + common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1), NULL_TREE); op0 = convert (common_type, op0); op1 = convert (common_type, op1); } @@ -5271,7 +5317,9 @@ cas_loop: /* newval = old + val; */ if (rhs_type != rhs_semantic_type) val = build1 (EXCESS_PRECISION_EXPR, nonatomic_rhs_semantic_type, val); - rhs = build_binary_op (loc, modifycode, old, val, true); + rhs = build_binary_op (loc, modifycode, + convert_lvalue_to_rvalue (loc, old, true, true), + val, true); if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR) { tree eptype = TREE_TYPE (rhs); @@ -5727,7 +5775,48 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, goto return_build_unary_op; } - if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg))) + tree true_res; + if (c_hardbool_type_attr (TREE_TYPE (arg), NULL, &true_res)) + { + tree larg = stabilize_reference (arg); + tree sarg = save_expr (larg); + switch (code) + { + case PREINCREMENT_EXPR: + val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val); + break; + case POSTINCREMENT_EXPR: + val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val); + break; + case PREDECREMENT_EXPR: + { + tree rarg = convert_lvalue_to_rvalue (location, sarg, + true, true); + rarg = invert_truthvalue_loc (location, rarg); + rarg = convert (TREE_TYPE (sarg), rarg); + val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, rarg); + } + break; + case POSTDECREMENT_EXPR: + { + tree rarg = convert_lvalue_to_rvalue (location, sarg, + true, true); + rarg = invert_truthvalue_loc (location, rarg); + tree iarg = convert (TREE_TYPE (larg), rarg); + val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, iarg); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val); + } + break; + default: + gcc_unreachable (); + } + TREE_SIDE_EFFECTS (val) = 1; + } + else if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg))) val = boolean_increment (code, arg); else val = build2 (code, TREE_TYPE (arg), arg, inc); @@ -6380,7 +6469,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, addr_space_t as_common; if (comp_target_types (colon_loc, type1, type2)) - result_type = common_pointer_type (type1, type2); + { + ifexp = save_expr (ifexp); + result_type = common_pointer_type (type1, type2, ifexp); + } else if (null_pointer_constant_p (orig_op1)) result_type = type2; else if (null_pointer_constant_p (orig_op2)) @@ -7337,8 +7429,10 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, clear_decl_read = true; } - newrhs = build_binary_op (location, - modifycode, lhs, newrhs, true); + newrhs = build_binary_op (location, modifycode, + convert_lvalue_to_rvalue (location, lhs, + true, true), + newrhs, true); if (clear_decl_read) DECL_READ_P (lhs) = 0; @@ -12730,11 +12824,9 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, } else { - struct c_expr expr; - memset (&expr, 0, sizeof (expr)); - expr.value = input; - expr = convert_lvalue_to_rvalue (loc, expr, true, false); - input = c_fully_fold (expr.value, false, NULL); + input = c_fully_fold (convert_lvalue_to_rvalue (loc, input, + true, false), + false, NULL); if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input))) { @@ -14390,7 +14482,7 @@ build_binary_op (location_t location, enum tree_code code, Otherwise, the targets must be compatible and both must be object or both incomplete. */ if (comp_target_types (location, type0, type1)) - result_type = common_pointer_type (type0, type1); + result_type = common_pointer_type (type0, type1, NULL_TREE); else if (!addr_space_superset (as0, as1, &as_common)) { error_at (location, "comparison of pointers to " @@ -14529,7 +14621,7 @@ build_binary_op (location_t location, enum tree_code code, if (comp_target_types (location, type0, type1)) { - result_type = common_pointer_type (type0, type1); + result_type = common_pointer_type (type0, type1, NULL_TREE); if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) != !COMPLETE_TYPE_P (TREE_TYPE (type1))) pedwarn_c99 (location, OPT_Wpedantic, @@ -15356,12 +15448,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, /* If the array section is pointer based and the pointer itself is _Atomic qualified, we need to atomically load the pointer. */ - c_expr expr; - memset (&expr, 0, sizeof (expr)); - expr.value = ret; - expr = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c), - expr, false, false); - ret = expr.value; + ret = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c), + ret, false, false); } return ret; } @@ -16966,6 +17054,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; break; } + /* FALLTHRU */ + case OMP_CLAUSE_TO: + case OMP_CLAUSE_FROM: if (OMP_CLAUSE_ITERATORS (c) && c_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c))) { @@ -16973,8 +17064,6 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; } /* FALLTHRU */ - case OMP_CLAUSE_TO: - case OMP_CLAUSE_FROM: case OMP_CLAUSE__CACHE_: { using namespace omp_addr_tokenizer; diff --git a/gcc/common.opt b/gcc/common.opt index 70659fa..bf38f60 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1067,6 +1067,8 @@ Driver Undocumented ; ; 21: Fix noexcept lambda capture pruning. ; Fix C++20 layout of base with all explicitly defaulted constructors. +; Fix mangling of class and array objects with implicitly +; zero-initialized non-trailing subojects. ; Default in G++ 16. ; ; Additional positive integers will be assigned as new versions of diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index da3cb9f..f2ede07 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -1758,6 +1758,11 @@ riscv_expand_arch (int argc, { gcc_assert (argc == 1); location_t loc = UNKNOWN_LOCATION; + + /* Filter out -march=unset, it will expand from -mcpu later. */ + if (strcmp (argv[0], "unset") == 0) + return ""; + /* Try to interpret the arch as CPU first. */ const char *arch_str = riscv_expand_arch_from_cpu (argc, argv); if (!strlen (arch_str)) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 791f3b9..49af963 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2477,9 +2477,9 @@ constexpr wide_int_bitmask PTA_DIAMONDRAPIDS = PTA_GRANITERAPIDS_D | PTA_MOVRS | PTA_AMX_MOVRS | PTA_USER_MSR; constexpr wide_int_bitmask PTA_BDVER1 = PTA_64BIT | PTA_MMX | PTA_SSE - | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 - | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4 - | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE; + | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_POPCNT | PTA_LZCNT + | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL + | PTA_AVX | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE; constexpr wide_int_bitmask PTA_BDVER2 = PTA_BDVER1 | PTA_BMI | PTA_TBM | PTA_F16C | PTA_FMA; constexpr wide_int_bitmask PTA_BDVER3 = PTA_BDVER2 | PTA_XSAVEOPT @@ -2487,13 +2487,13 @@ constexpr wide_int_bitmask PTA_BDVER3 = PTA_BDVER2 | PTA_XSAVEOPT constexpr wide_int_bitmask PTA_BDVER4 = PTA_BDVER3 | PTA_AVX2 | PTA_BMI2 | PTA_RDRND | PTA_MOVBE | PTA_MWAITX; -constexpr wide_int_bitmask PTA_ZNVER1 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 - | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 - | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2 | PTA_BMI | PTA_BMI2 - | PTA_F16C | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT - | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE | PTA_MWAITX | PTA_ADX | PTA_RDSEED - | PTA_CLZERO | PTA_CLFLUSHOPT | PTA_XSAVEC | PTA_XSAVES | PTA_SHA | PTA_LZCNT - | PTA_POPCNT; +constexpr wide_int_bitmask PTA_ZNVER1 = PTA_64BIT | PTA_MMX | PTA_SSE + | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_POPCNT | PTA_LZCNT + | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL + | PTA_AVX | PTA_AVX2 | PTA_BMI | PTA_BMI2 | PTA_F16C | PTA_FMA | PTA_PRFCHW + | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE + | PTA_MWAITX | PTA_ADX | PTA_RDSEED | PTA_CLZERO | PTA_CLFLUSHOPT + | PTA_XSAVEC | PTA_XSAVES | PTA_SHA; constexpr wide_int_bitmask PTA_ZNVER2 = PTA_ZNVER1 | PTA_CLWB | PTA_RDPID | PTA_WBNOINVD; constexpr wide_int_bitmask PTA_ZNVER3 = PTA_ZNVER2 | PTA_VAES | PTA_VPCLMULQDQ @@ -2506,19 +2506,19 @@ constexpr wide_int_bitmask PTA_ZNVER5 = PTA_ZNVER4 | PTA_AVXVNNI | PTA_MOVDIRI | PTA_MOVDIR64B | PTA_AVX512VP2INTERSECT | PTA_PREFETCHI; constexpr wide_int_bitmask PTA_BTVER1 = PTA_64BIT | PTA_MMX | PTA_SSE - | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4A | PTA_ABM | PTA_CX16 - | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE; + | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4A | PTA_LZCNT | PTA_POPCNT + | PTA_ABM | PTA_CX16 | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE; constexpr wide_int_bitmask PTA_BTVER2 = PTA_BTVER1 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_BMI | PTA_F16C | PTA_MOVBE | PTA_XSAVEOPT; constexpr wide_int_bitmask PTA_LUJIAZUI = PTA_64BIT | PTA_MMX | PTA_SSE - | PTA_SSE2 | PTA_SSE3 | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 - | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_BMI | PTA_BMI2 | PTA_PRFCHW - | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE - | PTA_ADX | PTA_RDSEED | PTA_POPCNT; + | PTA_SSE2 | PTA_SSE3 | PTA_CX16 | PTA_LZCNT | PTA_POPCNT | PTA_ABM + | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_BMI + | PTA_BMI2 | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE + | PTA_RDRND | PTA_MOVBE | PTA_ADX | PTA_RDSEED; constexpr wide_int_bitmask PTA_YONGFENG = PTA_LUJIAZUI | PTA_AVX | PTA_AVX2 - | PTA_F16C | PTA_FMA | PTA_SHA | PTA_LZCNT; + | PTA_F16C | PTA_FMA | PTA_SHA; #ifndef GENERATOR_FILE diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 2b0dd66..6686f10 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -18298,17 +18298,17 @@ (any_rotate:SWI (match_operand:SWI 1 "const_int_operand") (subreg:QI - (and - (match_operand 2 "int248_register_operand") - (match_operand 3 "const_int_operand")) 0)))] + (match_operator 4 "and_operator" + [(match_operand 2 "int248_register_operand") + (match_operand 3 "const_int_operand")]) 0)))] "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == GET_MODE_BITSIZE (<MODE>mode) - 1" - [(set (match_dup 4) (match_dup 1)) + [(set (match_dup 5) (match_dup 1)) (set (match_dup 0) - (any_rotate:SWI (match_dup 4) + (any_rotate:SWI (match_dup 5) (subreg:QI - (and:SI (match_dup 2) (match_dup 3)) 0)))] - "operands[4] = gen_reg_rtx (<MODE>mode);") + (match_op_dup 4 [(match_dup 2) (match_dup 3)]) 0)))] + "operands[5] = gen_reg_rtx (<MODE>mode);") (define_insn_and_split "*<insn><mode>3_mask_1" [(set (match_operand:SWI 0 "nonimmediate_operand") diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 0f31090..175798c 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1714,10 +1714,14 @@ (define_predicate "div_operator" (match_code "div")) -;; Return true if this is a and, ior or xor operation. +;; Return true if this is an and, ior or xor operation. (define_predicate "logic_operator" (match_code "and,ior,xor")) +;; Return true if this is an and operation. +(define_predicate "and_operator" + (match_code "and")) + ;; Return true if this is a plus, minus, and, ior or xor operation. (define_predicate "plusminuslogic_operator" (match_code "plus,minus,and,ior,xor")) diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize index 34dad45..5d24f5ed 100755 --- a/gcc/config/riscv/arch-canonicalize +++ b/gcc/config/riscv/arch-canonicalize @@ -20,77 +20,314 @@ # along with GCC; see the file COPYING3. If not see # <http://www.gnu.org/licenses/>. -# TODO: Extract riscv_subset_t from riscv-common.cc and make it can be compiled -# standalone to replace this script, that also prevents us implementing -# that twice and keep sync again and again. - from __future__ import print_function import sys import argparse import collections import itertools +import re +import os from functools import reduce SUPPORTED_ISA_SPEC = ["2.2", "20190608", "20191213"] CANONICAL_ORDER = "imafdqlcbkjtpvnh" LONG_EXT_PREFIXES = ['z', 's', 'h', 'x'] +def parse_define_riscv_ext(content): + """Parse DEFINE_RISCV_EXT macros using position-based parsing.""" + extensions = [] + + # Find all DEFINE_RISCV_EXT blocks + pattern = r'DEFINE_RISCV_EXT\s*\(' + matches = [] + + pos = 0 + while True: + match = re.search(pattern, content[pos:]) + if not match: + break + + start_pos = pos + match.start() + paren_count = 0 + current_pos = pos + match.end() - 1 # Start at the opening parenthesis + + # Find the matching closing parenthesis + while current_pos < len(content): + if content[current_pos] == '(': + paren_count += 1 + elif content[current_pos] == ')': + paren_count -= 1 + if paren_count == 0: + break + current_pos += 1 + + if paren_count == 0: + # Extract the content inside parentheses + macro_content = content[pos + match.end():current_pos] + ext_data = parse_macro_arguments(macro_content) + if ext_data: + extensions.append(ext_data) + + pos = current_pos + 1 + + return extensions + +def parse_macro_arguments(macro_content): + """Parse the arguments of a DEFINE_RISCV_EXT macro.""" + # Remove comments /* ... */ + cleaned_content = re.sub(r'/\*[^*]*\*/', '', macro_content) + + # Split arguments by comma, but respect nested structures + args = [] + current_arg = "" + paren_count = 0 + brace_count = 0 + in_string = False + escape_next = False + + for char in cleaned_content: + if escape_next: + current_arg += char + escape_next = False + continue + + if char == '\\': + escape_next = True + current_arg += char + continue + + if char == '"' and not escape_next: + in_string = not in_string + current_arg += char + continue + + if in_string: + current_arg += char + continue + + if char == '(': + paren_count += 1 + elif char == ')': + paren_count -= 1 + elif char == '{': + brace_count += 1 + elif char == '}': + brace_count -= 1 + elif char == ',' and paren_count == 0 and brace_count == 0: + args.append(current_arg.strip()) + current_arg = "" + continue + + current_arg += char + + # Add the last argument + if current_arg.strip(): + args.append(current_arg.strip()) + + # We need at least 6 arguments to get DEP_EXTS (position 5) + if len(args) < 6: + return None + + ext_name = args[0].strip() + dep_exts_arg = args[5].strip() # DEP_EXTS is at position 5 + + # Parse dependency extensions from the DEP_EXTS argument + deps = parse_dep_exts(dep_exts_arg) + + return { + 'name': ext_name, + 'dep_exts': deps + } + +def parse_dep_exts(dep_exts_str): + """Parse the DEP_EXTS argument to extract dependency list with conditions.""" + # Remove outer parentheses if present + dep_exts_str = dep_exts_str.strip() + if dep_exts_str.startswith('(') and dep_exts_str.endswith(')'): + dep_exts_str = dep_exts_str[1:-1].strip() + + # Remove outer braces if present + if dep_exts_str.startswith('{') and dep_exts_str.endswith('}'): + dep_exts_str = dep_exts_str[1:-1].strip() + + if not dep_exts_str: + return [] + + deps = [] + + # First, find and process conditional dependencies + conditional_pattern = r'\{\s*"([^"]+)"\s*,\s*(\[.*?\]\s*\([^)]*\)\s*->\s*bool.*?)\}' + conditional_matches = [] + + for match in re.finditer(conditional_pattern, dep_exts_str, re.DOTALL): + ext_name = match.group(1) + condition_code = match.group(2) + deps.append({'ext': ext_name, 'type': 'conditional', 'condition': condition_code}) + conditional_matches.append((match.start(), match.end())) + + # Remove conditional dependency blocks from the string + remaining_str = dep_exts_str + for start, end in reversed(conditional_matches): # Reverse order to maintain indices + remaining_str = remaining_str[:start] + remaining_str[end:] + + # Now handle simple quoted strings in the remaining text + for match in re.finditer(r'"([^"]+)"', remaining_str): + deps.append({'ext': match.group(1), 'type': 'simple'}) + + # Remove duplicates while preserving order + seen = set() + unique_deps = [] + for dep in deps: + key = (dep['ext'], dep['type']) + if key not in seen: + seen.add(key) + unique_deps.append(dep) + + return unique_deps + +def evaluate_conditional_dependency(ext, dep, xlen, current_exts): + """Evaluate whether a conditional dependency should be included.""" + ext_name = dep['ext'] + condition = dep['condition'] + # Parse the condition based on known patterns + if ext_name == 'zcf' and ext in ['zca', 'c', 'zce']: + # zcf depends on RV32 and F extension + return xlen == 32 and 'f' in current_exts + elif ext_name == 'zcd' and ext in ['zca', 'c']: + # zcd depends on D extension + return 'd' in current_exts + elif ext_name == 'c' and ext in ['zca']: + # Special case for zca -> c conditional dependency + if xlen == 32: + if 'd' in current_exts: + return 'zcf' in current_exts and 'zcd' in current_exts + elif 'f' in current_exts: + return 'zcf' in current_exts + else: + return True + elif xlen == 64: + if 'd' in current_exts: + return 'zcd' in current_exts + else: + return True + return False + else: + # Report error for unhandled conditional dependencies + import sys + print(f"ERROR: Unhandled conditional dependency: '{ext_name}' with condition:", file=sys.stderr) + print(f" Condition code: {condition[:100]}...", file=sys.stderr) + print(f" Current context: xlen={xlen}, exts={sorted(current_exts)}", file=sys.stderr) + # For now, return False to be safe + return False + +def resolve_dependencies(arch_parts, xlen): + """Resolve all dependencies including conditional ones.""" + current_exts = set(arch_parts) + implied_deps = set() + + # Keep resolving until no new dependencies are found + changed = True + while changed: + changed = False + new_deps = set() + + for ext in current_exts | implied_deps: + if ext in IMPLIED_EXT: + for dep in IMPLIED_EXT[ext]: + if dep['type'] == 'simple': + if dep['ext'] not in current_exts and dep['ext'] not in implied_deps: + new_deps.add(dep['ext']) + changed = True + elif dep['type'] == 'conditional': + should_include = evaluate_conditional_dependency(ext, dep, xlen, current_exts | implied_deps) + if should_include: + if dep['ext'] not in current_exts and dep['ext'] not in implied_deps: + new_deps.add(dep['ext']) + changed = True + + implied_deps.update(new_deps) + + return implied_deps + +def parse_def_file(file_path, script_dir, processed_files=None, collect_all=False): + """Parse a single .def file and recursively process #include directives.""" + if processed_files is None: + processed_files = set() + + # Avoid infinite recursion + if file_path in processed_files: + return ({}, set()) if collect_all else {} + processed_files.add(file_path) + + implied_ext = {} + all_extensions = set() if collect_all else None + + if not os.path.exists(file_path): + return (implied_ext, all_extensions) if collect_all else implied_ext + + with open(file_path, 'r') as f: + content = f.read() + + # Process #include directives first + include_pattern = r'#include\s+"([^"]+)"' + includes = re.findall(include_pattern, content) + + for include_file in includes: + include_path = os.path.join(script_dir, include_file) + if collect_all: + included_ext, included_all = parse_def_file(include_path, script_dir, processed_files, collect_all) + implied_ext.update(included_ext) + all_extensions.update(included_all) + else: + included_ext = parse_def_file(include_path, script_dir, processed_files, collect_all) + implied_ext.update(included_ext) + + # Parse DEFINE_RISCV_EXT blocks using position-based parsing + parsed_exts = parse_define_riscv_ext(content) + + for ext_data in parsed_exts: + ext_name = ext_data['name'] + deps = ext_data['dep_exts'] + + if collect_all: + all_extensions.add(ext_name) + + if deps: + implied_ext[ext_name] = deps + + return (implied_ext, all_extensions) if collect_all else implied_ext + +def parse_def_files(): + """Parse RISC-V extension definition files starting from riscv-ext.def.""" + # Get directory containing this script + try: + script_dir = os.path.dirname(os.path.abspath(__file__)) + except NameError: + # When __file__ is not defined (e.g., interactive mode) + script_dir = os.getcwd() + + # Start with the main definition file + main_def_file = os.path.join(script_dir, 'riscv-ext.def') + return parse_def_file(main_def_file, script_dir) + +def get_all_extensions(): + """Get all supported extensions and their implied extensions.""" + # Get directory containing this script + try: + script_dir = os.path.dirname(os.path.abspath(__file__)) + except NameError: + # When __file__ is not defined (e.g., interactive mode) + script_dir = os.getcwd() + + # Start with the main definition file + main_def_file = os.path.join(script_dir, 'riscv-ext.def') + return parse_def_file(main_def_file, script_dir, collect_all=True) + # # IMPLIED_EXT(ext) -> implied extension list. +# This is loaded dynamically from .def files # -IMPLIED_EXT = { - "d" : ["f", "zicsr"], - - "a" : ["zaamo", "zalrsc"], - "zabha" : ["zaamo"], - "zacas" : ["zaamo"], - - "f" : ["zicsr"], - "b" : ["zba", "zbb", "zbs"], - "zdinx" : ["zfinx", "zicsr"], - "zfinx" : ["zicsr"], - "zhinx" : ["zhinxmin", "zfinx", "zicsr"], - "zhinxmin" : ["zfinx", "zicsr"], - - "zk" : ["zkn", "zkr", "zkt"], - "zkn" : ["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"], - "zks" : ["zbkb", "zbkc", "zbkx", "zksed", "zksh"], - - "v" : ["zvl128b", "zve64d"], - "zve32x" : ["zvl32b"], - "zve64x" : ["zve32x", "zvl64b"], - "zve32f" : ["f", "zve32x"], - "zve64f" : ["f", "zve32f", "zve64x"], - "zve64d" : ["d", "zve64f"], - - "zvl64b" : ["zvl32b"], - "zvl128b" : ["zvl64b"], - "zvl256b" : ["zvl128b"], - "zvl512b" : ["zvl256b"], - "zvl1024b" : ["zvl512b"], - "zvl2048b" : ["zvl1024b"], - "zvl4096b" : ["zvl2048b"], - "zvl8192b" : ["zvl4096b"], - "zvl16384b" : ["zvl8192b"], - "zvl32768b" : ["zvl16384b"], - "zvl65536b" : ["zvl32768b"], - - "zvkn" : ["zvkned", "zvknhb", "zvkb", "zvkt"], - "zvknc" : ["zvkn", "zvbc"], - "zvkng" : ["zvkn", "zvkg"], - "zvks" : ["zvksed", "zvksh", "zvkb", "zvkt"], - "zvksc" : ["zvks", "zvbc"], - "zvksg" : ["zvks", "zvkg"], - "zvbb" : ["zvkb"], - "zvbc" : ["zve64x"], - "zvkb" : ["zve32x"], - "zvkg" : ["zve32x"], - "zvkned" : ["zve32x"], - "zvknha" : ["zve32x"], - "zvknhb" : ["zve64x"], - "zvksed" : ["zve32x"], - "zvksh" : ["zve32x"], -} +IMPLIED_EXT = parse_def_files() def arch_canonicalize(arch, isa_spec): # TODO: Support extension version. @@ -123,21 +360,31 @@ def arch_canonicalize(arch, isa_spec): long_exts += extra_long_ext # - # Handle implied extensions. + # Handle implied extensions using new conditional logic. # - any_change = True - while any_change: - any_change = False - for ext in std_exts + long_exts: - if ext in IMPLIED_EXT: - implied_exts = IMPLIED_EXT[ext] - for implied_ext in implied_exts: - if implied_ext == 'zicsr' and is_isa_spec_2p2: - continue + # Extract xlen from architecture string + # TODO: We should support profile here. + if arch.startswith('rv32'): + xlen = 32 + elif arch.startswith('rv64'): + xlen = 64 + else: + raise Exception("Unsupported prefix `%s`" % arch) - if implied_ext not in std_exts + long_exts: - long_exts.append(implied_ext) - any_change = True + # Get all current extensions + current_exts = std_exts + long_exts + + # Resolve dependencies + implied_deps = resolve_dependencies(current_exts, xlen) + + # Filter out zicsr for ISA spec 2.2 + if is_isa_spec_2p2: + implied_deps.discard('zicsr') + + # Add implied dependencies to long_exts + for dep in implied_deps: + if dep not in current_exts: + long_exts.append(dep) # Single letter extension might appear in the long_exts list, # because we just append extensions list to the arch string. @@ -179,17 +426,171 @@ def arch_canonicalize(arch, isa_spec): return new_arch -if len(sys.argv) < 2: - print ("Usage: %s <arch_str> [<arch_str>*]" % sys.argv) - sys.exit(1) +def dump_all_extensions(): + """Dump all extensions and their implied extensions.""" + implied_ext, all_extensions = get_all_extensions() -parser = argparse.ArgumentParser() -parser.add_argument('-misa-spec', type=str, - default='20191213', - choices=SUPPORTED_ISA_SPEC) -parser.add_argument('arch_strs', nargs=argparse.REMAINDER) + print("All supported RISC-V extensions:") + print("=" * 60) -args = parser.parse_args() + if not all_extensions: + print("No extensions found.") + return -for arch in args.arch_strs: - print (arch_canonicalize(arch, args.misa_spec)) + # Sort all extensions for consistent output + sorted_all = sorted(all_extensions) + + # Print all extensions with their dependencies (if any) + for ext_name in sorted_all: + if ext_name in implied_ext: + deps = implied_ext[ext_name] + dep_strs = [] + for dep in deps: + if dep['type'] == 'simple': + dep_strs.append(dep['ext']) + else: + dep_strs.append(f"{dep['ext']}*") # Mark conditional deps with * + print(f"{ext_name:15} -> {', '.join(dep_strs)}") + else: + print(f"{ext_name:15} -> (no dependencies)") + + print(f"\nTotal extensions: {len(all_extensions)}") + print(f"Extensions with dependencies: {len(implied_ext)}") + print(f"Extensions without dependencies: {len(all_extensions) - len(implied_ext)}") + +def run_unit_tests(): + """Run unit tests using pytest dynamically imported.""" + try: + import pytest + except ImportError: + print("Error: pytest is required for running unit tests.") + print("Please install pytest: pip install pytest") + return 1 + + # Define test functions + def test_basic_arch_parsing(): + """Test basic architecture string parsing.""" + result = arch_canonicalize("rv64i", "20191213") + assert result == "rv64i" + + def test_simple_extensions(): + """Test simple extension handling.""" + result = arch_canonicalize("rv64im", "20191213") + assert "zmmul" in result + + def test_implied_extensions(): + """Test implied extension resolution.""" + result = arch_canonicalize("rv64imaf", "20191213") + assert "zicsr" in result + + def test_conditional_dependencies(): + """Test conditional dependency evaluation.""" + # Test RV32 with F extension should include zcf when c is present + result = arch_canonicalize("rv32ifc", "20191213") + parts = result.split("_") + if "c" in parts: + assert "zca" in parts + if "f" in parts: + assert "zcf" in parts + + def test_parse_dep_exts(): + """Test dependency parsing function.""" + # Test simple dependency + deps = parse_dep_exts('{"ext1", "ext2"}') + assert len(deps) == 2 + assert deps[0]['ext'] == 'ext1' + assert deps[0]['type'] == 'simple' + + def test_evaluate_conditional_dependency(): + """Test conditional dependency evaluation.""" + # Test zcf condition for RV32 with F + dep = {'ext': 'zcf', 'type': 'conditional', 'condition': 'test'} + result = evaluate_conditional_dependency('zce', dep, 32, {'f'}) + assert result == True + + # Test zcf condition for RV64 with F (should be False) + result = evaluate_conditional_dependency('zce', dep, 64, {'f'}) + assert result == False + + def test_parse_define_riscv_ext(): + """Test DEFINE_RISCV_EXT parsing.""" + content = ''' + DEFINE_RISCV_EXT( + /* NAME */ test, + /* UPPERCASE_NAME */ TEST, + /* FULL_NAME */ "Test extension", + /* DESC */ "", + /* URL */ , + /* DEP_EXTS */ ({"dep1", "dep2"}), + /* SUPPORTED_VERSIONS */ ({{1, 0}}), + /* FLAG_GROUP */ test, + /* BITMASK_GROUP_ID */ 0, + /* BITMASK_BIT_POSITION*/ 0, + /* EXTRA_EXTENSION_FLAGS */ 0) + ''' + + extensions = parse_define_riscv_ext(content) + assert len(extensions) == 1 + assert extensions[0]['name'] == 'test' + assert len(extensions[0]['dep_exts']) == 2 + + # Collect test functions + test_functions = [ + test_basic_arch_parsing, + test_simple_extensions, + test_implied_extensions, + test_conditional_dependencies, + test_parse_dep_exts, + test_evaluate_conditional_dependency, + test_parse_define_riscv_ext + ] + + # Run tests manually first, then optionally with pytest + print("Running unit tests...") + + passed = 0 + failed = 0 + + for i, test_func in enumerate(test_functions): + try: + print(f" Running {test_func.__name__}...", end=" ") + test_func() + print("PASSED") + passed += 1 + except Exception as e: + print(f"FAILED: {e}") + failed += 1 + + print(f"\nTest Summary: {passed} passed, {failed} failed") + + if failed == 0: + print("\nAll tests passed!") + return 0 + else: + print(f"\n{failed} test(s) failed!") + return 1 + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('-misa-spec', type=str, + default='20191213', + choices=SUPPORTED_ISA_SPEC) + parser.add_argument('--dump-all', action='store_true', + help='Dump all extensions and their implied extensions') + parser.add_argument('--selftest', action='store_true', + help='Run unit tests using pytest') + parser.add_argument('arch_strs', nargs='*', + help='Architecture strings to canonicalize') + + args = parser.parse_args() + + if args.dump_all: + dump_all_extensions() + elif args.selftest: + sys.exit(run_unit_tests()) + elif args.arch_strs: + for arch in args.arch_strs: + print (arch_canonicalize(arch, args.misa_spec)) + else: + parser.print_help() + sys.exit(1) diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 45fa521..29342d8 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -71,7 +71,7 @@ extern const char *riscv_arch_help (int argc, const char **argv); {"tune", "%{!mtune=*:" \ " %{!mcpu=*:-mtune=%(VALUE)}" \ " %{mcpu=*:-mtune=%:riscv_default_mtune(%* %(VALUE))}}" }, \ - {"arch", "%{!march=*:" \ + {"arch", "%{!march=*|march=unset:" \ " %{!mcpu=*:-march=%(VALUE)}" \ " %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" }, \ {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \ @@ -111,13 +111,19 @@ extern const char *riscv_arch_help (int argc, const char **argv); %(subtarget_asm_spec)" \ ASM_MISA_SPEC +/* Drop all -march=* options before -march=unset. */ +#define ARCH_UNSET_CLEANUP_SPECS \ + "%{march=unset:%<march=*} " \ + #undef DRIVER_SELF_SPECS #define DRIVER_SELF_SPECS \ +ARCH_UNSET_CLEANUP_SPECS \ "%{march=help:%:riscv_arch_help()} " \ "%{print-supported-extensions:%:riscv_arch_help()} " \ "%{-print-supported-extensions:%:riscv_arch_help()} " \ "%{march=*:%:riscv_expand_arch(%*)} " \ -"%{!march=*:%{mcpu=*:%:riscv_expand_arch_from_cpu(%*)}} " +"%{!march=*|march=unset:%{mcpu=*:%:riscv_expand_arch_from_cpu(%*)}} " \ +"%{march=unset:%{!mcpu=*:%eAt least one valid -mcpu option must be given after -march=unset}} " #define LOCAL_LABEL_PREFIX "." #define USER_LABEL_PREFIX "" diff --git a/gcc/configure b/gcc/configure index bacdd29..cab9c75 100755 --- a/gcc/configure +++ b/gcc/configure @@ -872,7 +872,6 @@ c_strict_warn strict_warn c_loose_warn loose_warn -aliasing_flags CPP EGREP GREP @@ -7126,45 +7125,6 @@ $as_echo "#define HAVE_SWAP_IN_UTILITY 1" >>confdefs.h fi -# Check whether compiler is affected by placement new aliasing bug (PR 29286). -# If the host compiler is affected by the bug, and we build with optimization -# enabled (which happens e.g. when cross-compiling), the pool allocator may -# get miscompiled. Use -fno-strict-aliasing to work around this problem. -# Since there is no reliable feature check for the presence of this bug, -# we simply use a GCC version number check. (This should never trigger for -# stages 2 or 3 of a native bootstrap.) -aliasing_flags= -if test "$GCC" = yes; then - saved_CXXFLAGS="$CXXFLAGS" - - # The following test compilation will succeed if and only if $CXX accepts - # -fno-strict-aliasing *and* is older than GCC 4.3. - CXXFLAGS="$CXXFLAGS -fno-strict-aliasing" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX is affected by placement new aliasing bug" >&5 -$as_echo_n "checking whether $CXX is affected by placement new aliasing bug... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) -#error compiler not affected by placement new aliasing bug -#endif - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; }; aliasing_flags='-fno-strict-aliasing' -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - - CXXFLAGS="$saved_CXXFLAGS" -fi - - - - # --------------------- # Warnings and checking # --------------------- @@ -21522,7 +21482,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 21525 "configure" +#line 21485 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -21628,7 +21588,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 21631 "configure" +#line 21591 "configure" #include "confdefs.h" #if HAVE_DLFCN_H diff --git a/gcc/configure.ac b/gcc/configure.ac index 2c43b38..ac1f0e9 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -563,35 +563,6 @@ if test $ac_cv_std_swap_in_utility = yes; then [Define if <utility> defines std::swap.]) fi -# Check whether compiler is affected by placement new aliasing bug (PR 29286). -# If the host compiler is affected by the bug, and we build with optimization -# enabled (which happens e.g. when cross-compiling), the pool allocator may -# get miscompiled. Use -fno-strict-aliasing to work around this problem. -# Since there is no reliable feature check for the presence of this bug, -# we simply use a GCC version number check. (This should never trigger for -# stages 2 or 3 of a native bootstrap.) -aliasing_flags= -if test "$GCC" = yes; then - saved_CXXFLAGS="$CXXFLAGS" - - # The following test compilation will succeed if and only if $CXX accepts - # -fno-strict-aliasing *and* is older than GCC 4.3. - CXXFLAGS="$CXXFLAGS -fno-strict-aliasing" - AC_MSG_CHECKING([whether $CXX is affected by placement new aliasing bug]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ -#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) -#error compiler not affected by placement new aliasing bug -#endif -])], - [AC_MSG_RESULT([yes]); aliasing_flags='-fno-strict-aliasing'], - [AC_MSG_RESULT([no])]) - - CXXFLAGS="$saved_CXXFLAGS" -fi -AC_SUBST(aliasing_flags) - - - # --------------------- # Warnings and checking # --------------------- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cb4ff09..8e9b8ea 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,28 @@ +2025-08-06 Patrick Palka <ppalka@redhat.com> + + PR c++/121231 + PR c++/119688 + PR c++/94511 + * mangle.cc (write_expression): Write out implicit non-trailing + zeroes of a CONSTRUCTOR when the ABI version is at least 21. + +2025-08-06 Jason Merrill <jason@redhat.com> + + * constexpr.cc (cxx_eval_indirect_ref): Improve diagnostic. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + + * parser.cc (cp_parser_omp_clause_from_to): Parse 'iterator' modifier. + * semantics.cc (finish_omp_clauses): Finish iterators for to/from + clauses. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + Andrew Stubbs <ams@baylibre.com> + + * parser.cc (cp_parser_omp_clause_map): Parse 'iterator' modifier. + * semantics.cc (finish_omp_clauses): Finish iterators. Apply + iterators to generated clauses. + 2025-08-05 Jason Merrill <jason@redhat.com> PR c++/121068 diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 65b91ec..b8ac454 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -7179,10 +7179,23 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t))); /* DR 1188 says we don't have to deal with this. */ if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), - "accessing value of %qE through a %qT glvalue in a " - "constant expression", build_fold_indirect_ref (sub), - TREE_TYPE (t)); + { + auto_diagnostic_group d; + error_at (cp_expr_loc_or_input_loc (t), + "accessing value of %qT object through a %qT " + "glvalue in a constant expression", + TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)); + tree ob = build_fold_indirect_ref (sub); + if (DECL_P (ob)) + { + if (DECL_ARTIFICIAL (ob)) + inform (DECL_SOURCE_LOCATION (ob), + "%qT object created here", TREE_TYPE (ob)); + else + inform (DECL_SOURCE_LOCATION (ob), + "%q#D declared here", ob); + } + } *non_constant_p = true; return t; } diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index 13d5ded..fd69099 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -3745,11 +3745,59 @@ write_expression (tree expr) || !zero_init_expr_p (ce->value)) last_nonzero = i; + tree prev_field = NULL_TREE; if (undigested || last_nonzero != UINT_MAX) for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i) { if (i > last_nonzero) break; + if (!undigested && !CONSTRUCTOR_NO_CLEARING (expr) + && (TREE_CODE (etype) == RECORD_TYPE + || TREE_CODE (etype) == ARRAY_TYPE)) + { + /* Write out any implicit non-trailing zeros + (which we neglected to do before v21). */ + if (TREE_CODE (etype) == RECORD_TYPE) + { + tree field; + if (i == 0) + field = first_field (etype); + else + field = DECL_CHAIN (prev_field); + for (;;) + { + field = next_subobject_field (field); + if (field == ce->index) + break; + if (abi_check (21)) + write_expression (build_zero_cst + (TREE_TYPE (field))); + field = DECL_CHAIN (field); + } + } + else if (TREE_CODE (etype) == ARRAY_TYPE) + { + unsigned HOST_WIDE_INT j; + if (i == 0) + j = 0; + else + j = 1 + tree_to_uhwi (prev_field); + unsigned HOST_WIDE_INT k; + if (TREE_CODE (ce->index) == RANGE_EXPR) + k = tree_to_uhwi (TREE_OPERAND (ce->index, 0)); + else + k = tree_to_uhwi (ce->index); + tree zero = NULL_TREE; + for (; j < k; ++j) + if (abi_check (21)) + { + if (!zero) + zero = build_zero_cst (TREE_TYPE (etype)); + write_expression (zero); + } + } + } + if (!undigested && TREE_CODE (etype) == UNION_TYPE) { /* Express the active member as a designator. */ @@ -3794,6 +3842,9 @@ write_expression (tree expr) else for (unsigned j = 0; j < reps; ++j) write_expression (ce->value); + prev_field = ce->index; + if (prev_field && TREE_CODE (prev_field) == RANGE_EXPR) + prev_field = TREE_OPERAND (prev_field, 1); } } else diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 759442ad..a8c54c7 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -42636,8 +42636,11 @@ cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc) to ( variable-list ) OpenMP 5.1: - from ( [present :] variable-list ) - to ( [present :] variable-list ) */ + from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + + motion-modifier: + present | iterator (iterators-definition) */ static tree cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, @@ -42646,23 +42649,113 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; - bool present = false; - cp_token *token = cp_lexer_peek_token (parser->lexer); + int pos = 1; + int colon_pos = 0; + int iterator_length = 0; - if (token->type == CPP_NAME - && strcmp (IDENTIFIER_POINTER (token->u.value), "present") == 0 - && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON)) + while (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_NAME) { - present = true; - cp_lexer_consume_token (parser->lexer); - cp_lexer_consume_token (parser->lexer); + const char *identifier = + IDENTIFIER_POINTER (cp_lexer_peek_nth_token (parser->lexer, + pos)->u.value); + if (cp_lexer_nth_token_is (parser->lexer, pos + 1, CPP_OPEN_PAREN)) + { + int n = cp_parser_skip_balanced_tokens (parser, pos + 1); + if (n != pos + 1) + { + if (strcmp (identifier, "iterator") == 0) + iterator_length = n - pos; + pos = n - 1; + } + } + if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COMMA) + pos += 2; + else + pos++; + if (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_COLON) + { + colon_pos = pos; + break; + } } + bool present = false; + tree iterators = NULL_TREE; + + for (int pos = 1; pos < colon_pos; ++pos) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_COMMA) + { + cp_lexer_consume_token (parser->lexer); + continue; + } + const char *p = IDENTIFIER_POINTER (token->u.value); + if (strcmp ("present", p) == 0) + { + if (present) + { + cp_parser_error (parser, "too many %<present%> modifiers"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + present = true; + cp_lexer_consume_token (parser->lexer); + } + else if (strcmp ("iterator", p) == 0) + { + if (iterators) + { + cp_parser_error (parser, "too many %<iterator%> modifiers"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + begin_scope (sk_omp, NULL); + iterators = cp_parser_omp_iterators (parser); + pos += iterator_length - 1; + } + + else + { + error_at (token->location, + "%qs clause with modifier other than %<iterator%> " + "or %<present%>", + kind == OMP_CLAUSE_TO ? "to" : "from"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + } + + if (colon_pos) + cp_parser_require (parser, CPP_COLON, RT_COLON); + tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, true); if (present) for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_MOTION_PRESENT (c) = 1; + if (iterators) + { + tree block = poplevel (1, 1, 0); + if (iterators == error_mark_node) + iterators = NULL_TREE; + else + TREE_VEC_ELT (iterators, 5) = block; + } + + if (iterators) + for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ITERATORS (c) = iterators; + return nl; } diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 256ac3f..0c7788d 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -9007,6 +9007,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; break; } + /* FALLTHRU */ + case OMP_CLAUSE_TO: + case OMP_CLAUSE_FROM: if (OMP_CLAUSE_ITERATORS (c) && cp_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c))) { @@ -9014,8 +9017,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; } /* FALLTHRU */ - case OMP_CLAUSE_TO: - case OMP_CLAUSE_FROM: case OMP_CLAUSE__CACHE_: { using namespace omp_addr_tokenizer; diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 4fe6418..1217b5d 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,7 @@ +2025-08-06 Sam James <sam@gentoo.org> + + * Make-lang.in (ALL_DFLAGS): Don't use ALIASING_FLAGS. + 2025-07-25 David Malcolm <dmalcolm@redhat.com> * d-diagnostic.cc: Likewise. diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in index 2d444c9..0ddd524 100644 --- a/gcc/d/Make-lang.in +++ b/gcc/d/Make-lang.in @@ -61,7 +61,7 @@ WARN_DFLAGS = -Wall -Wdeprecated NOEXCEPTION_DFLAGS = $(filter-out -fno-rtti, $(NOEXCEPTION_FLAGS)) ALL_DFLAGS = $(DFLAGS-$@) $(GDCFLAGS) -fversion=IN_GCC $(CHECKING_DFLAGS) \ - $(PICFLAG) $(ALIASING_FLAGS) $(NOEXCEPTION_DFLAGS) $(COVERAGE_FLAGS) \ + $(PICFLAG) $(NOEXCEPTION_DFLAGS) $(COVERAGE_FLAGS) \ $(WARN_DFLAGS) DCOMPILE.base = $(GDC) -c $(ALL_DFLAGS) -o $@ diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 64c1217..7423224 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -393,7 +393,7 @@ Note binutils 2.35 or newer is required for LTO to work correctly with GNU libtool that includes doing a bootstrap with LTO enabled. @item gzip version 1.2.4 (or later) or -@itemx bzip2 version 1.0.2 (or later) +@itemx xz version 5.0 (or later) Necessary to uncompress GCC @command{tar} files when source code is obtained via HTTPS mirror sites. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 105a60d..00468a7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -3016,8 +3016,9 @@ Version 20, which first appeared in G++ 15, fixes manglings of lambdas in static data member initializers. Version 21, which first appeared in G++ 16, fixes unnecessary captures -in noexcept lambdas (c++/119764) and layout of a base class -with all explicitly defaulted constructors (c++/120012). +in noexcept lambdas (c++/119764), layout of a base class with all explicitly +defaulted constructors (c++/120012), and mangling of class and array +objects with implicitly zero-initialized non-trailing subobjects (c++/121231). See also @option{-Wabi}. @@ -31336,7 +31337,7 @@ The default is @option{-misa-spec=20191213} unless GCC has been configured with @option{--with-isa-spec=} specifying a different default version. @opindex march -@item -march=@var{ISA-string|Profiles|Profile_ISA-string} +@item -march=@var{ISA-string|Profiles|Profile_ISA-string|help|unset} Generate code for given RISC-V ISA or Profiles or a combination of them (e.g.@: @samp{rv64im} @samp{rvi20u64} @samp{rvi20u64_zbb}). ISA strings and Profiles must be lower-case. Examples include @samp{rv64i}, @samp{rv32g}, @@ -31347,6 +31348,12 @@ at the beginning of the option, then use underline connect ISA-string (e.g.@: @option{help} (@option{-march=help}) is accepted to list all supported extensions. +@samp{-march=unset} causes the compiler to ignore any @samp{-march=@dots{}} options +that appear earlier on the command line, behaving as if the option was never +passed. This is useful for ensuring that the architecture is taken from the +@samp{-mcpu} option, and it will result in an error if no @samp{-mcpu} option +is given when @samp{-march=unset} is used. + The syntax of the ISA string is defined as follows: @table @code diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l index e36ca5b..37e4eb0 100644 --- a/gcc/gengtype-lex.l +++ b/gcc/gengtype-lex.l @@ -21,17 +21,6 @@ along with GCC; see the file COPYING3. If not see %option noinput %{ -#ifdef HOST_GENERATOR_FILE -#include "config.h" -#define GENERATOR_FILE 1 -#else -#include "bconfig.h" -#endif -#include "system.h" - -#define malloc xmalloc -#define realloc xrealloc - #include "gengtype.h" #define YY_DECL int yylex (const char **yylval) diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc index 8fb7a60..1e434ce 100644 --- a/gcc/gimple-lower-bitint.cc +++ b/gcc/gimple-lower-bitint.cc @@ -76,7 +76,7 @@ enum bitint_prec_kind { /* Caches to speed up bitint_precision_kind. */ static int small_max_prec, mid_min_prec, large_min_prec, huge_min_prec; -static int limb_prec; +static int limb_prec, abi_limb_prec; static bool bitint_big_endian, bitint_extended; /* Categorize _BitInt(PREC) as small, middle, large or huge. */ @@ -109,6 +109,9 @@ bitint_precision_kind (int prec) large_min_prec = MAX_FIXED_MODE_SIZE + 1; if (!limb_prec) limb_prec = GET_MODE_PRECISION (limb_mode); + if (!abi_limb_prec) + abi_limb_prec + = GET_MODE_PRECISION (as_a <scalar_int_mode> (info.abi_limb_mode)); if (!huge_min_prec) { if (4 * limb_prec >= MAX_FIXED_MODE_SIZE) @@ -429,7 +432,7 @@ struct bitint_large_huge void insert_before (gimple *); tree limb_access_type (tree, tree); - tree limb_access (tree, tree, tree, bool); + tree limb_access (tree, tree, tree, bool, bool = false); tree build_bit_field_ref (tree, tree, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT); void if_then (gimple *, profile_probability, edge &, edge &); @@ -610,11 +613,14 @@ bitint_large_huge::limb_access_type (tree type, tree idx) TYPE. If WRITE_P is true, it will be a store, otherwise a read. */ tree -bitint_large_huge::limb_access (tree type, tree var, tree idx, bool write_p) +bitint_large_huge::limb_access (tree type, tree var, tree idx, bool write_p, + bool abi_load_p) { tree atype = (tree_fits_uhwi_p (idx) ? limb_access_type (type, idx) : m_limb_type); - tree ltype = m_limb_type; + + tree ltype = (bitint_extended && abi_load_p) ? atype : m_limb_type; + addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (var)); if (as != TYPE_ADDR_SPACE (ltype)) ltype = build_qualified_type (ltype, TYPE_QUALS (ltype) @@ -651,12 +657,21 @@ bitint_large_huge::limb_access (tree type, tree var, tree idx, bool write_p) { unsigned HOST_WIDE_INT nelts = CEIL (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))), limb_prec); - tree atype = build_array_type_nelts (ltype, nelts); + + /* Build the array type with m_limb_type from the right address + space. */ + tree limb_type_a = m_limb_type; + if (as != TYPE_ADDR_SPACE (m_limb_type)) + limb_type_a = build_qualified_type (m_limb_type, + TYPE_QUALS (m_limb_type) + | ENCODE_QUAL_ADDR_SPACE (as)); + + tree atype = build_array_type_nelts (limb_type_a, nelts); var = build1 (VIEW_CONVERT_EXPR, atype, var); } ret = build4 (ARRAY_REF, ltype, var, idx, NULL_TREE, NULL_TREE); } - if (!write_p && !useless_type_conversion_p (atype, m_limb_type)) + if (!write_p && !useless_type_conversion_p (atype, ltype)) { gimple *g = gimple_build_assign (make_ssa_name (m_limb_type), ret); insert_before (g); @@ -1964,6 +1979,7 @@ bitint_large_huge::handle_load (gimple *stmt, tree idx) tree rhs1 = gimple_assign_rhs1 (stmt); tree rhs_type = TREE_TYPE (rhs1); bool eh = stmt_ends_bb_p (stmt); + bool load_bitfield_p = false; edge eh_edge = NULL; gimple *g; @@ -1987,12 +2003,18 @@ bitint_large_huge::handle_load (gimple *stmt, tree idx) if (!bitint_big_endian && DECL_OFFSET_ALIGN (fld) >= TYPE_ALIGN (TREE_TYPE (rhs1)) && (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (fld)) % limb_prec) == 0) - goto normal_load; + { + load_bitfield_p = true; + goto normal_load; + } /* Even if DECL_FIELD_BIT_OFFSET (fld) is a multiple of BITS_PER_UNIT, handle it normally for now. */ if (!bitint_big_endian && (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (fld)) % BITS_PER_UNIT) == 0) - goto normal_load; + { + load_bitfield_p = true; + goto normal_load; + } tree repr = DECL_BIT_FIELD_REPRESENTATIVE (fld); poly_int64 bitoffset; poly_uint64 field_offset, repr_offset; @@ -2241,7 +2263,7 @@ normal_load: /* Use write_p = true for loads with EH edges to make sure limb_access doesn't add a cast as separate statement after it. */ - rhs1 = limb_access (rhs_type, rhs1, idx, eh); + rhs1 = limb_access (rhs_type, rhs1, idx, eh, !load_bitfield_p); tree ret = make_ssa_name (TREE_TYPE (rhs1)); g = gimple_build_assign (ret, rhs1); insert_before (g); @@ -2373,7 +2395,7 @@ range_to_prec (tree op, gimple *stmt) from that precision, if it is negative, the operand is sign-extended from -*PREC. If PREC_STORED is NULL, it is the toplevel call, otherwise *PREC_STORED is prec from the innermost call without - range optimizations. */ + range optimizations (0 for uninitialized SSA_NAME). */ tree bitint_large_huge::handle_operand_addr (tree op, gimple *stmt, @@ -2481,7 +2503,7 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt, *prec = TYPE_UNSIGNED (TREE_TYPE (op)) ? limb_prec : -limb_prec; precs = *prec; if (prec_stored) - *prec_stored = precs; + *prec_stored = 0; tree var = create_tmp_var (m_limb_type); TREE_ADDRESSABLE (var) = 1; ret = build_fold_addr_expr (var); @@ -2510,6 +2532,13 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt, int prec_stored_val = 0; ret = handle_operand_addr (rhs1, g, &prec_stored_val, prec); precs = prec_stored_val; + if (prec_stored) + *prec_stored = prec_stored_val; + if (precs == 0) + { + gcc_assert (*prec == limb_prec || *prec == -limb_prec); + precs = *prec; + } if (TYPE_PRECISION (lhs_type) > TYPE_PRECISION (rhs_type)) { if (TYPE_UNSIGNED (lhs_type) @@ -2518,7 +2547,9 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt, } else { - if (*prec > 0 && *prec < TYPE_PRECISION (lhs_type)) + if (prec_stored_val == 0) + /* Non-widening cast of uninitialized value. */; + else if (*prec > 0 && *prec < TYPE_PRECISION (lhs_type)) ; else if (TYPE_UNSIGNED (lhs_type)) { @@ -3150,6 +3181,17 @@ bitint_large_huge::lower_mergeable_stmt (gimple *stmt, tree_code &cmp_code, { tree l = limb_access (nlhs ? NULL_TREE : lhs_type, nlhs ? nlhs : lhs, idx, true); + + if (bitint_extended + && sext + && TYPE_UNSIGNED (lhs_type) + && tree_fits_uhwi_p (idx) + && !nlhs) + { + rhs1 = add_cast (limb_access_type (lhs_type, idx), rhs1); + rhs1 = add_cast (TREE_TYPE (l), rhs1); + } + g = gimple_build_assign (l, rhs1); } insert_before (g); @@ -6669,7 +6711,7 @@ static unsigned int gimple_lower_bitint (void) { small_max_prec = mid_min_prec = large_min_prec = huge_min_prec = 0; - limb_prec = 0; + limb_prec = abi_limb_prec = 0; bitint_big_endian = false; unsigned int i; @@ -7631,7 +7673,20 @@ gimple_lower_bitint (void) from smaller number. */ min_prec = prec; else - min_prec = CEIL (min_prec, limb_prec) * limb_prec; + { + min_prec = CEIL (min_prec, limb_prec) * limb_prec; + if (min_prec > (unsigned) limb_prec + && abi_limb_prec > limb_prec) + { + /* For targets with ABI limb precision higher than + limb precision round to ABI limb precision, + otherwise c can contain padding bits. */ + min_prec + = CEIL (min_prec, abi_limb_prec) * abi_limb_prec; + if (min_prec > prec - rem - 2 * limb_prec) + min_prec = prec; + } + } if (min_prec == 0) c = NULL_TREE; else if (min_prec == prec) diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index e178519..ca1fa21 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -9966,9 +9966,11 @@ remove_unused_omp_iterator_vars (tree *list_p) if (t == NULL_TREE) { need_new_iterators = true; - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM)) + if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP + && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM)) + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM) warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, "iterator variable %qE not used in clause " "expression", DECL_NAME (var)); @@ -13582,7 +13584,8 @@ omp_instantiate_implicit_mappers (splay_tree_node n, void *data) static void gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, enum omp_region_type region_type, - enum tree_code code) + enum tree_code code, + gimple_seq *loops_seq_p = NULL) { using namespace omp_addr_tokenizer; struct gimplify_omp_ctx *ctx, *outer_ctx; @@ -14353,23 +14356,24 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, if (OMP_CLAUSE_SIZE (c) == NULL_TREE) OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl) : TYPE_SIZE_UNIT (TREE_TYPE (decl)); - if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p, - NULL, is_gimple_val, fb_rvalue) == GS_ERROR) + gimple_seq *seq_p; + seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p); + if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR) { remove = true; + exit_omp_iterator_loop_context (c); break; } if (!DECL_P (decl)) { - if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, - NULL, is_gimple_lvalue, fb_lvalue) - == GS_ERROR) - { - remove = true; - break; - } + if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL, + is_gimple_lvalue, fb_lvalue) == GS_ERROR) + remove = true; + exit_omp_iterator_loop_context (c); break; } + exit_omp_iterator_loop_context (c); goto do_notice; case OMP_CLAUSE__MAPPER_BINDING_: @@ -18728,7 +18732,7 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) if ((ort & ORT_ACC) == 0) in_omp_construct = false; gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort, - TREE_CODE (expr)); + TREE_CODE (expr), &iterator_loops_seq); if (TREE_CODE (expr) == OMP_TARGET) optimize_target_teams (expr, pre_p); if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0 @@ -18885,10 +18889,16 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p) default: gcc_unreachable (); } + + gimple_seq iterator_loops_seq = NULL; + remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr)); + build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr), + &iterator_loops_seq); + gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p, - ort, TREE_CODE (expr)); + ort, TREE_CODE (expr), &iterator_loops_seq); gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr), - TREE_CODE (expr)); + TREE_CODE (expr), &iterator_loops_seq); if (TREE_CODE (expr) == OACC_UPDATE && omp_find_clause (OMP_STANDALONE_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT)) @@ -18952,7 +18962,8 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p) gcc_unreachable (); } } - stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr)); + stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr), + iterator_loops_seq); gimplify_seq_add_stmt (pre_p, stmt); *expr_p = NULL_TREE; diff --git a/gcc/match.pd b/gcc/match.pd index 82e6e29..06a4a91 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -5508,16 +5508,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (convert @0))) /* Strip inner integral conversions that do not change precision or size, or - zero-extend while keeping the same size (for bool-to-char). */ + zero-extend while keeping the same size (for bool-to-char). + However, keep this conversion if the result is an extended _BitInt, + since it may rely on this conversion to extend properly. */ + (simplify (view_convert (convert@0 @1)) + (with { + bool extended_bitint = false; + if (BITINT_TYPE_P (TREE_TYPE (@0))) + { + struct bitint_info info; + extended_bitint + = targetm.c.bitint_type_info (TYPE_PRECISION (TREE_TYPE (@0)), + &info); + extended_bitint = extended_bitint && info.extended; + } + } (if ((INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0))) && (INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1))) + && !extended_bitint && TYPE_SIZE (TREE_TYPE (@0)) == TYPE_SIZE (TREE_TYPE (@1)) && (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)) || (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@1)) && TYPE_UNSIGNED (TREE_TYPE (@1))))) - (view_convert @1))) + (view_convert @1)))) /* Simplify a view-converted empty or single-element constructor. */ (simplify diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1ac6084..df2c843 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,112 @@ +2025-08-06 Sam James <sam@gentoo.org> + + * g++.dg/cpp26/constexpr-new3.C: Escape '[' and ']'. + +2025-08-06 Alexandre Oliva <oliva@adacore.com> + + * gcc.dg/torture/hardbool-ai.c: New. + * gcc.dg/torture/hardbool-vi.c: New. + * gcc.dg/torture/hardbool.c: Handle NO_BITFIELDS. + (add1, preinc, postinc, sub1, predec, postdec): New. + (main): Exercise them. + +2025-08-06 Martin Uecker <uecker@tugraz.at> + + PR c/108931 + * gcc.dg/vla-tert-1.c: New test. + +2025-08-06 Patrick Palka <ppalka@redhat.com> + + PR c++/121231 + PR c++/119688 + PR c++/94511 + * g++.dg/abi/mangle82.C: New test. + * g++.dg/cpp2a/nontype-class73.C: New test. + +2025-08-06 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp26/constexpr-new3.C: Tweak diagnostic. + +2025-08-06 Richard Biener <rguenther@suse.de> + + * gcc.dg/vect/vect-gather-1.c: Adjust to hide N. + +2025-08-06 Tejas Belagod <tejas.belagod@arm.com> + + * gcc.target/aarch64/sve/acle/general/cops.c: Fix test. + +2025-08-06 Yang Yujie <yangyujie@loongson.cn> + + * gcc.dg/torture/bitint-84.c: New test. + +2025-08-06 Yang Yujie <yangyujie@loongson.cn> + + * gcc.dg/torture/bitint-83.c: New test. + +2025-08-06 Yang Yujie <yangyujie@loongson.cn> + + * gcc.dg/bitintext.h (BEXTC1): Define. Convert the copied + object back to the original type before comparison. + (BEXTC): Use BEXTC1 for both the signed and the unsigned case. + +2025-08-06 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/121413 + * gcc.dg/torture/bitint-85.c: New test. + +2025-08-06 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/121127 + * gcc.dg/bitint-125.c: New test. + +2025-08-06 Yuao Ma <c8ef@outlook.com> + + * gfortran.dg/c_f_pointer_shape_tests_2.f03: Use the new driver. + * gfortran.dg/c_f_pointer_shape_tests_4.f03: Ditto. + * gfortran.dg/c_f_pointer_shape_tests_4_driver.c: Removed. + * gfortran.dg/c_f_pointer_shape_tests_2_driver.c: Renamed to ... + * gfortran.dg/c_f_pointer_shape_tests_driver.c: ... this; format + with gcc style. + +2025-08-06 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/120778 + * c-c++-common/cpp/comment-ff-1.c: New test. + * c-c++-common/cpp/comment-vtab-1.c: New test. + +2025-08-06 Martin Uecker <uecker@tugraz.at> + + PR c/121217 + * gcc.dg/pr121217.c: New test. + +2025-08-06 Kito Cheng <kito.cheng@sifive.com> + + * gcc.target/riscv/arch-unset-1.c: New test. + * gcc.target/riscv/arch-unset-2.c: New test. + * gcc.target/riscv/arch-unset-3.c: New test. + * gcc.target/riscv/arch-unset-4.c: New test. + * gcc.target/riscv/arch-unset-5.c: New test. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + + * c-c++-common/gomp/target-update-iterators-1.c: New. + * c-c++-common/gomp/target-update-iterators-2.c: New. + * c-c++-common/gomp/target-update-iterators-3.c: New. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + Andrew Stubbs <ams@baylibre.com> + + * c-c++-common/gomp/map-6.c (foo): Amend expected error message. + * c-c++-common/gomp/target-map-iterators-1.c: New. + * c-c++-common/gomp/target-map-iterators-2.c: New. + * c-c++-common/gomp/target-map-iterators-3.c: New. + * c-c++-common/gomp/target-map-iterators-4.c: New. + +2025-08-06 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR libfortran/121234 + * gfortran.dg/pr121234.f90: New test. + 2025-08-05 Jason Merrill <jason@redhat.com> PR c++/121068 diff --git a/gcc/testsuite/c-c++-common/cpp/comment-ff-1.c b/gcc/testsuite/c-c++-common/cpp/comment-ff-1.c new file mode 100644 index 0000000..0d071b1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/comment-ff-1.c @@ -0,0 +1,12 @@ +// C++26 P2843R3 - Preprocessing is never undefined +// Test that form-feed followed by non-whitespace +// in line comments are accepted. +// { dg-do compile } +// { dg-options "-pedantic-errors -Wall -W" } + +// +int a; +// +int b; +// comment +int c; diff --git a/gcc/testsuite/c-c++-common/cpp/comment-vtab-1.c b/gcc/testsuite/c-c++-common/cpp/comment-vtab-1.c new file mode 100644 index 0000000..03feb73 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/comment-vtab-1.c @@ -0,0 +1,12 @@ +// C++26 P2843R3 - Preprocessing is never undefined +// Test that vertical tab followed by non-whitespace +// in line comments are accepted. +// { dg-do compile } +// { dg-options "-pedantic-errors -Wall -W" } + +// +int a; +// +int b; +// comment +int c; diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c new file mode 100644 index 0000000..53b22f0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +#define DIM1 17 +#define DIM2 39 + +void f (int **x, float **y) +{ + #pragma omp target update to (iterator(i=0:DIM1): x[i][:DIM2]) + + #pragma omp target update to (iterator(i=0:DIM1): x[i][:DIM2], y[i][:DIM2]) + + #pragma omp target update to (iterator(i=0:DIM1), present: x[i][:DIM2]) + + #pragma omp target update to (iterator(i=0:DIM1), iterator(j=0:DIM2): x[i][j]) /* { dg-error "too many 'iterator' modifiers" } */ + /* { dg-error "'#pragma omp target update' must contain at least one 'from' or 'to' clauses" "" { target *-*-* } .-1 } */ + + #pragma omp target update from (iterator(i=0:DIM1), something: x[i][j]) /* { dg-error "'from' clause with modifier other than 'iterator' or 'present'" } */ + /* { dg-error "expected '\\)' before 'something'" "" { target c } .-1 } */ + /* { dg-error "'#pragma omp target update' must contain at least one 'from' or 'to' clauses" "" { target *-*-* } .-2 } */ +} diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c new file mode 100644 index 0000000..dbd43e0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +void f (int *x, float *y, double *z) +{ + #pragma omp target update to(iterator(i=0:10): x) /* { dg-warning "iterator variable 'i' not used in clause expression" }*/ + ; + + #pragma omp target update from(iterator(i2=0:10, j2=0:20): x[i2]) /* { dg-warning "iterator variable 'j2' not used in clause expression" }*/ + ; + + #pragma omp target update to(iterator(i3=0:10, j3=0:20, k3=0:30): x[i3+j3], y[j3+k3], z[k3+i3]) + /* { dg-warning "iterator variable 'i3' not used in clause expression" "" { target *-*-* } .-1 } */ + /* { dg-warning "iterator variable 'j3' not used in clause expression" "" { target *-*-* } .-2 } */ + /* { dg-warning "iterator variable 'k3' not used in clause expression" "" { target *-*-* } .-3 } */ + ; +} + +/* { dg-final { scan-tree-dump "update to\\\(x " "gimple" } } */ +/* { dg-final { scan-tree-dump "update from\\\(iterator\\\(int i2=0:10:1, loop_label=" "gimple" } } */ +/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int i3=0:10:1, int k3=0:30:1, loop_label=" "gimple" } } */ +/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int j3=0:20:1, int k3=0:30:1, loop_label=" "gimple" } } */ +/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int i3=0:10:1, int j3=0:20:1, loop_label=" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c new file mode 100644 index 0000000..ef55216 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +#define DIM1 10 +#define DIM2 20 +#define DIM3 30 + +void f (int ***x, float ***y, double **z) +{ + #pragma omp target update to (iterator(i=0:DIM1, j=0:DIM2): x[i][j][:DIM3], y[i][j][:DIM3]) + #pragma omp target update from (iterator(i=0:DIM1): z[i][:DIM2]) +} + +/* { dg-final { scan-tree-dump-times "if \\(i <= 9\\) goto <D\.\[0-9\]+>; else goto <D\.\[0-9\]+>;" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "if \\(j <= 19\\) goto <D\.\[0-9\]+>; else goto <D\.\[0-9\]+>;" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "to\\(iterator\\(int i=0:10:1, int j=0:20:1, loop_label=<D\.\[0-9\]+>, elems=omp_iter_data\.\[0-9\]+, index=D\.\[0-9\]+\\):\\*D\.\[0-9\]+" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "from\\(iterator\\(int i=0:10:1, loop_label=<D\.\[0-9\]+>, elems=omp_iter_data\.\[0-9\]+, index=D\.\[0-9\]+\\):\\*D\.\[0-9\]+" 1 "gimple" } } */ diff --git a/gcc/testsuite/g++.dg/abi/mangle82.C b/gcc/testsuite/g++.dg/abi/mangle82.C new file mode 100644 index 0000000..39dd581 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle82.C @@ -0,0 +1,85 @@ +// Test mangling of C++20 class NTTP objects with implicitly zeroed +// non-trailing subojects. +// PR c++/121231 +// { dg-do compile { target c++20 } } + +struct A { + int x, y, z; + + static constexpr A make(int x, int y, int z) { + A a{}; + if (x != 0) + a.x = x; + if (y != 0) + a.y = y; + if (z != 0) + a.z = z; + return a; + } +}; + +struct B : A { + int w; + + static constexpr B make(int x, int y, int z, int w) { + B b{}; + if (x != 0 || y != 0 || z != 0) + static_cast<A&>(b) = A::make(x, y, z); + if (w != 0) + b.w = w; + return b; + } +}; + +struct C { + int xyz[3]; + + static constexpr C make(int x, int y, int z) { + C c{}; + if (x != 0) + c.xyz[0] = x; + if (y != 0) + c.xyz[1] = y; + if (z != 0) + c.xyz[2] = z; + return c; + } +}; + +template<int N, A a> void f(); +template<int N, B b> void g(); +template<int N, C c> void h(); + +int main() { + f<0, A::make(0, 0, 1)>(); // void f<0, A{0, 0, 1}>() + f<1, A::make(0, 1, 0)>(); // void f<1, A{0, 1}>() + f<2, A::make(0, 0, 0)>(); // void f<2, A{}>() + f<3, A::make(1, 0, 1)>(); // void f<3, A{1, 0, 1}>() + + g<0, B::make(0, 0, 0, 1)>(); // void g<0, B{A{}, 1}>() + g<1, B::make(0, 0, 1, 0)>(); // void g<1, B{A{0, 0, 1}}>() + g<2, B::make(0, 1, 0, 0)>(); // void g<2, B{A{0, 1}}>() + g<3, B::make(0, 0, 0, 0)>(); // void g<3, B{}>() + g<4, B::make(1, 0, 1, 0)>(); // void g<4, B{A{1, 0, 1}}>() + + h<0, C::make(0, 0, 1)>(); // void h<0, C{int [3]{0, 0, 1}}>() + h<1, C::make(0, 1, 0)>(); // void h<1, C{int [3]{0, 1}}>() + h<2, C::make(0, 0, 0)>(); // void h<2, C{}>() + h<3, C::make(1, 0, 1)>(); // void h<3, C{int [3]{1, 0, 1}}>() +} + +// { dg-final { scan-assembler "_Z1fILi0EXtl1ALi0ELi0ELi1EEEEvv" } } +// { dg-final { scan-assembler "_Z1fILi1EXtl1ALi0ELi1EEEEvv" } } +// { dg-final { scan-assembler "_Z1fILi2EXtl1AEEEvv" } } +// { dg-final { scan-assembler "_Z1fILi3EXtl1ALi1ELi0ELi1EEEEvv" } } + +// { dg-final { scan-assembler "_Z1gILi0EXtl1Btl1AELi1EEEEvv" } } +// { dg-final { scan-assembler "_Z1gILi1EXtl1Btl1ALi0ELi0ELi1EEEEEvv" } } +// { dg-final { scan-assembler "_Z1gILi2EXtl1Btl1ALi0ELi1EEEEEvv" } } +// { dg-final { scan-assembler "_Z1gILi3EXtl1BEEEvv" } } +// { dg-final { scan-assembler "_Z1gILi4EXtl1Btl1ALi1ELi0ELi1EEEEEvv" } } + +// { dg-final { scan-assembler "_Z1hILi0EXtl1CtlA3_iLi0ELi0ELi1EEEEEvv" } } +// { dg-final { scan-assembler "_Z1hILi1EXtl1CtlA3_iLi0ELi1EEEEEvv" } } +// { dg-final { scan-assembler "_Z1hILi2EXtl1CEEEvv" } } +// { dg-final { scan-assembler "_Z1hILi3EXtl1CtlA3_iLi1ELi0ELi1EEEEEvv" } } diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C index 6a06a6e..c79060f 100644 --- a/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C @@ -37,7 +37,7 @@ baz () { std::allocator<int> a; auto b = a.allocate (2); - new (b) long (42); // { dg-error "accessing value of 'heap ' through a 'long int' glvalue in a constant expression" } + new (b) long (42); // { dg-error "accessing value of 'int \\\[2\\\]' object through a 'long int' glvalue in a constant expression" } a.deallocate (b, 2); return true; } diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class73.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class73.C new file mode 100644 index 0000000..7f27cad --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class73.C @@ -0,0 +1,30 @@ +// PR c++/119688 +// { dg-do compile { target c++20 } } + +template<int N> +struct builder { + bool value[256]{}; + constexpr builder(char const (&s)[N]) { + for(int i = 0 ; i < N; ++i) + value[static_cast<unsigned char>(s[i])] = true; + } +}; + +template<builder A> +constexpr auto operator""_ar() { + return A.value; +} + +constexpr auto first = "ab"_ar; +static_assert( first['a']); +static_assert( first['b']); +static_assert(!first['c']); +static_assert(!first['d']); +static_assert(!first['z']); + +constexpr auto second = "cd"_ar; +static_assert(!second['a']); +static_assert(!second['b']); +static_assert(!second['z']); +static_assert( second['c']); +static_assert( second['d']); diff --git a/gcc/testsuite/gcc.dg/bitint-125.c b/gcc/testsuite/gcc.dg/bitint-125.c new file mode 100644 index 0000000..5ef0e32 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-125.c @@ -0,0 +1,15 @@ +/* PR tree-optimization/121127 */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-O2 -w" } */ + +#if __BITINT_MAXWIDTH__ >= 576 +_BitInt(575) +foo (void) +{ + _BitInt(576) d; + _BitInt(575) e = d * 42wb; + return e; +} +#else +int i; +#endif diff --git a/gcc/testsuite/gcc.dg/bitintext.h b/gcc/testsuite/gcc.dg/bitintext.h index d5f2689d..f61cf9a 100644 --- a/gcc/testsuite/gcc.dg/bitintext.h +++ b/gcc/testsuite/gcc.dg/bitintext.h @@ -25,22 +25,20 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ r) /* Macro to test whether (on targets where psABI requires it) _BitInt with padding bits have those filled with sign or zero extension. */ #if defined(__s390x__) || defined(__arm__) || defined(__loongarch__) +#define BEXTC1(x, uns) \ + do { \ + uns _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \ + do_copy (&__x, &(x), sizeof (__x)); \ + if (__x != (typeof (x)) __x) \ + __builtin_abort (); \ + } while (0) + #define BEXTC(x) \ - do { \ - if ((typeof (x)) -1 < 0) \ - { \ - _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \ - do_copy (&__x, &(x), sizeof (__x)); \ - if (__x != (x)) \ - __builtin_abort (); \ - } \ - else \ - { \ - unsigned _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \ - do_copy (&__x, &(x), sizeof (__x)); \ - if (__x != (x)) \ - __builtin_abort (); \ - } \ + do { \ + if ((typeof (x)) -1 < 0) \ + BEXTC1 ((x), signed); \ + else \ + BEXTC1 ((x), unsigned); \ } while (0) #else #define BEXTC(x) do { (void) (x); } while (0) diff --git a/gcc/testsuite/gcc.dg/pr121217.c b/gcc/testsuite/gcc.dg/pr121217.c new file mode 100644 index 0000000..313f1e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr121217.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-std=gnu17" } */ + +typedef union{ + char *nordic_ref; + unsigned long long int bit_number; + enum PinMode mode : 2; /* { dg-warning "narrower" } */ + /* { dg-error "field 'mode'" "" { target *-*-* } .-1 } */ + unsigned char value; + } s; typedef struct{ + union{ + char *nordic_ref; + unsigned long long int bit_number; + enum PinMode mode : 2; /* { dg-warning "narrower" } */ + /* { dg-error "field 'mode'" "" { target *-*-* } .-1 } */ + unsigned char value; + } s; +} /* { dg-error "expected identifier" } */ + diff --git a/gcc/testsuite/gcc.dg/torture/bitint-83.c b/gcc/testsuite/gcc.dg/torture/bitint-83.c new file mode 100644 index 0000000..8a9df44 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bitint-83.c @@ -0,0 +1,48 @@ +/* Derived from a test in gcc.dg/torture/bitint-16.c */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-std=c23 -pedantic-errors" } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */ + +#include "../bitintext.h" + +#define BASIC_TESTS \ + TEST(8) \ + TEST(16) \ + TEST(32) + +#if __BITINT_MAXWIDTH__ >= 519 +#define ALL_TESTS \ + BASIC_TESTS \ + TEST(64) \ + TEST(128) \ + TEST(256) \ + TEST(512) +#else +#define ALL_TESTS BASIC_TESTS +#endif + +#define TEST(N) \ +void \ +test##N (unsigned _BitInt(N + 7) *t, _BitInt(N) x) \ +{ \ + *t = -x; \ +} +ALL_TESTS +#undef TEST + +volatile int y = 0; + +int +main (void) +{ +#define TEST(N) \ + { \ + unsigned _BitInt(N + 7) t; \ + _BitInt(N) x = y + N; \ + test##N (&t, x); \ + BEXTC (t); \ + } + ALL_TESTS +#undef TEST +} diff --git a/gcc/testsuite/gcc.dg/torture/bitint-84.c b/gcc/testsuite/gcc.dg/torture/bitint-84.c new file mode 100644 index 0000000..b3ecbef --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bitint-84.c @@ -0,0 +1,18 @@ +/* A simple variant of gcc.dg/torture/bitint-64.c */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-std=c23" } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */ + +#include "../bitintext.h" + +enum E : char { E22 = 22 } e = E22; + +int +main () +{ + _Atomic _BitInt (5) b = 0; + b += e; + BEXTC (b); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/bitint-85.c b/gcc/testsuite/gcc.dg/torture/bitint-85.c new file mode 100644 index 0000000..43eb6ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bitint-85.c @@ -0,0 +1,34 @@ +/* { dg-do run { target bitint } } */ +/* { dg-options "-std=c23 -pedantic-errors" } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */ + +#if __BITINT_MAXWIDTH__ >= 1024 +constexpr _BitInt(1024) d = -541140097068598424394740839221562143161511518875518765552323978870598341733206554363735813878577506997168480201818027232521wb; +int c; + +static inline void +foo (_BitInt(1024) b, _BitInt(1024) *r) +{ + if (c) + b = 0; + *r = b; +} + +[[gnu::noipa]] void +bar (_BitInt(1024) y) +{ + if (y != d) + __builtin_abort (); +} +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 1024 + _BitInt(1024) x; + foo (d, &x); + bar (x); +#endif +} diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-ai.c b/gcc/testsuite/gcc.dg/torture/hardbool-ai.c new file mode 100644 index 0000000..97569a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/hardbool-ai.c @@ -0,0 +1,7 @@ +/* { dg-do run } */ + +#define basetype _Atomic int + +#define NO_BITFIELDS 1 + +#include "hardbool.c" diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-vi.c b/gcc/testsuite/gcc.dg/torture/hardbool-vi.c new file mode 100644 index 0000000..898d395 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/hardbool-vi.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ + +#define basetype volatile int + +#include "hardbool.c" diff --git a/gcc/testsuite/gcc.dg/torture/hardbool.c b/gcc/testsuite/gcc.dg/torture/hardbool.c index 0168495..ed0c598 100644 --- a/gcc/testsuite/gcc.dg/torture/hardbool.c +++ b/gcc/testsuite/gcc.dg/torture/hardbool.c @@ -21,8 +21,12 @@ typedef unsigned char __attribute__ ((__hardbool__ (1, 0))) zbool; struct hs { hbool a[2]; +#ifndef NO_BITFIELDS hbool x:2; hbool y:5; +#else + hbool x, y; +#endif zbool z:1; }; @@ -57,6 +61,30 @@ int ghs(hbool s) { int t = (hbool)2; +hbool add1(hbool *s) { + return *s += 1; +} + +hbool preinc(hbool *s) { + return ++*s; +} + +hbool postinc(hbool *s) { + return (*s)++; +} + +hbool sub1(hbool *s) { + return *s -= 1; +} + +hbool predec(hbool *s) { + return --*s; +} + +hbool postdec(hbool *s) { + return (*s)--; +} + void check_pfalse (hbool *p) { assert (!*p); @@ -114,5 +142,43 @@ int main () { check_vtrue (h2 (2)); check_vtrue (h2 (1)); check_vfalse (h2 (0)); -} + hbool v; + v = 0; + check_vtrue (add1 (&v)); + assert (v); + v = 0; + check_vtrue (preinc (&v)); + assert (v); + v = 0; + check_vfalse (postinc (&v)); + assert (v); + v = 0; + check_vtrue (sub1 (&v)); + assert (v); + v = 0; + check_vtrue (predec (&v)); + assert (v); + v = 0; + check_vfalse (postdec (&v)); + assert (v); + + v = 1; + check_vtrue (add1 (&v)); + assert (v); + v = 1; + check_vtrue (preinc (&v)); + assert (v); + v = 1; + check_vtrue (postinc (&v)); + assert (v); + v = 1; + check_vfalse (sub1 (&v)); + assert (!v); + v = 1; + check_vfalse (predec (&v)); + assert (!v); + v = 1; + check_vtrue (postdec (&v)); + assert (!v); +} diff --git a/gcc/testsuite/gcc.dg/vect/vect-gather-1.c b/gcc/testsuite/gcc.dg/vect/vect-gather-1.c index 5f6640d..6497ab4 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-gather-1.c +++ b/gcc/testsuite/gcc.dg/vect/vect-gather-1.c @@ -3,9 +3,9 @@ #define N 16 void __attribute__((noipa)) -f (int *restrict y, int *restrict x, int *restrict indices) +f (int *restrict y, int *restrict x, int *restrict indices, int n) { - for (int i = 0; i < N; ++i) + for (int i = 0; i < n; ++i) { y[i * 2] = x[indices[i * 2]] + 1; y[i * 2 + 1] = x[indices[i * 2 + 1]] + 2; @@ -49,7 +49,7 @@ main (void) { check_vect (); - f (y, x, indices); + f (y, x, indices, N); #pragma GCC novector for (int i = 0; i < 32; ++i) if (y[i] != expected[i]) diff --git a/gcc/testsuite/gcc.dg/vla-tert-1.c b/gcc/testsuite/gcc.dg/vla-tert-1.c new file mode 100644 index 0000000..dfbb2e6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-tert-1.c @@ -0,0 +1,293 @@ +/* { dg-do run } + * { dg-options "-std=c99" } + * */ + + +// For the conditional operator and variably modified types, +// verify that the size expression on the selected branch +// is evaluated and the correct result is returned. + + +// keep track which side was evaluated. +static int fc[2] = { 0 }; + +static int f(int s, int c) +{ + fc[c]++; + return s; +} + + +int main() +{ + // two VLAs, constant condition + + fc[0] = fc[1] = 0; + + if (5 != sizeof(*(1 ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); + + if ((1 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + fc[0] = fc[1] = 0; + + if (3 != sizeof(*(0 ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); // fails + + if ((0 != fc[0]) || (1 != fc[1])) + __builtin_abort(); // fails + + // two VLAs + + int c = 0; + fc[0] = fc[1] = 0; + + if (3 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); // fails + + if ((0 != fc[0]) || (1 != fc[1])) + __builtin_abort(); + + c = 1; + fc[0] = fc[1] = 0; + + if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); + + if ((1 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // VLA + array of unknown size, VLA side is evaluated, defined + + c = 0; + fc[0] = fc[1] = 0; + + if (3 != sizeof(*(c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); + + if ((0 != fc[0]) || (1 != fc[1])) + __builtin_abort(); + + c = 1; + fc[0] = fc[1] = 0; + + if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0))) + __builtin_abort(); + + if ((1 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // VLA + array of unknown size, VLA side is not evaluated + + c = 1; + fc[0] = fc[1] = 0; + + sizeof(*(c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0)); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // without sizeof + + fc[0] = fc[1] = 0; + + (c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + c = 0; + fc[0] = fc[1] = 0; + + sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0)); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // without sizeof + + fc[0] = fc[1] = 0; + + (c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + + // VLA + array of known size, VLA side is evaluated + + c = 0; + fc[0] = fc[1] = 0; + + if (3 != sizeof(*(c ? (char(*)[3])0 : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); + + // sizeof is not evaluated because not a VLA + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + c = 0; + fc[0] = fc[1] = 0; + + // without sizeof + + (c ? (char(*)[3])0 : (char(*)[ f(3, 1) ])0); + + if ((0 != fc[0]) || (1 != fc[1])) + __builtin_abort(); + + c = 1; + fc[0] = fc[1] = 0; + + if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[5])0))) + __builtin_abort(); + + // sizeof is not evaluated because not a VLA + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // without sizeof + + fc[0] = fc[1] = 0; + + (c ? (char(*)[ f(5, 0) ])0 : (char(*)[ 5 ])0); + + if ((1 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // VLA + array of known size, VLA side is not evaluated + + c = 0; + fc[0] = fc[1] = 0; + + if (3 != sizeof(*(c ? (char(*)[ f(3, 0) ])0 : (char(*)[ 3 ])0))) + __builtin_abort(); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + c = 1; + fc[0] = fc[1] = 0; + + if (5 != sizeof(*(c ? (char(*)[ 5 ])0 : (char(*)[ f(5, 1) ])0))) + __builtin_abort(); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // VM type on one side, null pointer on the other side + + c = 0; + fc[0] = fc[1] = 0; + + if (3 != sizeof(*(c ? (void*)0 : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); + + if ((0 != fc[0]) || (1 != fc[1])) + __builtin_abort(); + + c = 1; + fc[0] = fc[1] = 0; + + if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (void*)0))) + __builtin_abort(); + + if ((1 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + +#if 0 + // these cases are not fixable + // VM types on one side, null pointer on the other side + c = 1; + fc[0] = fc[1] = 0; + + if (3 != sizeof(*(c ? (void*)0 : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); + + if ((0 != fc[0]) || (1 != fc[1])) + __builtin_abort(); + + c = 0; + fc[0] = fc[1] = 0; + + if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (void*)0))) + __builtin_abort(); + + if ((1 != fc[0]) || (0 != fc[1])) + __builtin_abort(); +#endif + + // VLA + void* + void* p = 0; + c = 0; + fc[0] = fc[1] = 0; + + if (1 != sizeof(*(c ? p : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); + + // not a VLA or evaluated + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // .. without sizeof + + (c ? p : (char(*)[ f(3, 1) ])0); + + if ((0 != fc[0]) || (1 != fc[1])) + __builtin_abort(); + + c = 1; + fc[0] = fc[1] = 0; + + if (1 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : p))) + __builtin_abort(); + + // not a VLA + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // .. without sizeof + + (c ? (char(*)[ f(5, 0) ])0 : p); + + if ((1 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // VLA + void*, VLA side not evaluated + + c = 1; + fc[0] = fc[1] = 0; + + if (1 != sizeof(*(c ? p : (char(*)[ f(3, 1) ])0))) + __builtin_abort(); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // .. without sizeof + + (c ? p : (char(*)[ f(3, 1) ])0); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + c = 0; + fc[0] = fc[1] = 0; + + if (1 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : p))) + __builtin_abort(); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + // .. without sizeof + + (c ? (char(*)[ f(5, 0) ])0 : p); + + if ((0 != fc[0]) || (0 != fc[1])) + __builtin_abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c index f0dc9a9..1201ca0 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c @@ -212,22 +212,22 @@ type init4 = svld1_ ## su ## sz (cmp ## sz, mem); \ \ type res_init1 = func_ ## type ## _init1 (); \ - svbool_t cmp = svcmpne_ ## su ## sz (all_true, init1, res_init1); \ + svbool_t cmp = svcmpne_ ## su ## sz (cmp ## sz, init1, res_init1); \ if (svptest_any (all_true, cmp)) \ __builtin_abort (); \ \ type res_init2 = func_ ## type ## _init2 (); \ - cmp = svcmpne_ ## su ## sz (all_true, init2, res_init2); \ + cmp = svcmpne_ ## su ## sz (cmp ## sz, init2, res_init2); \ if (svptest_any (all_true, cmp)) \ __builtin_abort (); \ \ type res_init3 = func_ ## type ## _init3 (); \ - cmp = svcmpne_ ## su ## sz (all_true, init3, res_init3); \ + cmp = svcmpne_ ## su ## sz (cmp ## sz, init3, res_init3); \ if (svptest_any (all_true, cmp)) \ __builtin_abort (); \ \ type res_init4 = func_ ## type ## _init4 (); \ - cmp = svcmpne_ ## su ## sz (all_true, init4, res_init4); \ + cmp = svcmpne_ ## su ## sz (cmp ## sz, init4, res_init4); \ if (svptest_any (all_true, cmp)) \ __builtin_abort (); \ } diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-1.c b/gcc/testsuite/gcc.target/riscv/arch-unset-1.c new file mode 100644 index 0000000..971b936 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arch-unset-1.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64i -march=unset -mcpu=sifive-x280 -mabi=lp64 -misa-spec=20191213" } */ +int foo() +{ +} + +/* { dg-final { scan-assembler "\.attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zfh1p0_zfhmin1p0_zca1p0_zcd1p0_zba1p0_zbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvfh1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0\"" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-2.c b/gcc/testsuite/gcc.target/riscv/arch-unset-2.c new file mode 100644 index 0000000..9840658 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arch-unset-2.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64i -march=unset -mcpu=sifive-x280 -march=rv64i -mabi=lp64 -misa-spec=20191213" } */ +int foo() +{ +} + +/* { dg-final { scan-assembler "\.attribute arch, \"rv64i2p1\"" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-3.c b/gcc/testsuite/gcc.target/riscv/arch-unset-3.c new file mode 100644 index 0000000..5ddc224 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arch-unset-3.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64i -march=unset -mcpu=sifive-x280 -march=rv64i -march=unset -mabi=lp64 -misa-spec=20191213" } */ +int foo() +{ +} + +/* { dg-final { scan-assembler "\.attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zfh1p0_zfhmin1p0_zca1p0_zcd1p0_zba1p0_zbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvfh1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0\"" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-4.c b/gcc/testsuite/gcc.target/riscv/arch-unset-4.c new file mode 100644 index 0000000..c16821d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arch-unset-4.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64i -march=unset -mcpu=sifive-x280 -march=unset -march=rv64i -march=unset -march=rv64i -mabi=lp64 -misa-spec=20191213" } */ +int foo() +{ +} + +/* { dg-final { scan-assembler "\.attribute arch, \"rv64i2p1\"" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-5.c b/gcc/testsuite/gcc.target/riscv/arch-unset-5.c new file mode 100644 index 0000000..368c129 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arch-unset-5.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64i -march=unset -mabi=lp64 -misa-spec=20191213" } */ +int foo() +{ +} + +/* { dg-error "At least one valid -mcpu option must be given after -march=unset" "" { target { "riscv*-*-*" } } 0 } */ diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f03 b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f03 index 79cf2c1..da20835 100644 --- a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f03 +++ b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f03 @@ -1,5 +1,5 @@ ! { dg-do run } -! { dg-additional-sources c_f_pointer_shape_tests_2_driver.c } +! { dg-additional-sources c_f_pointer_shape_tests_driver.c } ! Verify that the optional SHAPE parameter to c_f_pointer can be of any ! valid integer kind. We don't test all kinds here since it would be ! difficult to know what kinds are valid for the architecture we're running on. diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2_driver.c b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2_driver.c deleted file mode 100644 index 1282beb..0000000 --- a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2_driver.c +++ /dev/null @@ -1,46 +0,0 @@ -#define NUM_ELEMS 10 -#define NUM_ROWS 2 -#define NUM_COLS 3 - -void test_long_long_1d(int *array, int num_elems); -void test_long_long_2d(int *array, int num_rows, int num_cols); -void test_long_1d(int *array, int num_elems); -void test_int_1d(int *array, int num_elems); -void test_short_1d(int *array, int num_elems); -void test_mixed(int *array, int num_elems); - -int main(int argc, char **argv) -{ - int my_array[NUM_ELEMS]; - int my_2d_array[NUM_ROWS][NUM_COLS]; - int i, j; - - for(i = 0; i < NUM_ELEMS; i++) - my_array[i] = i; - - for(i = 0; i < NUM_ROWS; i++) - for(j = 0; j < NUM_COLS; j++) - my_2d_array[i][j] = (i*NUM_COLS) + j; - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. */ - test_long_long_1d(my_array, NUM_ELEMS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. - The indices are transposed for Fortran. */ - test_long_long_2d(my_2d_array[0], NUM_COLS, NUM_ROWS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_long. */ - test_long_1d(my_array, NUM_ELEMS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_int. */ - test_int_1d(my_array, NUM_ELEMS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_short. */ - test_short_1d(my_array, NUM_ELEMS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_int and - kind=c_long_long. */ - test_mixed(my_array, NUM_ELEMS); - - return 0; -} diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03 b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03 index 3f60f17..519087a 100644 --- a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03 +++ b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03 @@ -1,5 +1,5 @@ ! { dg-do run } -! { dg-additional-sources c_f_pointer_shape_tests_2_driver.c } +! { dg-additional-sources c_f_pointer_shape_tests_driver.c } ! Verify that the optional SHAPE parameter to c_f_pointer can be of any ! valid integer kind. We don't test all kinds here since it would be ! difficult to know what kinds are valid for the architecture we're running on. diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c deleted file mode 100644 index 1282beb..0000000 --- a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c +++ /dev/null @@ -1,46 +0,0 @@ -#define NUM_ELEMS 10 -#define NUM_ROWS 2 -#define NUM_COLS 3 - -void test_long_long_1d(int *array, int num_elems); -void test_long_long_2d(int *array, int num_rows, int num_cols); -void test_long_1d(int *array, int num_elems); -void test_int_1d(int *array, int num_elems); -void test_short_1d(int *array, int num_elems); -void test_mixed(int *array, int num_elems); - -int main(int argc, char **argv) -{ - int my_array[NUM_ELEMS]; - int my_2d_array[NUM_ROWS][NUM_COLS]; - int i, j; - - for(i = 0; i < NUM_ELEMS; i++) - my_array[i] = i; - - for(i = 0; i < NUM_ROWS; i++) - for(j = 0; j < NUM_COLS; j++) - my_2d_array[i][j] = (i*NUM_COLS) + j; - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. */ - test_long_long_1d(my_array, NUM_ELEMS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. - The indices are transposed for Fortran. */ - test_long_long_2d(my_2d_array[0], NUM_COLS, NUM_ROWS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_long. */ - test_long_1d(my_array, NUM_ELEMS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_int. */ - test_int_1d(my_array, NUM_ELEMS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_short. */ - test_short_1d(my_array, NUM_ELEMS); - - /* Test c_f_pointer where SHAPE is of type integer, kind=c_int and - kind=c_long_long. */ - test_mixed(my_array, NUM_ELEMS); - - return 0; -} diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_driver.c b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_driver.c new file mode 100644 index 0000000..70e7d56 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_driver.c @@ -0,0 +1,47 @@ +#define NUM_ELEMS 10 +#define NUM_ROWS 2 +#define NUM_COLS 3 + +void test_long_long_1d (int *array, int num_elems); +void test_long_long_2d (int *array, int num_rows, int num_cols); +void test_long_1d (int *array, int num_elems); +void test_int_1d (int *array, int num_elems); +void test_short_1d (int *array, int num_elems); +void test_mixed (int *array, int num_elems); + +int +main (int argc, char **argv) +{ + int my_array[NUM_ELEMS]; + int my_2d_array[NUM_ROWS][NUM_COLS]; + int i, j; + + for (i = 0; i < NUM_ELEMS; i++) + my_array[i] = i; + + for (i = 0; i < NUM_ROWS; i++) + for (j = 0; j < NUM_COLS; j++) + my_2d_array[i][j] = (i * NUM_COLS) + j; + + /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. */ + test_long_long_1d (my_array, NUM_ELEMS); + + /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. + The indices are transposed for Fortran. */ + test_long_long_2d (my_2d_array[0], NUM_COLS, NUM_ROWS); + + /* Test c_f_pointer where SHAPE is of type integer, kind=c_long. */ + test_long_1d (my_array, NUM_ELEMS); + + /* Test c_f_pointer where SHAPE is of type integer, kind=c_int. */ + test_int_1d (my_array, NUM_ELEMS); + + /* Test c_f_pointer where SHAPE is of type integer, kind=c_short. */ + test_short_1d (my_array, NUM_ELEMS); + + /* Test c_f_pointer where SHAPE is of type integer, kind=c_int and + kind=c_long_long. */ + test_mixed (my_array, NUM_ELEMS); + + return 0; +} diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index 663a821..c19baba 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -1199,6 +1199,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) pp_string (pp, "from("); if (OMP_CLAUSE_MOTION_PRESENT (clause)) pp_string (pp, "present:"); + if (OMP_CLAUSE_ITERATORS (clause)) + { + dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags); + pp_colon (pp); + } dump_generic_node (pp, OMP_CLAUSE_DECL (clause), spc, flags, false); goto print_clause_size; @@ -1207,6 +1212,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) pp_string (pp, "to("); if (OMP_CLAUSE_MOTION_PRESENT (clause)) pp_string (pp, "present:"); + if (OMP_CLAUSE_ITERATORS (clause)) + { + dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags); + pp_colon (pp); + } dump_generic_node (pp, OMP_CLAUSE_DECL (clause), spc, flags, false); goto print_clause_size; diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc index dc82bf6..a9d4aae 100644 --- a/gcc/tree-vect-data-refs.cc +++ b/gcc/tree-vect-data-refs.cc @@ -4423,8 +4423,9 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) MASKED_P is true if the load or store is conditional. MEMORY_TYPE is the type of the memory elements being loaded or stored. OFFSET_TYPE is the type of the offset that is being applied to the invariant - base address. SCALE is the amount by which the offset should - be multiplied *after* it has been converted to address width. + base address. If OFFSET_TYPE is scalar the function chooses an + appropriate vector type for it. SCALE is the amount by which the + offset should be multiplied *after* it has been converted to address width. Return true if the function is supported, storing the function id in *IFN_OUT and the vector type for the offset in *OFFSET_VECTYPE_OUT. @@ -4467,9 +4468,15 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p, for (;;) { - tree offset_vectype = get_vectype_for_scalar_type (vinfo, offset_type); - if (!offset_vectype) - return false; + tree offset_vectype; + if (VECTOR_TYPE_P (offset_type)) + offset_vectype = offset_type; + else + { + offset_vectype = get_vectype_for_scalar_type (vinfo, offset_type); + if (!offset_vectype) + return false; + } /* Test whether the target supports this combination. */ if (internal_gather_scatter_fn_supported_p (ifn, vectype, memory_type, @@ -4500,10 +4507,15 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p, return true; } + /* For fixed offset vector type we're done. */ + if (VECTOR_TYPE_P (offset_type)) + return false; + if (TYPE_PRECISION (offset_type) >= POINTER_SIZE && TYPE_PRECISION (offset_type) >= element_bits) return false; + /* Try a larger offset vector type. */ offset_type = build_nonstandard_integer_type (TYPE_PRECISION (offset_type) * 2, TYPE_UNSIGNED (offset_type)); } @@ -4512,7 +4524,7 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p, /* STMT_INFO is a call to an internal gather load or scatter store function. Describe the operation in INFO. */ -static void +void vect_describe_gather_scatter_call (stmt_vec_info stmt_info, gather_scatter_info *info) { @@ -6524,7 +6536,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, tree vectype, int misalignment, gather_scatter_info *gs_info) { - data_reference *dr = dr_info ? dr_info->dr : nullptr; + data_reference *dr = dr_info->dr; stmt_vec_info stmt_info = dr_info->stmt; machine_mode mode = TYPE_MODE (vectype); loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo); @@ -6605,7 +6617,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, } } */ - if (dr && DR_IS_READ (dr)) + if (DR_IS_READ (dr)) { if (can_implement_p (vec_realign_load_optab, mode) && (!targetm.vectorize.builtin_mask_for_load @@ -6635,38 +6647,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, tree type = TREE_TYPE (DR_REF (dr)); bool is_gather_scatter = gs_info != nullptr; if (misalignment == DR_MISALIGNMENT_UNKNOWN) - { - if (!is_gather_scatter || dr != nullptr) - is_packed = not_size_aligned (DR_REF (dr)); - else - { - /* Gather-scatter accesses normally perform only component accesses - so alignment is irrelevant for them. Targets like riscv do care - about scalar alignment in vector accesses, though, so check scalar - alignment here. We determined the alias pointer as well as the - base alignment during pattern recognition and can re-use it here. - - As we do not have an analyzed dataref we only know the alignment - of the reference itself and nothing about init, steps, etc. - For now don't try harder to determine misalignment and - just assume it is unknown. We consider the type packed if its - scalar alignment is lower than the natural alignment of a vector - element's type. */ - - gcc_assert (!GATHER_SCATTER_LEGACY_P (*gs_info)); - gcc_assert (dr == nullptr); - - tree inner_vectype = TREE_TYPE (vectype); - - unsigned HOST_WIDE_INT scalar_align - = tree_to_uhwi (gs_info->alias_ptr); - unsigned HOST_WIDE_INT inner_vectype_sz - = tree_to_uhwi (TYPE_SIZE (inner_vectype)); - - bool is_misaligned = scalar_align < inner_vectype_sz; - is_packed = scalar_align > 1 && is_misaligned; - } - } + is_packed = not_size_aligned (DR_REF (dr)); if (targetm.vectorize.support_vector_misalignment (mode, type, misalignment, is_packed, is_gather_scatter)) diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 794a073..59acbc1 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -120,6 +120,8 @@ _slp_tree::_slp_tree () SLP_TREE_LANE_PERMUTATION (this) = vNULL; SLP_TREE_DEF_TYPE (this) = vect_uninitialized_def; SLP_TREE_CODE (this) = ERROR_MARK; + SLP_TREE_GS_SCALE (this) = 0; + SLP_TREE_GS_BASE (this) = NULL_TREE; this->ldst_lanes = false; this->avoid_stlf_fail = false; SLP_TREE_VECTYPE (this) = NULL_TREE; @@ -680,6 +682,15 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap, { internal_fn ifn = gimple_call_internal_fn (stmt); commutative_op = first_commutative_argument (ifn); + if (internal_gather_scatter_fn_p (ifn)) + { + vect_describe_gather_scatter_call + (stmt_info, + first ? &(*oprnds_info)[0]->first_gs_info : &gs_info); + if (first) + (*oprnds_info)[0]->first_gs_p = true; + gs_op = 0; + } } } else if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt)) @@ -2720,6 +2731,9 @@ out: stmt_info = stmts[0]; + int gs_scale = 0; + tree gs_base = NULL_TREE; + /* Create SLP_TREE nodes for the definition node/s. */ FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info) { @@ -2742,6 +2756,12 @@ out: continue; } + if (oprnd_info->first_gs_p) + { + gs_scale = oprnd_info->first_gs_info.scale; + gs_base = oprnd_info->first_gs_info.base; + } + if (is_a <bb_vec_info> (vinfo) && oprnd_info->first_dt == vect_internal_def && !oprnd_info->any_pattern) @@ -3131,6 +3151,8 @@ fail: node = vect_create_new_slp_node (node, stmts, nops); SLP_TREE_VECTYPE (node) = vectype; SLP_TREE_CHILDREN (node).splice (children); + SLP_TREE_GS_SCALE (node) = gs_scale; + SLP_TREE_GS_BASE (node) = gs_base; return node; } diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index f7a052b..a6f4db4 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -1497,7 +1497,8 @@ check_load_store_for_partial_vectors (loop_vec_info loop_vinfo, tree vectype, gs_info->memory_type, gs_info->offset_vectype, gs_info->scale, - elsvals)) + elsvals) + || gs_info->decl != NULL_TREE) vect_record_loop_mask (loop_vinfo, masks, nvectors, vectype, scalar_mask); else @@ -2018,31 +2019,40 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)) { *memory_access_type = VMAT_GATHER_SCATTER; - if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info, - elsvals)) - gcc_unreachable (); slp_tree offset_node = SLP_TREE_CHILDREN (slp_node)[0]; tree offset_vectype = SLP_TREE_VECTYPE (offset_node); + memset (gs_info, 0, sizeof (gather_scatter_info)); gs_info->offset_vectype = offset_vectype; - /* When using internal functions, we rely on pattern recognition - to convert the type of the offset to the type that the target - requires, with the result being a call to an internal function. - If that failed for some reason (e.g. because another pattern - took priority), just handle cases in which the offset already - has the right type. */ - if (GATHER_SCATTER_IFN_P (*gs_info) - && !is_gimple_call (stmt_info->stmt) - && !tree_nop_conversion_p (TREE_TYPE (gs_info->offset), - TREE_TYPE (offset_vectype))) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "%s offset requires a conversion\n", - vls_type == VLS_LOAD ? "gather" : "scatter"); - return false; - } - else if (GATHER_SCATTER_EMULATED_P (*gs_info)) + gs_info->scale = SLP_TREE_GS_SCALE (slp_node); + gs_info->base = SLP_TREE_GS_BASE (slp_node); + gs_info->memory_type = TREE_TYPE (DR_REF (first_dr_info->dr)); + gs_info->decl = NULL_TREE; + gs_info->ifn = IFN_LAST; + tree tem; + if (vect_gather_scatter_fn_p (loop_vinfo, vls_type == VLS_LOAD, + masked_p, vectype, + gs_info->memory_type, + offset_vectype, gs_info->scale, + &gs_info->ifn, &tem, + elsvals)) + /* GATHER_SCATTER_IFN_P. */; + else if (vls_type == VLS_LOAD + ? (targetm.vectorize.builtin_gather + && (gs_info->decl + = targetm.vectorize.builtin_gather (vectype, + TREE_TYPE + (offset_vectype), + gs_info->scale))) + : (targetm.vectorize.builtin_scatter + && (gs_info->decl + = targetm.vectorize.builtin_scatter (vectype, + TREE_TYPE + (offset_vectype), + gs_info->scale)))) + /* GATHER_SCATTER_LEGACY_P. */; + else { + /* GATHER_SCATTER_EMULATED_P. */ if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant () || !TYPE_VECTOR_SUBPARTS (offset_vectype).is_constant () || VECTOR_BOOLEAN_TYPE_P (offset_vectype) @@ -8529,7 +8539,6 @@ vectorizable_store (vec_info *vinfo, gcc_assert (useless_type_conversion_p (vectype, TREE_TYPE (vec_oprnd))); } - unsigned HOST_WIDE_INT align; tree final_mask = NULL_TREE; tree final_len = NULL_TREE; tree bias = NULL_TREE; @@ -8544,6 +8553,8 @@ vectorizable_store (vec_info *vinfo, final_mask, vec_mask, gsi); } + unsigned align = get_object_alignment (DR_REF (first_dr_info->dr)); + tree alias_align_ptr = build_int_cst (ref_type, align); if (GATHER_SCATTER_IFN_P (gs_info)) { if (costing_p) @@ -8585,7 +8596,7 @@ vectorizable_store (vec_info *vinfo, if (VECTOR_TYPE_P (TREE_TYPE (vec_offset))) call = gimple_build_call_internal ( IFN_MASK_LEN_SCATTER_STORE, 8, dataref_ptr, - gs_info.alias_ptr, + alias_align_ptr, vec_offset, scale, vec_oprnd, final_mask, final_len, bias); else @@ -8602,12 +8613,12 @@ vectorizable_store (vec_info *vinfo, else if (final_mask) call = gimple_build_call_internal (IFN_MASK_SCATTER_STORE, 6, dataref_ptr, - gs_info.alias_ptr, + alias_align_ptr, vec_offset, scale, vec_oprnd, final_mask); else call = gimple_build_call_internal (IFN_SCATTER_STORE, 5, dataref_ptr, - gs_info.alias_ptr, + alias_align_ptr, vec_offset, scale, vec_oprnd); gimple_call_set_nothrow (call, true); @@ -8763,7 +8774,6 @@ vectorizable_store (vec_info *vinfo, = (j % factor) * const_nunits; tree idx_type = TREE_TYPE (TREE_TYPE (vec_offset)); tree scale = size_int (gs_info.scale); - align = get_object_alignment (DR_REF (first_dr_info->dr)); tree ltype = build_aligned_type (TREE_TYPE (vectype), align); for (unsigned k = 0; k < const_nunits; ++k) { @@ -10392,7 +10402,8 @@ vectorizable_load (vec_info *vinfo, } /* 2. Create the vector-load in the loop. */ - unsigned HOST_WIDE_INT align; + unsigned align = get_object_alignment (DR_REF (first_dr_info->dr)); + tree alias_align_ptr = build_int_cst (ref_type, align); if (GATHER_SCATTER_IFN_P (gs_info)) { if (costing_p) @@ -10440,7 +10451,7 @@ vectorizable_load (vec_info *vinfo, if (VECTOR_TYPE_P (TREE_TYPE (vec_offset))) call = gimple_build_call_internal (IFN_MASK_LEN_GATHER_LOAD, 9, dataref_ptr, - gs_info.alias_ptr, + alias_align_ptr, vec_offset, scale, zero, final_mask, vec_els, final_len, bias); @@ -10456,13 +10467,13 @@ vectorizable_load (vec_info *vinfo, else if (final_mask) call = gimple_build_call_internal (IFN_MASK_GATHER_LOAD, 7, dataref_ptr, - gs_info.alias_ptr, + alias_align_ptr, vec_offset, scale, zero, final_mask, vec_els); else call = gimple_build_call_internal (IFN_GATHER_LOAD, 5, dataref_ptr, - gs_info.alias_ptr, + alias_align_ptr, vec_offset, scale, zero); gimple_call_set_nothrow (call, true); new_stmt = call; @@ -10620,7 +10631,6 @@ vectorizable_load (vec_info *vinfo, unsigned elt_offset = (i % factor) * const_nunits; tree idx_type = TREE_TYPE (TREE_TYPE (vec_offset)); tree scale = size_int (gs_info.scale); - align = get_object_alignment (DR_REF (first_dr_info->dr)); tree ltype = build_aligned_type (TREE_TYPE (vectype), align); for (unsigned k = 0; k < const_nunits; ++k) { diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 52e1075..9653496 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -306,6 +306,11 @@ struct _slp_tree { unsigned int lanes; /* The operation of this node. */ enum tree_code code; + /* For gather/scatter memory operations the scale each offset element + should be multiplied by before being added to the base. */ + int gs_scale; + /* For gather/scatter memory operations the loop-invariant base value. */ + tree gs_base; /* Whether uses of this load or feeders of this store are suitable for load/store-lanes. */ bool ldst_lanes; @@ -412,6 +417,8 @@ public: #define SLP_TREE_CODE(S) (S)->code #define SLP_TREE_MEMORY_ACCESS_TYPE(S) (S)->memory_access_type #define SLP_TREE_TYPE(S) (S)->type +#define SLP_TREE_GS_SCALE(S) (S)->gs_scale +#define SLP_TREE_GS_BASE(S) (S)->gs_base enum vect_partial_vector_style { vect_partial_vectors_none, @@ -2550,6 +2557,8 @@ extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree, extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info, gather_scatter_info *, vec<int> * = nullptr); +extern void vect_describe_gather_scatter_call (stmt_vec_info, + gather_scatter_info *); extern opt_result vect_find_stmt_data_reference (loop_p, gimple *, vec<data_reference_p> *, vec<int> *, int); diff --git a/gcc/tree.cc b/gcc/tree.cc index 203cc1c..dcc1abd 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -323,8 +323,8 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_IS_DEVICE_PTR */ 1, /* OMP_CLAUSE_INCLUSIVE */ 1, /* OMP_CLAUSE_EXCLUSIVE */ - 2, /* OMP_CLAUSE_FROM */ - 2, /* OMP_CLAUSE_TO */ + 3, /* OMP_CLAUSE_FROM */ + 3, /* OMP_CLAUSE_TO */ 3, /* OMP_CLAUSE_MAP (update walk_tree_1 if this is changed) */ 1, /* OMP_CLAUSE_HAS_DEVICE_ADDR */ 1, /* OMP_CLAUSE_DOACROSS */ @@ -1660,11 +1660,13 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_LOCATION(NODE) (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus #define OMP_CLAUSE_HAS_ITERATORS(NODE) \ - (OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_MAP \ + ((OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_FROM \ + || OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_TO \ + || OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_MAP) \ && OMP_CLAUSE_ITERATORS (NODE)) #define OMP_CLAUSE_ITERATORS(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \ - OMP_CLAUSE_MAP, \ + OMP_CLAUSE_FROM, \ OMP_CLAUSE_MAP), 2) /* True on OMP_FOR and other OpenMP/OpenACC looping constructs if the loop nest |