diff options
69 files changed, 1427 insertions, 173 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 00f62e1..eebaa03 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,69 @@ +2025-11-01 Shreya Munnangi <smunnangi1@ventanamicro.com> + + PR target/67731 + * simplify-rtx.cc (simplify_context::simplify_binary_operation_1): + Handle IOR of single bit bitfields from the same object. + +2025-11-01 Jeff Law <jlaw@ventanamicro.com> + + * config/riscv/riscv-protos.h (has_vtype_op): Add prototype. + (mask_agnostic_p, get_avl, vsetvl_insn_p): Likewise. + * config/riscv/riscv-vsetvl.cc (has_vtype_op): No longer static. + (vsetvl_insn_p, get_avl_mask_agnostic_p): Likewise. + * config/riscv/riscv.cc (struct last_vcofnig): New structure. + (clear_vconfig): New function. + (compatible_with_last_vconfig, riscv_sched_init): Likewise. + (riscv_sched_reorder): Likewise. + (TARGET_SCHED_INIT, TARGET_SCHED_REORDER): Define. + * config/riscv/vector.md ("*mov<mode>"): Set has_vtype_op, has_vl_op + attributes. + * .simplify-rtx.cc.swo: New file. + +2025-11-01 Jeff Law <jlaw@ventanamicro.com> + + PR rtl-optimization/122321 + * lra-constraints.cc (update_equiv): Make sure REGNO is in + ira_reg_equiv before trying to update ira_reg_equiv. + +2025-11-01 Martin Uecker <uecker@tugraz.at> + + * doc/extend.texi: Document new extension. + +2025-11-01 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * config/xtensa/xtensa.md (negsf2): + Add another insn pattern that is valid when TARGET_DENSITY is + enabled and both the source and destination are address registers. + +2025-11-01 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * config/xtensa/xtensa.md + (c_enum "unspec", int_iterator ANY_ROUND): Add UNSPEC_ROUND. + (int_attr m_round): Add a pair of UNSPEC_ROUND and "round". + (int_attr c_round): New integer iterator attribute, that expands + to "flag_unsafe_math_optimizations" in the case of UNSPEC_ROUND, + and to "1" otherwise. + (l<m_round>sfsi2, *l<m_round>sfsi2_2x, *l<m_round>sfsi2_scaled): + Append " && <c_round>" to the conditions. + +2025-11-01 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * config/xtensa/xtensa.md (*fix<s_fix>_truncsfsi2_scaled, + *float<s_float>sisf2_scaled, *l<m_round>sfsi2_scaled): + Remove 'F'-constraint. + +2025-11-01 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR ipa/122512 + * cgraph.h (enum toplevel_type): Add TOPLEVEL_MAX. Add comment + about keeping toplevel_type_names in sync. + * symtab.cc (symtab_type_names): Rename to ... + (toplevel_type_names): Add new types and add an assert about + the size. + (symtab_node::get_symtab_type_string): Use toplevel_type_names + instead of symtab_type_names. + (symtab_node::dump_base): Likewise. + 2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com> PR tree-optimization/122437 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 38eec11..befd735 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251101 +20251102 diff --git a/gcc/ada/locales.c b/gcc/ada/locales.c index a3f884c..89c5b7b 100644 --- a/gcc/ada/locales.c +++ b/gcc/ada/locales.c @@ -646,7 +646,7 @@ str_get_last_byte (char *lc_all) { return last_byte; } -/* Utility function to search in the iso_639_1 table for an iso-639-1 code; +/* Utility function to search in the iso_639 table for an iso-639-1 code; returns the corresponding iso-639-3 code or NULL if not found. */ static char* @@ -670,7 +670,30 @@ iso_639_1_to_639_3(char* iso_639_1_code) { return NULL; } -/* Utility function to search in the iso_639_1 table for a language name; +/* Utility function to search in the iso_639 table for an iso-639-3 code; + returns 1 if found or 0 if not found. */ + +static int +is_iso_639_3(char* iso_639_3_code) { + int len = ARRAY_SIZE (iso_639); + char **p = iso_639; + int j; + + p = p + 1; + for (j=0; j < len/3; j++) { + char* s1 = iso_639_3_code; + char* s2 = *p; + + if (s1[0]==s2[0] && s1[1]==s2[1] && s1[2]==s2[2]) + return 1; + + p = p + 3; + } + + return 0; +} + +/* Utility function to search in the iso_639 table for a language name; returns the corresponding iso-639-3 code or NULL if not found. */ static char* @@ -772,7 +795,8 @@ c_get_language_code (char4 p) { /* Copy the ISO-639-3 code (adding a null terminator) */ } else if (lang_length == 3) { - str_copy(iso_639_3_code, lc_all, lang_length); + if (is_iso_639_3(lc_all)) + str_copy(iso_639_3_code, lc_all, lang_length); /* Handle conversion of language name to ISO-639-3 */ diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index aa15166..79986bb 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -8500,26 +8500,28 @@ package body Sem_Ch3 is Full_P := Full_View (Parent_Type); -- A type extension of a type with unknown discriminants is an - -- indefinite type that the back-end cannot handle directly. + -- indefinite type that the back end cannot handle directly. -- We treat it as a private type, and build a completion that is -- derived from the full view of the parent, and hopefully has - -- known discriminants. + -- known discriminants. Note that the type will nevertheless be + -- turned into a public type in Build_Derived_Record_Type as for + -- any other extension; the only difference is the completion. -- If the full view of the parent type has an underlying record view, - -- use it to generate the underlying record view of this derived type + -- use it to generate the underlying record view of the derived type -- (required for chains of derivations with unknown discriminants). - -- Minor optimization: we avoid the generation of useless underlying - -- record view entities if the private type declaration has unknown - -- discriminants but its corresponding full view has no - -- discriminants. + -- Minor optimization: we avoid creating useless underlying record + -- view entities when the private type has unknown discriminants but + -- its corresponding full view has no discriminants. if Has_Unknown_Discriminants (Parent_Type) and then Present (Full_P) and then (Has_Discriminants (Full_P) or else Present (Underlying_Record_View (Full_P))) - and then not In_Open_Scopes (Par_Scope) - and then Expander_Active + and then (not In_Open_Scopes (Par_Scope) + or else not (In_Package_Body (Par_Scope) + or else In_Private_Part (Par_Scope))) then declare Full_Der : constant Entity_Id := Make_Temporary (Loc, 'T'); @@ -8534,7 +8536,7 @@ package body Sem_Ch3 is -- Build anonymous completion, as a derivation from the full -- view of the parent. This is not a completion in the usual - -- sense, because the current type is not private. + -- sense, because the derived type is no longer private. Decl := Make_Full_Type_Declaration (Loc, @@ -8557,8 +8559,18 @@ package body Sem_Ch3 is Underlying_Record_View (Full_P)); end if; + -- If the extension is done in the public part of the scope of + -- the parent, its visible declarations have been installed, so + -- we first need to uninstall them before reinstalling both the + -- private and the visible declarations in this order. + + if In_Open_Scopes (Par_Scope) then + Uninstall_Declarations (Par_Scope); + end if; + Install_Private_Declarations (Par_Scope); Install_Visible_Declarations (Par_Scope); + Insert_Before (N, Decl); -- Mark entity as an underlying record view before analysis, @@ -8582,6 +8594,13 @@ package body Sem_Ch3 is Uninstall_Declarations (Par_Scope); + -- If the extension is done in the public part of the scope of + -- the parent, reinstall the visible declarations only. + + if In_Open_Scopes (Par_Scope) then + Install_Visible_Declarations (Par_Scope); + end if; + if Etype (Full_Der) = Any_Type then pragma Assert (Serious_Errors_Detected > 0); return; @@ -10007,13 +10026,15 @@ package body Sem_Ch3 is or else Unknown_Discriminants_Present (N)); -- The partial view of the parent may have unknown discriminants, - -- but if the full view has discriminants and the parent type is - -- in scope they must be inherited. + -- but when its full view has discriminants and is visible, then + -- these discriminants must be inherited. elsif Has_Unknown_Discriminants (Parent_Type) and then (not Has_Discriminants (Parent_Type) - or else not In_Open_Scopes (Scope (Parent_Base))) + or else not In_Open_Scopes (Scope (Parent_Base)) + or else not (In_Package_Body (Scope (Parent_Base)) + or else In_Private_Part (Scope (Parent_Base)))) then Set_Has_Unknown_Discriminants (Derived_Type); end if; @@ -15144,19 +15165,20 @@ package body Sem_Ch3 is Fixup_Bad_Constraint; return; - -- Check that the type has visible discriminants. The type may be - -- a private type with unknown discriminants whose full view has - -- discriminants which are invisible. + -- Check that the type has known discriminants - elsif not Has_Discriminants (T) - or else - (Has_Unknown_Discriminants (T) - and then Is_Private_Type (T)) - then + elsif Has_Unknown_Discriminants (T) then + Error_Msg_N ("invalid constraint: type has unknown discriminants", C); + Fixup_Bad_Constraint; + return; + + elsif not Has_Discriminants (T) then Error_Msg_N ("invalid constraint: type has no discriminant", C); Fixup_Bad_Constraint; return; + -- And is not already constrained + elsif Is_Constrained (E) or else (Ekind (E) = E_Class_Wide_Subtype and then Present (Discriminant_Constraint (E))) diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index e9d00d0..a83ac64 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -5330,11 +5330,6 @@ package body Sem_Ch8 is --------------------- procedure End_Use_Package (N : Node_Id) is - Pack : Entity_Id; - Pack_Name : Node_Id; - Id : Entity_Id; - Elmt : Elmt_Id; - function Type_In_Use (T : Entity_Id; P : Entity_Id) return Boolean; -- Check whether type T is declared in P and appears in an active -- use_type clause. @@ -5349,6 +5344,14 @@ package body Sem_Ch8 is return Scope (BT) = P and then (In_Use (T) or else In_Use (BT)); end Type_In_Use; + -- Local variables + + Elmt : Elmt_Id; + Id : Entity_Id; + Pack : Entity_Id; + Pack_Name : Node_Id; + Scop : Entity_Id; + -- Start of processing for End_Use_Package begin @@ -5373,17 +5376,20 @@ package body Sem_Ch8 is -- Preserve use-visibility of operators that are primitive -- operators of a type that is use-visible through an active - -- use_type_clause. + -- use_type_clause. Note that we compare with the scope of + -- the operator and not Pack itself, lest Pack be a renaming. + + Scop := Scope (Id); if Nkind (Id) = N_Defining_Operator_Symbol and then - (Type_In_Use (Etype (Id), Pack) - or else Type_In_Use (Etype (First_Formal (Id)), Pack) + (Type_In_Use (Etype (Id), Scop) + or else Type_In_Use (Etype (First_Formal (Id)), Scop) or else (Present (Next_Formal (First_Formal (Id))) and then Type_In_Use - (Etype (Next_Formal (First_Formal (Id))), Pack))) + (Etype (Next_Formal (First_Formal (Id))), Scop))) then null; else diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 274e2a7..23cc53a 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,21 @@ +2025-11-01 Martin Uecker <uecker@tugraz.at> + + * c-decl.cc (build_compound_literal): Add error. + * c-parser.cc (c_parser_braced_init): Take bool argument for + variable size instead of DECL. + (c_parser_initializer,c_parser_initval): Adapt. + (c_parser_postfix_expression_after_paren_type): Change + error to pedwarn. + * c-typeck.cc (process_init_element): Add error for + variable-size compound literal with static or constexpr. + +2025-11-01 Martin Uecker <uecker@tugraz.at> + + PR c/97986 + * c-parser.cc (c_parser_postfix_expression): Adapt. + * c-tree.h (c_build_va_arg): Adapt prototype. + * c-typeck.cc (c_build_va_arg): Handle UB. + 2025-10-30 Qing Zhao <qing.zhao@oracle.com> * c-typeck.cc (build_access_with_size_for_counted_by): When the element diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 2b31a43..1e1da2d 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -6536,6 +6536,10 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const, return error_mark_node; } + if ((TREE_STATIC (decl) || C_DECL_DECLARED_CONSTEXPR (decl)) + && C_TYPE_VARIABLE_SIZE (type)) + error_at (loc, "storage size isn%'t constant"); + if (TREE_STATIC (decl) && !verify_type_context (loc, TCTX_STATIC_STORAGE, type)) return error_mark_node; diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 0cf3f92..9b3a786 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1767,7 +1767,7 @@ static tree c_parser_simple_asm_expr (c_parser *); static tree c_parser_gnu_attributes (c_parser *); static struct c_expr c_parser_initializer (c_parser *, tree); static struct c_expr c_parser_braced_init (c_parser *, tree, bool, - struct obstack *, tree); + struct obstack *, bool); static void c_parser_initelt (c_parser *, struct obstack *); static void c_parser_initval (c_parser *, struct c_expr *, struct obstack *); @@ -6459,7 +6459,9 @@ static struct c_expr c_parser_initializer (c_parser *parser, tree decl) { if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) - return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl); + return c_parser_braced_init (parser, NULL_TREE, false, NULL, + decl != error_mark_node + && C_DECL_VARIABLE_SIZE (decl)); else { struct c_expr ret; @@ -6499,12 +6501,12 @@ location_t last_init_list_comma; compound literal, and NULL_TREE for other initializers and for nested braced lists. NESTED_P is true for nested braced lists, false for the list of a compound literal or the list that is the - top-level initializer in a declaration. DECL is the declaration for - the top-level initializer for a declaration, otherwise NULL_TREE. */ + top-level initializer in a declaration. VARSIZE_P indicates + wether the object to be initialized has a variable size. */ static struct c_expr c_parser_braced_init (c_parser *parser, tree type, bool nested_p, - struct obstack *outer_obstack, tree decl) + struct obstack *outer_obstack, bool varsize_p) { struct c_expr ret; struct obstack braced_init_obstack; @@ -6532,7 +6534,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, } else { - if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl)) + if (varsize_p) error_at (brace_loc, "variable-sized object may not be initialized except " "with an empty initializer"); @@ -6826,7 +6828,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after) init = c_parser_braced_init (parser, NULL_TREE, true, - braced_init_obstack, NULL_TREE); + braced_init_obstack, false); else { init = c_parser_expr_no_commas (parser, after); @@ -11793,15 +11795,9 @@ c_parser_postfix_expression (c_parser *parser) else { tree type_expr = NULL_TREE; + tree type = groktypename (t1, &type_expr, NULL); expr.value = c_build_va_arg (start_loc, e1.value, loc, - groktypename (t1, &type_expr, NULL)); - if (type_expr) - { - expr.value = build2 (C_MAYBE_CONST_EXPR, - TREE_TYPE (expr.value), type_expr, - expr.value); - C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true; - } + type, type_expr); set_c_expr_source_range (&expr, start_loc, end_loc); } } @@ -13516,10 +13512,11 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, || (scspecs && scspecs->storage_class == csc_static) || constexpr_p), constexpr_p, &richloc); type = groktypename (type_name, &type_expr, &type_expr_const); + bool varsize_p = false; if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type)) { - error_at (type_loc, "compound literal has variable size"); - type = error_mark_node; + pedwarn (type_loc, OPT_Wpedantic, "compound literal has variable size"); + varsize_p = true; } else if (TREE_CODE (type) == FUNCTION_TYPE) { @@ -13544,7 +13541,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, (TYPE_QUALS (type_no_array) | TYPE_QUAL_CONST)); } - init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE); + init = c_parser_braced_init (parser, type, false, NULL, varsize_p); if (constexpr_p) finish_underspecified_init (NULL_TREE, underspec_state); finish_init (); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index f367cda..ff63d69 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -917,7 +917,7 @@ extern tree c_omp_finish_mapper_clauses (tree); extern tree c_omp_mapper_lookup (tree, tree); extern tree c_omp_extract_mapper_directive (tree); extern tree c_omp_map_array_section (location_t, tree); -extern tree c_build_va_arg (location_t, tree, location_t, tree); +extern tree c_build_va_arg (location_t, tree, location_t, tree, tree); extern tree c_finish_transaction (location_t, tree, int); extern bool c_tree_equal (tree, tree); extern tree c_build_function_call_vec (location_t, const vec<location_t>&, diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index bc0fb6b..2cef463 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -12734,7 +12734,9 @@ retry: if (constructor_max_index != NULL_TREE && (tree_int_cst_lt (constructor_max_index, constructor_index) - || integer_all_onesp (constructor_max_index))) + || integer_all_onesp (constructor_max_index)) + /* For VLA we got an error already. */ + && !C_TYPE_VARIABLE_SIZE (constructor_type)) { pedwarn_init (loc, 0, "excess elements in array initializer"); @@ -18435,7 +18437,8 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, /* Build a VA_ARG_EXPR for the C parser. */ tree -c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type) +c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type, + tree type_expr) { if (error_operand_p (type)) return error_mark_node; @@ -18459,10 +18462,36 @@ c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type) type); return error_mark_node; } + else if (TREE_CODE (type) == ARRAY_TYPE && C_TYPE_VARIABLE_SIZE (type) + && !flag_isoc99) + { + error_at (loc2, "second argument to %<va_arg%> is an array type %qT", + type); + return error_mark_node; + } else if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE) warning_at (loc2, OPT_Wc___compat, "C++ requires promoted type, not enum type, in %<va_arg%>"); - return build_va_arg (loc2, expr, type); + + if (flag_isoc99 && TREE_CODE (type) == ARRAY_TYPE) + { + warning_at (loc2, 0, "second argument to %<va_arg%> is an array type %qT", + type); + /* We create a trap but evaluate side effects first. */ + tree trapfn = builtin_decl_explicit (BUILT_IN_TRAP); + trapfn = build_call_expr_loc (loc2, trapfn, 0); + tree e2 = build2 (COMPOUND_EXPR, void_type_node, expr, trapfn); + /* Return a compound literal of the right type. */ + tree e1 = build_compound_literal (loc2, type, NULL, true, 0, NULL); + expr = build2 (COMPOUND_EXPR, type, e2, e1); + } + else + expr = build_va_arg (loc2, expr, type); + + if (type_expr) + expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), type_expr, expr); + + return expr; } /* Return truthvalue of whether T1 is the same tree structure as T2. diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 227c12a..0bdba55 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -3272,7 +3272,8 @@ avr_load_libgcc_p (rtx op) return (n_bytes > 2 && !AVR_HAVE_LPMX - && avr_mem_flash_p (op)); + && avr_mem_flash_p (op) + && MEM_ADDR_SPACE (op) == ADDR_SPACE_FLASH); } @@ -3624,6 +3625,46 @@ avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen) avr_asm_len ("sbiw %2,1", xop, plen, 1); break; /* 2 */ + + /* cases 3 and 4 are only needed with ELPM but no ELPMx. */ + + case 3: + if (REGNO (dest) == REG_Z - 2 + && !reg_unused_after (insn, all_regs_rtx[REG_31])) + avr_asm_len ("push r31", xop, plen, 1); + + avr_asm_len ("%4lpm $ mov %A0,%3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %B0,%3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %C0,%3", xop, plen, 2); + + if (REGNO (dest) == REG_Z - 2) + { + if (!reg_unused_after (insn, all_regs_rtx[REG_31])) + avr_asm_len ("pop r31", xop, plen, 1); + } + else if (!reg_unused_after (insn, addr)) + avr_asm_len ("sbiw %2,2", xop, plen, 1); + + break; /* 3 */ + + case 4: + avr_asm_len ("%4lpm $ mov %A0,%3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %B0,%3 $ adiw %2,1", xop, plen, 3); + if (REGNO (dest) != REG_Z - 2) + { + avr_asm_len ("%4lpm $ mov %C0,%3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %D0,%3", xop, plen, 2); + if (!reg_unused_after (insn, addr)) + avr_asm_len ("sbiw %2,3", xop, plen, 1); + } + else + { + avr_asm_len ("%4lpm $ push %3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %D0,%3", xop, plen, 2); + avr_asm_len ("pop $C0", xop, plen, 1); + } + + break; /* 4 */ } break; /* REG */ diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 30a02a4..d73cf96 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -3947,9 +3947,17 @@ (match_operand:PSI 2 "nonmemory_operand" ""))) (clobber (reg:HI 26)) (clobber (reg:DI 18))])] - "AVR_HAVE_MUL" + "AVR_HAVE_MUL + || (avropt_pr118012 + /* AVR_TINY passes args on the stack, so we cannot work + around PR118012 like this. */ + && ! AVR_TINY)" { - if (s8_operand (operands[2], PSImode)) + if (!AVR_HAVE_MUL) + { + operands[2] = force_reg (PSImode, operands[2]); + } + else if (s8_operand (operands[2], PSImode)) { rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode)); emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1])); @@ -4038,7 +4046,9 @@ (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn"))) (clobber (reg:HI 26)) (clobber (reg:DI 18))] - "AVR_HAVE_MUL && !reload_completed" + "!reload_completed + && (AVR_HAVE_MUL + || (avropt_pr118012 && !AVR_TINY))" { gcc_unreachable(); } "&& 1" [(set (reg:PSI 18) @@ -4048,13 +4058,30 @@ (parallel [(set (reg:PSI 22) (mult:PSI (reg:PSI 22) (reg:PSI 18))) - (clobber (reg:QI 21)) - (clobber (reg:QI 25)) - (clobber (reg:HI 26))]) + (clobber (match_dup 3)) + (clobber (match_dup 4)) + (clobber (match_dup 5))]) (set (match_dup 0) (reg:PSI 22))] { - if (s8_operand (operands[2], PSImode)) + if (AVR_HAVE_MUL) + { + operands[3] = gen_rtx_REG (QImode, REG_21); + operands[4] = gen_rtx_REG (QImode, REG_25); + operands[5] = gen_rtx_REG (HImode, REG_26); + } + else + { + operands[3] = gen_rtx_REG (SImode, REG_18); + operands[4] = gen_rtx_SCRATCH (QImode); + operands[5] = gen_rtx_SCRATCH (HImode); + } + + if (!AVR_HAVE_MUL) + { + operands[2] = force_reg (PSImode, operands[2]); + } + else if (s8_operand (operands[2], PSImode)) { rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode)); emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1])); @@ -4106,6 +4133,32 @@ "%~call __mulpsi3" [(set_attr "type" "xcall")]) +(define_insn_and_split "*mulpsi3-nomul.libgcc_split" + [(set (reg:PSI 22) + (mult:PSI (reg:PSI 22) + (reg:PSI 18))) + (clobber (reg:SI 18)) + (clobber (scratch:QI)) + (clobber (scratch:HI))] + "!AVR_HAVE_MUL && avropt_pr118012 && !AVR_TINY" + "#" + "&& reload_completed" + [(scratch)] + { DONE_ADD_CCC }) + +(define_insn "*mulpsi3-nomul.libgcc" + [(set (reg:PSI 22) + (mult:PSI (reg:PSI 22) + (reg:PSI 18))) + (clobber (reg:SI 18)) + (clobber (scratch:QI)) + (clobber (scratch:HI)) + (clobber (reg:CC REG_CC))] + "reload_completed + && !AVR_HAVE_MUL && avropt_pr118012 && !AVR_TINY" + "%~call __mulpsi3" + [(set_attr "type" "xcall")]) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 24-bit signed/unsigned division and modulo. diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 587b2bd..6b6febc 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -598,6 +598,20 @@ ix86_canonicalize_comparison (int *code, rtx *op0, rtx *op1, } } + /* SUB (a, b) underflows precisely when a < b. Convert + (compare (minus (a b)) a) to (compare (a b)) + to match *sub<mode>_3 pattern. */ + if (!op0_preserve_value + && (*code == GTU || *code == LEU) + && GET_CODE (*op0) == MINUS + && rtx_equal_p (XEXP (*op0, 0), *op1)) + { + *op1 = XEXP (*op0, 1); + *op0 = XEXP (*op0, 0); + *code = (int) swap_condition ((enum rtx_code) *code); + return; + } + /* Swap operands of GTU comparison to canonicalize addcarry/subborrow comparison. */ if (!op0_preserve_value diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index 697198f..166ddd9 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -357,7 +357,7 @@ { if (TARGET_XTHEADBB && !immediate_operand (operands[2], VOIDmode)) FAIL; - if (TARGET_64BIT && register_operand (operands[2], QImode)) + if (TARGET_64BIT) { rtx t = gen_reg_rtx (DImode); emit_insn (gen_rotrsi3_sext (t, operands[1], operands[2])); diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index cdb706a..570acb1 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -209,6 +209,11 @@ rtl_opt_pass * make_pass_insert_landing_pad (gcc::context *ctxt); rtl_opt_pass * make_pass_vector_permconst (gcc::context *ctxt); rtl_opt_pass * make_pass_bclr_lowest_set_bit (gcc::context *ctxt); +/* Routines implemented in riscv-vsetvl.cc. */ +extern bool has_vtype_op (rtx_insn *); +extern bool mask_agnostic_p (rtx_insn *); +extern rtx get_avl (rtx_insn *); +extern bool vsetvl_insn_p (rtx_insn *); /* Routines implemented in riscv-string.c. */ extern bool riscv_expand_block_compare (rtx, rtx, rtx, rtx); diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc index 3586d0c..580ac9c 100644 --- a/gcc/config/riscv/riscv-vsetvl.cc +++ b/gcc/config/riscv/riscv-vsetvl.cc @@ -258,7 +258,7 @@ policy_to_str (bool agnostic_p) /* Return true if it is an RVV instruction depends on VTYPE global status register. */ -static bool +bool has_vtype_op (rtx_insn *rinsn) { return recog_memoized (rinsn) >= 0 && get_attr_has_vtype_op (rinsn); @@ -306,7 +306,7 @@ vector_config_insn_p (rtx_insn *rinsn) } /* Return true if it is vsetvldi or vsetvlsi. */ -static bool +bool vsetvl_insn_p (rtx_insn *rinsn) { if (!rinsn || !vector_config_insn_p (rinsn)) @@ -386,7 +386,7 @@ get_vl (rtx_insn *rinsn) } /* Helper function to get AVL operand. */ -static rtx +rtx get_avl (rtx_insn *rinsn) { if (vsetvl_insn_p (rinsn) || vsetvl_discard_result_insn_p (rinsn)) @@ -411,7 +411,7 @@ get_default_ma () } /* Helper function to get MA operand. */ -static bool +bool mask_agnostic_p (rtx_insn *rinsn) { /* If it doesn't have MA, we return agnostic by default. */ diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 63404d3..e978f92 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -10576,6 +10576,71 @@ riscv_issue_rate (void) return tune_param->issue_rate; } +/* Structure for very basic vector configuration tracking in the scheduler. */ +struct last_vconfig +{ + bool valid; + bool ta; + bool ma; + uint8_t sew; + uint8_t vlmul; + rtx avl; +} last_vconfig; + +/* Clear LAST_VCONFIG so we have no known state. */ +static void +clear_vconfig (void) +{ + memset (&last_vconfig, 0, sizeof (last_vconfig)); +} + +/* Return TRUE if INSN is a vector insn needing a particular + vector configuration that is trivially equal to the last + vector insn issued. Return FALSE otherwise. */ +static bool +compatible_with_last_vconfig (rtx_insn *insn) +{ + /* We might be able to extract the data from a preexisting vsetvl. */ + if (vsetvl_insn_p (insn)) + return false; + + /* Nothing to do for these cases. */ + if (!NONDEBUG_INSN_P (insn) || !has_vtype_op (insn)) + return false; + + extract_insn_cached (insn); + + rtx avl = get_avl (insn); + if (avl != last_vconfig.avl) + return false; + + if (get_sew (insn) != last_vconfig.sew) + return false; + + if (get_vlmul (insn) != last_vconfig.vlmul) + return false; + + if (tail_agnostic_p (insn) != last_vconfig.ta) + return false; + + if (mask_agnostic_p (insn) != last_vconfig.ma) + return false; + + /* No differences found, they're trivially compatible. */ + return true; +} + +/* Implement TARGET_SCHED_INIT, we use this to track the vector configuration + of the last issued vector instruction. We can then use that information + to potentially adjust the ready queue to issue instructions of a compatible + vector configuration instead of a conflicting configuration. That will + reduce the number of vsetvl instructions we ultimately emit. */ +static void +riscv_sched_init (FILE *, int, int) +{ + clear_vconfig (); +} + /* Implement TARGET_SCHED_VARIABLE_ISSUE. */ static int riscv_sched_variable_issue (FILE *, int, rtx_insn *insn, int more) @@ -10600,9 +10665,88 @@ riscv_sched_variable_issue (FILE *, int, rtx_insn *insn, int more) an assert so we can find and fix this problem. */ gcc_assert (insn_has_dfa_reservation_p (insn)); + /* If this is a vector insn with vl/vtype info, then record the last + vector configuration. */ + if (vsetvl_insn_p (insn)) + clear_vconfig (); + else if (NONDEBUG_INSN_P (insn) && has_vtype_op (insn)) + { + extract_insn_cached (insn); + + rtx avl = get_avl (insn); + if (avl == RVV_VLMAX) + avl = const0_rtx; + + if (!avl || !CONST_INT_P (avl)) + clear_vconfig (); + else + { + last_vconfig.valid = true; + last_vconfig.avl = avl; + last_vconfig.sew = get_sew (insn); + last_vconfig.vlmul = get_vlmul (insn); + last_vconfig.ta = tail_agnostic_p (insn); + last_vconfig.ma = mask_agnostic_p (insn); + } + } + return more - 1; } +/* Implement TARGET_SCHED_REORDER. The goal here is to look at the ready + queue and reorder it ever so slightly to encourage issing an insn with + the same vector configuration as the most recently issued vector + instruction. That will reduce vsetvl instructions. */ +static int +riscv_sched_reorder (FILE *, int, rtx_insn **ready, int *nreadyp, int) +{ + /* If we don't have a valid prior vector configuration, then there is + no point in reordering the ready queue, similarly if there is + just one entry in the queue. */ + if (!last_vconfig.valid || *nreadyp == 1) + return riscv_issue_rate (); + + return riscv_issue_rate (); + int nready = *nreadyp; + int priority = INSN_PRIORITY (ready[nready - 1]); + for (int i = nready - 1; i >= 0; i--) + { + rtx_insn *insn = ready[i]; + + /* On a high performance core, vsetvl instructions should be + inexpensive. Removing them is very much a secondary concern, so + be extremely conservative with reordering, essentially only + allowing reordering within the highest priority value. + + Lower end cores may benefit from more flexibility here. That + tuning is left to those who understand their core's behavior + and can thoroughly benchmark the result. Assuming such + designs appear, we can probably put an entry in the tuning + structure to indicate how much difference in priority to allow. */ + if (INSN_PRIORITY (insn) < priority) + break; + + if (compatible_with_last_vconfig (insn)) + { + /* This entry is compatible with the last vconfig and has + the same priority as the most important insn. So swap + it so that we keep the vector configuration as-is and + ultimately eliminate a vsetvl. + + Note no need to swap if this is the first entry in the + queue. */ + if (i == nready - 1) + break; + + std::swap (ready[i], ready[nready - 1]); + break; + } + } + + return riscv_issue_rate (); +} + + /* Implement TARGET_SCHED_MACRO_FUSION_P. Return true if target supports instruction fusion of some sort. */ @@ -16011,9 +16155,15 @@ riscv_prefetch_offset_address_p (rtx x, machine_mode mode) #undef TARGET_SCHED_MACRO_FUSION_PAIR_P #define TARGET_SCHED_MACRO_FUSION_PAIR_P riscv_macro_fusion_pair_p +#undef TARGET_SCHED_INIT +#define TARGET_SCHED_INIT riscv_sched_init + #undef TARGET_SCHED_VARIABLE_ISSUE #define TARGET_SCHED_VARIABLE_ISSUE riscv_sched_variable_issue +#undef TARGET_SCHED_REORDER +#define TARGET_SCHED_REORDER riscv_sched_reorder + #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST riscv_sched_adjust_cost diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md index 20e82e6..42171a5 100644 --- a/gcc/config/riscv/thead.md +++ b/gcc/config/riscv/thead.md @@ -34,7 +34,7 @@ (define_insn "*th_srri<mode>3" [(set (match_operand:GPR 0 "register_operand" "=r") (rotatert:GPR (match_operand:GPR 1 "register_operand" "r") - (match_operand 2 "const_int_operand" "n")))] + (match_operand 2 "const_int_operand" "n")))] "TARGET_XTHEADBB && (TARGET_64BIT || <MODE>mode == SImode)" { bool wform = TARGET_64BIT && (<MODE>mode == SImode); @@ -45,6 +45,22 @@ [(set_attr "type" "bitmanip") (set_attr "mode" "<GPR:MODE>")]) +;; Version with explicit sign extension to facilitate sign extension +;; removal. +(define_insn "*th_srrisi3_extended" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI + (rotatert:SI (match_operand:SI 1 "register_operand" "r") + (match_operand 2 "const_int_operand" "n"))))] + "TARGET_XTHEADBB && TARGET_64BIT" + { + operands[2] = GEN_INT (INTVAL (operands[2]) + & (GET_MODE_BITSIZE (SImode) - 1)); + return "th.srriw\t%0,%1,%2"; + } + [(set_attr "type" "bitmanip") + (set_attr "mode" "SI")]) + (define_insn "*th_ext<mode>4" [(set (match_operand:GPR 0 "register_operand" "=r") (sign_extract:GPR (match_operand:GPR 1 "register_operand" "r") diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index 3cb87bf..9d34725 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -1437,6 +1437,8 @@ [(set_attr "type" "vlde,vste,vmov") (set_attr "mode" "<MODE>") (set (attr "merge_op_idx") (const_int INVALID_ATTRIBUTE)) + (set (attr "has_vl_op") (const_string "false")) + (set (attr "has_vtype_op") (const_string "false")) (set (attr "avl_type_idx") (const_int INVALID_ATTRIBUTE)) (set (attr "mode_idx") (const_int INVALID_ATTRIBUTE))] ) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 4ba7f54..c713451 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -43,6 +43,7 @@ UNSPEC_FRAME_BLOCKAGE UNSPEC_CEIL UNSPEC_FLOOR + UNSPEC_ROUND ]) (define_c_enum "unspecv" [ @@ -104,8 +105,11 @@ ;; This iterator and attribute allow FP-to-integer rounding of two types ;; to be generated from one template. -(define_int_iterator ANY_ROUND [UNSPEC_CEIL UNSPEC_FLOOR]) -(define_int_attr m_round [(UNSPEC_CEIL "ceil") (UNSPEC_FLOOR "floor")]) +(define_int_iterator ANY_ROUND [UNSPEC_CEIL UNSPEC_FLOOR UNSPEC_ROUND]) +(define_int_attr m_round [(UNSPEC_CEIL "ceil") (UNSPEC_FLOOR "floor") + (UNSPEC_ROUND "round")]) +(define_int_attr c_round [(UNSPEC_CEIL "1") (UNSPEC_FLOOR "1") + (UNSPEC_ROUND "flag_unsafe_math_optimizations")]) ;; Attributes. @@ -691,13 +695,15 @@ }) (define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "register_operand" "f")))] + [(set (match_operand:SF 0 "register_operand") + (neg:SF (match_operand:SF 1 "register_operand"))) + (clobber (match_scratch:SI 2))] "TARGET_HARD_FLOAT" - "neg.s\t%0, %1" - [(set_attr "type" "farith") - (set_attr "mode" "SF") - (set_attr "length" "3")]) + {@ [cons: =0, 1, =2; attrs: type, length] + [D, D, &a; arith , 7] movi.n\t%2, 1\;slli\t%2, %2, 31\;add.n\t%0, %1, %2 + [f, f, X; farith, 3] neg.s\t%0, %1 + } + [(set_attr "mode" "SF")]) ;; Logical instructions. @@ -1139,7 +1145,7 @@ (define_insn "*fix<s_fix>_truncsfsi2_scaled" [(set (match_operand:SI 0 "register_operand" "=a") (any_fix:SI (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "fix_scaling_operand" "F"))))] + (match_operand:SF 2 "fix_scaling_operand" ""))))] "TARGET_HARD_FLOAT" "<m_fix>.s\t%0, %1, %U2" [(set_attr "type" "fconv") @@ -1158,7 +1164,7 @@ (define_insn "*float<s_float>sisf2_scaled" [(set (match_operand:SF 0 "register_operand" "=f") (mult:SF (any_float:SF (match_operand:SI 1 "register_operand" "a")) - (match_operand:SF 2 "float_scaling_operand" "F")))] + (match_operand:SF 2 "float_scaling_operand" "")))] "TARGET_HARD_FLOAT" "<m_float>.s\t%0, %1, %V2" [(set_attr "type" "fconv") @@ -1168,7 +1174,7 @@ (define_insn "l<m_round>sfsi2" [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(match_operand:SF 1 "register_operand" "f")] ANY_ROUND))] - "TARGET_HARD_FLOAT" + "TARGET_HARD_FLOAT && <c_round>" "<m_round>.s\t%0, %1, 0" [(set_attr "type" "fconv") (set_attr "mode" "SF") @@ -1178,7 +1184,7 @@ [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(plus:SF (match_operand:SF 1 "register_operand" "f") (match_dup 1))] ANY_ROUND))] - "TARGET_HARD_FLOAT" + "TARGET_HARD_FLOAT && <c_round>" "<m_round>.s\t%0, %1, 1" [(set_attr "type" "fconv") (set_attr "mode" "SF") @@ -1187,8 +1193,8 @@ (define_insn "*l<m_round>sfsi2_scaled" [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "fix_scaling_operand" "F"))] ANY_ROUND))] - "TARGET_HARD_FLOAT" + (match_operand:SF 2 "fix_scaling_operand" ""))] ANY_ROUND))] + "TARGET_HARD_FLOAT && <c_round>" "<m_round>.s\t%0, %1, %U2" [(set_attr "type" "fconv") (set_attr "mode" "SF") diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 73c2a03..ddcd552 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2025-11-01 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/122381 + * module.cc (trees_out::core_vals): Write BASELINK_OPTYPE (aka + TREE_CHAIN). + (trees_in::core_vals): Read it. + 2025-10-30 Jakub Jelinek <jakub@redhat.com> * std-name-hint.gperf: Remove duplicate entries for ispanstream diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 81357a8..e0b9efa 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -6733,6 +6733,7 @@ trees_out::core_vals (tree t) WT (((lang_tree_node *)t)->baselink.binfo); WT (((lang_tree_node *)t)->baselink.functions); WT (((lang_tree_node *)t)->baselink.access_binfo); + WT (((lang_tree_node *)t)->baselink.common.chain); break; case CONSTRAINT_INFO: @@ -7302,6 +7303,7 @@ trees_in::core_vals (tree t) RT (((lang_tree_node *)t)->baselink.binfo); RTU (((lang_tree_node *)t)->baselink.functions); RT (((lang_tree_node *)t)->baselink.access_binfo); + RT (((lang_tree_node *)t)->baselink.common.chain); break; case CONSTRAINT_INFO: @@ -13046,12 +13048,11 @@ trees_in::read_var_def (tree decl, tree maybe_template) if (DECL_EXPLICIT_INSTANTIATION (decl) && !DECL_EXTERNAL (decl)) setup_explicit_instantiation_definition_linkage (decl); - if (DECL_IMPLICIT_INSTANTIATION (decl) - || (DECL_EXPLICIT_INSTANTIATION (decl) - && !DECL_EXTERNAL (decl)) - || (DECL_CLASS_SCOPE_P (decl) - && !DECL_VTABLE_OR_VTT_P (decl) - && !DECL_TEMPLATE_INFO (decl))) + /* Class static data members are handled in read_class_def. */ + if (!DECL_CLASS_SCOPE_P (decl) + && (DECL_IMPLICIT_INSTANTIATION (decl) + || (DECL_EXPLICIT_INSTANTIATION (decl) + && !DECL_EXTERNAL (decl)))) note_vague_linkage_variable (decl); } if (!dyn_init) @@ -13465,6 +13466,10 @@ trees_in::read_class_def (tree defn, tree maybe_template) DECL_ACCESS (d) = tree_cons (type, access, list); } } + + if (TREE_CODE (decl) == VAR_DECL + && TREE_CODE (maybe_template) != TEMPLATE_DECL) + note_vague_linkage_variable (decl); } } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 8aaedae..30eae4b 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1131,6 +1131,14 @@ such an initializer, as shown here: char **foo = (char *[]) @{ "x", "y", "z" @}; @end smallexample +As a GNU extension, GCC allows compound literals with a variable size. +In this case, only empty initialization is allowed. + +@smallexample +int n = 4; +char (*p)[n] = &(char[n])@{ @}; +@end smallexample + Compound literals for scalar types and union types are also allowed. In the following example the variable @code{i} is initialized to the value @code{2}, the result of incrementing the unnamed object created by diff --git a/gcc/doc/tree-ssa.texi b/gcc/doc/tree-ssa.texi index dc6a111..25aa006 100644 --- a/gcc/doc/tree-ssa.texi +++ b/gcc/doc/tree-ssa.texi @@ -355,7 +355,7 @@ FOR_EACH_PHI_OR_STMT_DEF (def_operand_p, phi, iter, flags) Immediate use information is now always available. Using the immediate use iterators, you may examine every use of any @code{SSA_NAME}. For instance, -to change each use of @code{ssa_var} to @code{ssa_var2} and call fold_stmt on +to change each use of @code{ssa_var} to @code{val} and call fold_stmt on each stmt after that is done: @smallexample @@ -367,8 +367,9 @@ each stmt after that is done: FOR_EACH_IMM_USE_STMT (stmt, iterator, ssa_var) @{ FOR_EACH_IMM_USE_ON_STMT (imm_use_p, iterator) - SET_USE (imm_use_p, ssa_var_2); + SET_USE (imm_use_p, val); fold_stmt (stmt); + update_stmt (stmt); @} @end smallexample @@ -389,9 +390,7 @@ terminated early; a destructor takes care of that when leaving the @code{FOR_EACH_IMM_USE_STMT} scope. There are checks in @code{verify_ssa} which verify that the immediate use list -is up to date, as well as checking that an optimization didn't break from the -loop without using this macro. It is safe to simply 'break'; from a -@code{FOR_EACH_IMM_USE_FAST} traverse. +is up to date. Some useful functions and macros: @enumerate @@ -412,7 +411,9 @@ isn't located in a @code{PHI} node. @end enumerate Note that uses are not put into an immediate use list until their statement is -actually inserted into the instruction stream via a @code{bsi_*} routine. +actually inserted into the instruction stream via a @code{gsi_*} routine +which calls @code{update_stmt} to re-scan SSA operands and update the +immediate use lists. It is also still possible to utilize lazy updating of statements, but this should be used only when absolutely required. Both alias analysis and the diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 0d937eb..5501bca 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2025-11-01 Harald Anlauf <anlauf@gmx.de> + + PR fortran/78640 + * resolve.cc (resolve_fl_procedure): Check function result of a + pure function against F2018:C1585. + 2025-10-31 Yuao Ma <c8ef@outlook.com> * intrinsic.texi: Fix typo. diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index ecd2ada..03e26f0 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -15385,6 +15385,39 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag) return false; } + /* F2018:C1585: "The function result of a pure function shall not be both + polymorphic and allocatable, or have a polymorphic allocatable ultimate + component." */ + if (sym->attr.pure && sym->result && sym->ts.u.derived) + { + if (sym->ts.type == BT_CLASS + && sym->attr.class_ok + && CLASS_DATA (sym->result) + && CLASS_DATA (sym->result)->attr.allocatable) + { + gfc_error ("Result variable %qs of pure function at %L is " + "polymorphic allocatable", + sym->result->name, &sym->result->declared_at); + return false; + } + + if (sym->ts.type == BT_DERIVED && sym->ts.u.derived->components) + { + gfc_component *c = sym->ts.u.derived->components; + for (; c; c = c->next) + if (c->ts.type == BT_CLASS + && CLASS_DATA (c) + && CLASS_DATA (c)->attr.allocatable) + { + gfc_error ("Result variable %qs of pure function at %L has " + "polymorphic allocatable component %qs", + sym->result->name, &sym->result->declared_at, + c->name); + return false; + } + } + } + if (sym->attr.is_bind_c && sym->attr.is_c_interop != 1) { gfc_formal_arglist *curr_arg; diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 48ce7578..1bbf21f 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -523,6 +523,11 @@ update_equiv (int regno) { rtx x; + /* If REGNO is beyond the length of the equivalence array structure, + then there's nothing to update. */ + if (regno >= ira_reg_equiv_len) + return; + if ((x = ira_reg_equiv[regno].memory) != NULL_RTX) ira_reg_equiv[regno].memory = simplify_replace_fn_rtx (x, NULL_RTX, loc_equivalence_callback, diff --git a/gcc/m2/gm2-compiler/M2StackSpell.mod b/gcc/m2/gm2-compiler/M2StackSpell.mod index ac58c1c..06ce923 100644 --- a/gcc/m2/gm2-compiler/M2StackSpell.mod +++ b/gcc/m2/gm2-compiler/M2StackSpell.mod @@ -23,8 +23,10 @@ IMPLEMENTATION MODULE M2StackSpell ; FROM SymbolTable IMPORT NulSym, IsModule, IsDefImp, IsRecord, IsEnumeration, IsProcedure, GetNth, - GetSymName, GetSym, GetLocalSym, - UnknownReported, + GetSymName, GetSym, GetLocalSym, GetScope, + UnknownReported, IsUnknown, + GetUnknownOnImport, GetUnknownDeclScope, + ForeachExportedDo, ForeachProcedureDo, ForeachLocalSymDo, ForeachFieldEnumerationDo ; @@ -179,8 +181,9 @@ VAR PushCount : CARDINAL ; PushCandidate: Candidates ; + (* - PushName - + PushName - push a name to the candidate vec. *) PROCEDURE PushName (sym: CARDINAL) ; @@ -279,7 +282,7 @@ BEGIN cand := m2spellcheck.InitCandidates () ; IF PushCandidates (cand, sym) > 1 THEN - content := m2spellcheck.FindClosestCharStar (cand, string (misspelt)) ; + content := m2spellcheck.FindClosestCharStar (cand, string (misspelt)) ELSE content := NIL END ; @@ -310,6 +313,52 @@ END AddPunctuation ; *) PROCEDURE GetSpellHint (unknown: CARDINAL) : String ; +BEGIN + IF IsUnknown (unknown) AND + GetUnknownOnImport (unknown) AND + (GetUnknownDeclScope (unknown) # GetScope (unknown)) + THEN + (* It was created during an import statement. *) + RETURN GetExportedSpellHint (unknown, GetUnknownDeclScope (unknown)) + END ; + RETURN GetScopeSpellHint (unknown) +END GetSpellHint ; + + +(* + GetExportedSpellHint - return a string describing a spelling hint + using the module exported identifiers. +*) + +PROCEDURE GetExportedSpellHint (unknown, module: CARDINAL) : String ; +VAR + content : ConstCharStar ; + misspell, + HintStr : String ; +BEGIN + misspell := InitStringCharStar (KeyToCharStar (GetSymName (unknown))) ; + HintStr := NIL ; + PushCount := 0 ; + PushCandidate := m2spellcheck.InitCandidates () ; + ForeachExportedDo (module, PushName) ; + ForeachLocalSymDo (module, PushName) ; + IF PushCount > 0 + THEN + content := m2spellcheck.FindClosestCharStar (PushCandidate, + string (misspell)) ; + HintStr := BuildHintStr (HintStr, content) + END ; + m2spellcheck.KillCandidates (PushCandidate) ; + RETURN AddPunctuation (HintStr, '?') +END GetExportedSpellHint ; + + +(* + GetScopeSpellHint - return a string describing a spelling hint + using the visible scopes. +*) + +PROCEDURE GetScopeSpellHint (unknown: CARDINAL) : String ; VAR i, n : CARDINAL ; sym : CARDINAL ; @@ -331,7 +380,7 @@ BEGIN INC (i) END ; RETURN AddPunctuation (HintStr, '?') -END GetSpellHint ; +END GetScopeSpellHint ; (* diff --git a/gcc/m2/gm2-compiler/P1Build.bnf b/gcc/m2/gm2-compiler/P1Build.bnf index 4cbdf17..d56a286 100644 --- a/gcc/m2/gm2-compiler/P1Build.bnf +++ b/gcc/m2/gm2-compiler/P1Build.bnf @@ -358,9 +358,12 @@ END Ident ; *) PROCEDURE IdentScope (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ; +VAR + tokpos: CARDINAL ; BEGIN - Ident(stopset0, stopset1, stopset2) ; - AddNameToScope(LastIdent) + tokpos := GetTokenNo () ; + Ident (stopset0, stopset1, stopset2) ; + AddNameToScope (tokpos, LastIdent) END IdentScope ; @@ -374,14 +377,14 @@ PROCEDURE PossiblyExportIdent (stopset0: SetOfStop0; stopset1: SetOfStop1; stops VAR nothing: CARDINAL ; BEGIN - AddNameToScope(makekey(currentstring)) ; - PushTFtok(makekey(currentstring), identtok, GetTokenNo()) ; + AddNameToScope (GetTokenNo (), makekey (currentstring)) ; + PushTFtok (makekey (currentstring), identtok, GetTokenNo ()) ; CheckExplicitExported ; - IF NOT IsAutoPushOn() + IF NOT IsAutoPushOn () THEN - PopT(nothing) + PopT (nothing) END ; - Expect(identtok, stopset0, stopset1, stopset2) + Expect (identtok, stopset0, stopset1, stopset2) END PossiblyExportIdent ; diff --git a/gcc/m2/gm2-compiler/P1SymBuild.mod b/gcc/m2/gm2-compiler/P1SymBuild.mod index d6c0f2f..33d12bd 100644 --- a/gcc/m2/gm2-compiler/P1SymBuild.mod +++ b/gcc/m2/gm2-compiler/P1SymBuild.mod @@ -39,6 +39,7 @@ FROM M2Reserved IMPORT ImportTok, ExportTok, QualifiedTok, UnQualifiedTok, FROM FifoQueue IMPORT PutEnumerationIntoFifoQueue ; FROM P0SymBuild IMPORT EnterBlock, LeaveBlock ; +FROM libc IMPORT printf ; FROM SymbolTable IMPORT NulSym, ModeOfAddr, @@ -472,9 +473,6 @@ BEGIN OperandT(n+1)) ; i := 1 ; WHILE i<=n DO -(* - WriteString('Importing ') ; WriteKey(Operand(j)) ; WriteString(' from ') ; WriteKey(GetSymName(ModSym)) ; WriteLn ; -*) Sym := GetExported (OperandTok (n+1-i), ModSym, OperandT (n+1-i)) ; PutImported (Sym) ; @@ -619,7 +617,7 @@ BEGIN (* Ident List contains list of objects *) i := 1 ; WHILE i<=n DO - AddNameToImportList (OperandT (i)) ; + AddNameToImportList (OperandTok (i), OperandT (i)) ; INC (i) END ELSE diff --git a/gcc/m2/gm2-compiler/SymbolTable.def b/gcc/m2/gm2-compiler/SymbolTable.def index 09a5590..2a2f201 100644 --- a/gcc/m2/gm2-compiler/SymbolTable.def +++ b/gcc/m2/gm2-compiler/SymbolTable.def @@ -2136,6 +2136,20 @@ PROCEDURE UnknownReported (sym: CARDINAL) ; (* + GetUnknownOnImport - returns the onimport field of unknown sym. +*) + +PROCEDURE GetUnknownOnImport (sym: CARDINAL) : BOOLEAN ; + + +(* + GetUnknownDeclScope - returns the decl scope of unknown sym. +*) + +PROCEDURE GetUnknownDeclScope (sym: CARDINAL) : CARDINAL ; + + +(* IsReallyPointer - returns TRUE is sym is a pointer, address or a type declared as a pointer or address. *) @@ -2613,7 +2627,7 @@ PROCEDURE ResolveConstructorTypes ; current scope. *) -PROCEDURE AddNameToScope (n: Name) ; +PROCEDURE AddNameToScope (tok: CARDINAL; n: Name) ; (* @@ -2621,7 +2635,7 @@ PROCEDURE AddNameToScope (n: Name) ; module. *) -PROCEDURE AddNameToImportList (n: Name) ; +PROCEDURE AddNameToImportList (tok: CARDINAL; n: Name) ; (* diff --git a/gcc/m2/gm2-compiler/SymbolTable.mod b/gcc/m2/gm2-compiler/SymbolTable.mod index 023bd49..25170fb 100644 --- a/gcc/m2/gm2-compiler/SymbolTable.mod +++ b/gcc/m2/gm2-compiler/SymbolTable.mod @@ -230,6 +230,10 @@ TYPE SymUndefined = RECORD name : Name ; (* Index into name array, name *) (* of record. *) + declScope : CARDINAL ; (* Scope where unknown is *) + (* created. *) + onImport : BOOLEAN ; (* Was it created during an *) + (* import? *) oafamily : CARDINAL ; (* The oafamily for this sym *) errorScope: ErrorScope ; (* Title scope used if an *) (* error is emitted. *) @@ -1591,7 +1595,7 @@ END IsError ; MakeObject - creates an object node. *) -PROCEDURE MakeObject (name: Name) : CARDINAL ; +PROCEDURE MakeObject (tok: CARDINAL; name: Name) : CARDINAL ; VAR pSym: PtrToSymbol ; Sym : CARDINAL ; @@ -1601,8 +1605,8 @@ BEGIN WITH pSym^ DO SymbolType := ObjectSym ; Object.name := name ; - InitWhereDeclared(Object.At) ; - InitWhereFirstUsed(Object.At) + InitWhereDeclaredTok (tok, Object.At) ; + InitWhereFirstUsedTok (tok, Object.At) END ; RETURN( Sym ) END MakeObject ; @@ -8647,7 +8651,7 @@ BEGIN THEN (* Make unknown *) NewSym (Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ; (* Add to unknown tree *) AddSymToUnknownTree (ScopePtr, SymName, Sym) (* @@ -8684,7 +8688,7 @@ BEGIN THEN (* Make unknown. *) NewSym (Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ; (* Add to unknown tree *) AddSymToUnknownTree (ScopePtr, SymName, Sym) (* @@ -9252,7 +9256,7 @@ BEGIN IF Sym=NulSym THEN NewSym (Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, ModSym, TRUE) ; PutSymKey (Unresolved, SymName, Sym) END END @@ -9283,7 +9287,7 @@ BEGIN IF Sym=NulSym THEN NewSym(Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, ModSym, TRUE) ; PutSymKey (Unresolved, SymName, Sym) END END @@ -9310,7 +9314,7 @@ BEGIN IF Sym=NulSym THEN NewSym(Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, scope, TRUE) ; PutSymKey(Unresolved, SymName, Sym) END END | @@ -9319,7 +9323,7 @@ BEGIN IF Sym=NulSym THEN NewSym(Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, scope, TRUE) ; PutSymKey(Unresolved, SymName, Sym) END END | @@ -9328,7 +9332,7 @@ BEGIN IF Sym=NulSym THEN NewSym(Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ; PutSymKey(Unresolved, SymName, Sym) END END @@ -9599,7 +9603,8 @@ BEGIN CheckForUnknowns (tokno, name, ExportUnQualifiedTree, 'EXPORT UNQUALIFIED') ; CheckForSymbols (ExportRequest, - 'requested by another modules import (symbols have not been exported by the appropriate definition module)') ; + 'requested by another module import' + + ' and the symbol has not been exported by the appropriate definition module') ; CheckForUnknowns (tokno, name, Unresolved, 'unresolved') ; CheckForUnknowns (tokno, name, LocalSymbols, 'locally used') END | @@ -9752,12 +9757,12 @@ PROCEDURE CheckForSymbols (Tree: SymbolTree; a: ARRAY OF CHAR) ; VAR s: String ; BEGIN - IF NOT IsEmptyTree(Tree) + IF DoesTreeContainAny (Tree, IsUnreportedUnknown) THEN s := InitString ("the symbols are unknown at the end of module {%1Ea} when ") ; s := ConCat (s, Mark(InitString(a))) ; MetaErrorString1 (s, MainModule) ; - ForeachNodeDo(Tree, SymbolError) + ForeachNodeDo (Tree, SymbolError) END END CheckForSymbols ; @@ -11708,10 +11713,11 @@ END IsProcedureAnyNoReturn ; (* - FillInUnknownFields - + FillInUnknownFields - fills in all fields for the undefined sym. *) -PROCEDURE FillInUnknownFields (tok: CARDINAL; sym: CARDINAL; SymName: Name) ; +PROCEDURE FillInUnknownFields (tok: CARDINAL; sym: CARDINAL; SymName: Name; + descscope: CARDINAL; onimport: BOOLEAN) ; VAR pSym: PtrToSymbol ; BEGIN @@ -11722,6 +11728,8 @@ BEGIN name := SymName ; oafamily := NulSym ; errorScope := GetCurrentErrorScope () ; + declScope := descscope ; + onImport := onimport ; InitWhereFirstUsedTok (tok, At) END END @@ -11729,6 +11737,34 @@ END FillInUnknownFields ; (* + GetUnknownOnImport - returns the onimport field of unknown sym. +*) + +PROCEDURE GetUnknownOnImport (sym: CARDINAL) : BOOLEAN ; +VAR + pSym: PtrToSymbol ; +BEGIN + Assert (IsUnknown (sym)) ; + pSym := GetPsym (sym) ; + RETURN pSym^.Undefined.onImport +END GetUnknownOnImport ; + + +(* + GetUnknownDeclScope - returns the decl scope of unknown sym. +*) + +PROCEDURE GetUnknownDeclScope (sym: CARDINAL) : CARDINAL ; +VAR + pSym: PtrToSymbol ; +BEGIN + Assert (IsUnknown (sym)) ; + pSym := GetPsym (sym) ; + RETURN pSym^.Undefined.declScope +END GetUnknownDeclScope ; + + +(* FillInPointerFields - given a new symbol, sym, make it a pointer symbol and initialize its fields. *) @@ -12985,7 +13021,7 @@ END AddNameTo ; current scope. *) -PROCEDURE AddNameToScope (n: Name) ; +PROCEDURE AddNameToScope (tok: CARDINAL; n: Name) ; VAR pSym : PtrToSymbol ; scope: CARDINAL ; @@ -12995,9 +13031,9 @@ BEGIN WITH pSym^ DO CASE SymbolType OF - ProcedureSym: AddNameTo(Procedure.NamedObjects, MakeObject(n)) | - ModuleSym : AddNameTo(Module.NamedObjects, MakeObject(n)) | - DefImpSym : AddNameTo(DefImp.NamedObjects, MakeObject(n)) + ProcedureSym: AddNameTo(Procedure.NamedObjects, MakeObject (tok, n)) | + ModuleSym : AddNameTo(Module.NamedObjects, MakeObject (tok, n)) | + DefImpSym : AddNameTo(DefImp.NamedObjects, MakeObject (tok, n)) ELSE InternalError ('expecting - DefImp') @@ -13011,7 +13047,7 @@ END AddNameToScope ; module. *) -PROCEDURE AddNameToImportList (n: Name) ; +PROCEDURE AddNameToImportList (tok: CARDINAL; n: Name) ; VAR pSym : PtrToSymbol ; scope: CARDINAL ; @@ -13021,8 +13057,8 @@ BEGIN WITH pSym^ DO CASE SymbolType OF - ModuleSym: AddNameTo(Module.NamedImports, MakeObject(n)) | - DefImpSym: AddNameTo(DefImp.NamedImports, MakeObject(n)) + ModuleSym: AddNameTo (Module.NamedImports, MakeObject (tok, n)) | + DefImpSym: AddNameTo (DefImp.NamedImports, MakeObject (tok, n)) ELSE InternalError ('expecting - DefImp or Module symbol') diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index c4de035..b9591eb 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -3673,6 +3673,63 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, && GET_MODE_CLASS (mode) != MODE_CC) return CONSTM1_RTX (mode); + /* IOR of two single bit bitfields extracted from the same object. + Bitfields are represented as an AND based extraction */ + if (GET_CODE (op0) == AND + && GET_CODE (op1) == AND + /* Verify both AND operands are logical right shifts. */ + && GET_CODE (XEXP (op0, 0)) == LSHIFTRT + && GET_CODE (XEXP (op1, 0)) == LSHIFTRT + /* Verify both bitfields are extracted from the same object. */ + && XEXP (XEXP (op0, 0), 0) == XEXP (XEXP (op1, 0), 0) + /* Verify both fields are a single bit (could be generalized). */ + && XEXP (op0, 1) == CONST1_RTX (mode) + && XEXP (op1, 1) == CONST1_RTX (mode) + /* Verify bit positions (for cases with variable bit position). */ + && CONST_INT_P (XEXP (op0, 1)) + && CONST_INT_P (XEXP (op1, 1))) + { + unsigned HOST_WIDE_INT bitpos1 = INTVAL (XEXP (XEXP (op0, 0), 1)); + unsigned HOST_WIDE_INT bitpos2 = INTVAL (XEXP (XEXP (op1, 0), 1)); + unsigned HOST_WIDE_INT mask + = (HOST_WIDE_INT_1U << bitpos1) | (HOST_WIDE_INT_1U << bitpos2); + + rtx m = GEN_INT (mask); + rtx t = gen_rtx_AND (mode, XEXP (XEXP (op0, 0), 0), m); + t = gen_rtx_NE (mode, t, CONST0_RTX (mode)); + return t; + } + + /* IOR of multiple single bit bitfields extracted from the same object + (building on previous case). + First bitfield is represented as an AND based extraction, as done + above. Second represented as NE based extraction, from + output above. */ + if (GET_CODE (op0) == AND + && GET_CODE (op1) == NE + /* Verify AND operand is logical right shift. */ + && GET_CODE (XEXP (op0, 0)) == LSHIFTRT + /* Verify NE operand is an AND (based on output above). */ + && GET_CODE (XEXP (op1, 0)) == AND + /* Verify both bitfields are extracted from the same object. */ + && XEXP (XEXP (op0, 0), 0) == XEXP (XEXP (op1, 0), 0) + /* Verify masking is with a single bit and that we have a NE 0 + comparison for the other operand. */ + && XEXP (op0, 1) == CONST1_RTX (mode) + && XEXP (op1, 1) == CONST0_RTX (mode) + /* Verify bit position. */ + && CONST_INT_P (XEXP (op0, 1))) + { + unsigned HOST_WIDE_INT bitpos1 = INTVAL (XEXP (XEXP (op0, 0), 1)); + unsigned HOST_WIDE_INT mask + = (HOST_WIDE_INT_1U << bitpos1) | INTVAL (XEXP (XEXP (op1, 0), 1)); + + rtx m = GEN_INT (mask); + rtx t = gen_rtx_AND (mode, XEXP (XEXP (op0, 0), 0), m); + t = gen_rtx_NE (mode, t, CONST0_RTX (mode)); + return t; + } + /* Convert (ior (plus (A - 1)) (neg A)) to -1. */ if (match_plus_neg_pattern (op0, op1, mode)) return CONSTM1_RTX (mode); diff --git a/gcc/ssa-iterators.h b/gcc/ssa-iterators.h index 03d701c..0822a98 100644 --- a/gcc/ssa-iterators.h +++ b/gcc/ssa-iterators.h @@ -36,25 +36,17 @@ along with GCC; see the file COPYING3. If not see base for a circular list, and initially this is the only node in the list. - Fast iteration allows each use to be examined, but does not allow - any modifications to the uses or stmts. - - Normal iteration allows insertion, deletion, and modification. the - iterator manages this by inserting a marker node into the list - immediately before the node currently being examined in the list. - this marker node is uniquely identified by having null stmt *and* a - null use pointer. - - When iterating to the next use, the iteration routines check to see - if the node after the marker has changed. if it has, then the node - following the marker is now the next one to be visited. if not, the - marker node is moved past that node in the list (visualize it as - bumping the marker node through the list). this continues until - the marker node is moved to the original anchor position. the - marker node is then removed from the list. - - If iteration is halted early, the marker node must be removed from - the list before continuing. */ + Fast iteration via FOR_EACH_IMM_USE_FAST allows each use to be + examined, but does not allow any modifications to the uses or stmts. + + Safe iteration via FOR_EACH_IMM_USE_STMT and FOR_EACH_IMM_USE_ON_STMT + allows insertion, deletion, and modification of SSA operands within + the current stmt iterated. The iterator manages this by re-sorting + the immediate uses to batch uses on a single stmt after each other + and inserts a marker node into the list immediately after the node + ending the current batch. This marker node is uniquely identified by + having null stmt *and* a null use pointer. */ + struct imm_use_iterator { /* This is the current use the iterator is processing. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 013121d..91ec37f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,43 @@ +2025-11-01 Shreya Munnangi <smunnangi1@ventanamicro.com> + + PR target/67731 + * gcc.target/riscv/pr67731.c: New test. + * gcc.target/sh/pr67731.c: New test. + +2025-11-01 Jeff Law <jlaw@ventanamicro.com> + + PR rtl-optimization/122321 + * gcc.target/riscv/rvv/autovec/pr122321.c: New test. + +2025-11-01 Harald Anlauf <anlauf@gmx.de> + + PR fortran/78640 + * gfortran.dg/pure_result.f90: New test. + +2025-11-01 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/122381 + * g++.dg/modules/convop-2_a.H: New test. + * g++.dg/modules/convop-2_b.C: New test. + +2025-11-01 Martin Uecker <uecker@tugraz.at> + + * gcc.dg/gnu-compoundlit-1.c: New test. + * gcc.dg/gnu-compoundlit-2.c: New test. + * gcc.dg/pr68090.c: Adapt. + * gcc.dg/vla-init-4.c: Adapt. + * gcc.dg/vla-init-5.c: Adapt. + +2025-11-01 Martin Uecker <uecker@tugraz.at> + + PR c/97986 + * gcc.dg/pr97986-1.c: New test. + * gcc.dg/pr97986-2.c: New test. + +2025-11-01 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + * gcc.dg/fold-vecperm-1.c: Test at forwprop3. + 2025-10-31 Tamar Christina <tamar.christina@arm.com> PR target/121853 diff --git a/gcc/testsuite/g++.dg/modules/convop-2_a.H b/gcc/testsuite/g++.dg/modules/convop-2_a.H new file mode 100644 index 0000000..62bb210 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/convop-2_a.H @@ -0,0 +1,10 @@ +// PR c++/122381 +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +template <typename T> struct color_ref { + operator int() const { return 0; } + int foo(color_ref x) { + return x.operator int(); + } +}; diff --git a/gcc/testsuite/g++.dg/modules/convop-2_b.C b/gcc/testsuite/g++.dg/modules/convop-2_b.C new file mode 100644 index 0000000..d1e829e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/convop-2_b.C @@ -0,0 +1,5 @@ +// PR c++/122381 +// { dg-additional-options "-fmodules" } + +import "convop-2_a.H"; +template struct color_ref<int>; diff --git a/gcc/testsuite/g++.dg/modules/inst-6_a.C b/gcc/testsuite/g++.dg/modules/inst-6_a.C new file mode 100644 index 0000000..7f35cc1 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/inst-6_a.C @@ -0,0 +1,14 @@ +// PR c++/122421 +// { dg-additional-options "-fmodules" } +// { dg-module-cmi M } + +export module M; + +export template <typename T> struct Type { + static const int arr[3]; +}; + +extern template const int Type<double>::arr[3]; +template <typename T> const int Type<T>::arr[] = { 42, 43, 44 }; + +export Type<int> ti; diff --git a/gcc/testsuite/g++.dg/modules/inst-6_b.C b/gcc/testsuite/g++.dg/modules/inst-6_b.C new file mode 100644 index 0000000..5a8092c --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/inst-6_b.C @@ -0,0 +1,12 @@ +// PR c++/122421 +// { dg-additional-options "-fmodules" } + +import M; + +int main() { + const int& a = Type<int>::arr[0]; + const int& b = Type<double>::arr[0]; +} + +// { dg-final { scan-assembler {_ZNW1M4TypeIiE3arrE:} } } +// { dg-final { scan-assembler-not {_ZNW1M4TypeIdE3arrE:} } } diff --git a/gcc/testsuite/gcc.dg/fold-vecperm-1.c b/gcc/testsuite/gcc.dg/fold-vecperm-1.c index 5d4456b..878d392 100644 --- a/gcc/testsuite/gcc.dg/fold-vecperm-1.c +++ b/gcc/testsuite/gcc.dg/fold-vecperm-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-forwprop3" } */ typedef int v4si __attribute__((vector_size(16))); typedef short v8hi __attribute__((vector_size(16))); @@ -20,4 +20,4 @@ int128 concat (int128 a, int128 b) { return res; } -/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "forwprop3" } } */ diff --git a/gcc/testsuite/gcc.dg/gnu-compoundlit-1.c b/gcc/testsuite/gcc.dg/gnu-compoundlit-1.c new file mode 100644 index 0000000..a7f3496 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu-compoundlit-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-std=gnu23" } */ + +int g(int n, int (*p)[n]); +int f(int n) +{ + return g(n, &(int[n]){ }); +} + +void h(int n) +{ + (int[n]){ 1 }; /* { dg-error "empty initializer" } */ +} + +void i(int n) +{ + (static int[3]){ }; + (static int[n]){ }; /* { dg-error "storage size" } */ + (constexpr int[3]){ }; + (constexpr int[n]){ }; /* { dg-error "storage size" } */ + (register int[3]){ }; /* { dg-error "register" } */ + (register int[n]){ }; /* { dg-error "register" } */ + (_Thread_local int[3]){ }; /* { dg-error "_Thread_local" } */ + (_Thread_local int[n]){ }; /* { dg-error "_Thread_local" } */ +} + diff --git a/gcc/testsuite/gcc.dg/gnu-compoundlit-2.c b/gcc/testsuite/gcc.dg/gnu-compoundlit-2.c new file mode 100644 index 0000000..dcc5775 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu-compoundlit-2.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu23 -Wall" } */ + +[[gnu::noinline,gnu::noipa]] +static bool f(int n) +{ + struct foo { char a[n]; }; + struct foo x = { }; + + return 0 == __builtin_memcmp(&x, &(struct foo){ }, sizeof x); +} + +int main() +{ + if (!f(7)) + __builtin_abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/pr68090.c b/gcc/testsuite/gcc.dg/pr68090.c index 87b3b93..84e0ca4 100644 --- a/gcc/testsuite/gcc.dg/pr68090.c +++ b/gcc/testsuite/gcc.dg/pr68090.c @@ -1,13 +1,18 @@ /* PR c/68090 */ /* { dg-do compile } */ -/* { dg-options "" } */ +/* { dg-options "--pedantic-error" } */ void fn (int i) { (int[(0, 1)]) { 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ (int[i]) { 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ (int[(0, i)]) { 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ (int [][i]){ 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ (int [][(1, 2)]){ 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ } diff --git a/gcc/testsuite/gcc.dg/pr97986-1.c b/gcc/testsuite/gcc.dg/pr97986-1.c new file mode 100644 index 0000000..87ee3d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97986-1.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu23" } */ + +#include <stdarg.h> + +int f(int n, ...) +{ + __label__ b, d; + va_list ap; + va_start(ap, n); + _Static_assert(5 == sizeof(va_arg(ap, char[5]))); /* { dg-warning "array type" } */ + void g(void) { n++; goto b; } + int *a = va_arg((g(), ap), int[n]); /* { dg-warning "array type" } */ +b: + void h(void) { n++; goto d; } + typeof(va_arg(ap, int[(h(), n)])) c; /* { dg-warning "array type" } */ +d: + return n; +} + +int main() +{ + if (9 != f(7)) + __builtin_abort(); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/pr97986-2.c b/gcc/testsuite/gcc.dg/pr97986-2.c new file mode 100644 index 0000000..fc23a57 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97986-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c90" } */ + +#include <stdarg.h> + + +int f(int n, ...) +{ + va_list ap; + va_start(ap, n); + _Static_assert(5 == sizeof(va_arg(ap, char[5]))); + va_arg(ap, int[n]); /* { dg-error "array type" } */ + int * a = va_arg(ap, int[3]); /* { dg-error "invalid use of non-lvalue array" } */ +} + diff --git a/gcc/testsuite/gcc.dg/vla-init-4.c b/gcc/testsuite/gcc.dg/vla-init-4.c index 06351d0..7d1aa5b 100644 --- a/gcc/testsuite/gcc.dg/vla-init-4.c +++ b/gcc/testsuite/gcc.dg/vla-init-4.c @@ -4,4 +4,4 @@ /* { dg-options "" } */ const int i = 1; -void foo() { char *p = (char [i]){ "" }; } /* { dg-error "compound literal has variable size" } */ +void foo() { char *p = (char [i]){ "" }; } /* { dg-error "variable-sized object" } */ diff --git a/gcc/testsuite/gcc.dg/vla-init-5.c b/gcc/testsuite/gcc.dg/vla-init-5.c index aa9f491..2c249ec 100644 --- a/gcc/testsuite/gcc.dg/vla-init-5.c +++ b/gcc/testsuite/gcc.dg/vla-init-5.c @@ -4,4 +4,4 @@ /* { dg-options "" } */ const int i = 1; -void foo() { void *p = (char [][i]){ "" }; } /* { dg-error "compound literal has variable size" } */ +void foo() { void *p = (char [][i]){ "" }; } /* { dg-error "variable-sized object" } */ diff --git a/gcc/testsuite/gcc.target/avr/torture/pr84211-fuse-move-1.c b/gcc/testsuite/gcc.target/avr/torture/pr84211-fuse-move-1.c index 82ce227..4924e9d 100644 --- a/gcc/testsuite/gcc.target/avr/torture/pr84211-fuse-move-1.c +++ b/gcc/testsuite/gcc.target/avr/torture/pr84211-fuse-move-1.c @@ -1,5 +1,6 @@ /* { dg-do run } */ -/* { dg-additional-options -std=gnu99 } */ +/* Disable LTO since it has problems with flobal asm. */ +/* { dg-additional-options { -std=gnu99 -fno-lto } } */ #define USE_VALUE 0 diff --git a/gcc/testsuite/gcc.target/i386/pr122518.c b/gcc/testsuite/gcc.target/i386/pr122518.c new file mode 100644 index 0000000..2791889 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr122518.c @@ -0,0 +1,15 @@ +/* PR target/122518 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +inline unsigned min (unsigned a, unsigned b) +{ + return (a < b) ? a : b; +} + +unsigned uminsub (unsigned a, unsigned b) +{ + return min (a - b, a); +} + +/* { dg-final { scan-assembler-not "cmp" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/pr67731.c b/gcc/testsuite/gcc.target/riscv/pr67731.c new file mode 100644 index 0000000..6f254fc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr67731.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gcbv -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-O2 -march=rv32gcbv -mabi=ilp32" { target { rv32 } } } */ + +typedef struct +{ + _Bool a : 1; + _Bool b : 1; + _Bool c : 1; + _Bool d : 1; + unsigned int e : 4; +} S; + +_Bool test_00 (S* s) +{ + return s->b | s->c; +} + +_Bool test_01 (S* s) +{ + return s->b | s->c | s->d; +} +/* { dg-final { scan-assembler-times {\tlw\ta0,0\(a0\).*?\n\tandi\ta0,a0,\d+.*?\n\tsnez\ta0,a0.*?\n\tret} 2 } } */ +/* { dg-final { scan-assembler-not {\tor} } } */ +/* { dg-final { scan-assembler-not {\tbexti} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122321.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122321.c new file mode 100644 index 0000000..0e34bc1f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122321.c @@ -0,0 +1,150 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -w -O0" { target rv64 } } */ +/* { dg-options "-march=rv32gcv -mabi=ilp32 -w -O0" { target rv32 } } */ + + +typedef int a; +typedef signed char b; +typedef char c; +typedef short d; +typedef unsigned short e; +typedef a f; +typedef unsigned g; +typedef long h; +h j, k, l, m, n, o; +int p, q, r, s; +short t; +volatile a u; +a v[]; +char w, x; +a *y, *z; +a **aa; +__attribute__((always_inline)) b __attribute__((vector_size(16))) +ab(f __attribute__((vector_size(8 * sizeof(f)))), d ac, + d __attribute__((vector_size(2 * sizeof(d)))), d) { + return __builtin_shufflevector( + (b __attribute__((vector_size(16)))) __builtin_convertvector( + (d __attribute__((vector_size(16 *sizeof(d))))){ + ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac}, + c __attribute__((vector_size(16)))) | + __builtin_convertvector( + (d __attribute__((vector_size(16 *sizeof(d))))){ + ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac}, + c __attribute__((vector_size(16)))), + __builtin_convertvector( + (d __attribute__((vector_size(16 *sizeof(d))))){ + ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac}, + b __attribute__((vector_size(16)))), + 3, 21, 0, 2, 2, 7, 1, 8, 4, 0, 8, 0, 8, 9, 5, 6); +} +__attribute__((always_inline)) g +ad(d ae, h __attribute__((vector_size(32 * sizeof(h))))) { + g f = 6318; + return (8 ? ae / 786856318u : 0) & ae; +} +a(af)(a, int); +void(ag)(long); +char(ah)(char, char); +char(ai)(char); +short(aj)(short, short); +int ak(long, int *, int *, char, int); +void al(signed, a *, int *, long); +char am(int *, short, short); +void an(int *, long, int); +void ao(int, int *, a *); +a ap() { + int *aq, *ar, *as; + short at; + char au, av, aw = 2; + long ax, ay, az = j; + int ba, i; + g __attribute__((vector_size(16 * sizeof(g)))) bb = {80}; + b __attribute__((vector_size(4))) bc = {6}; + int bd[1]; + char *be = &w; + int bf, bg = q; + a **bh[] = { + &y, &z, &z, &y, &y, &y, &y, &y, &z, &z, &y, &z, &y, &y, &y, &y, &z, &y, + &z, &y, &y, &y, &z, &z, &z, &y, &z, &z, &z, &y, &z, &z, &y, &z, &z, &y, + &z, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y, &y, 0, &z, 0, + &z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z, &y, &z, &z, &y, + 0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y, &y, 0, + &z, 0, &z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z, &y, &z, + &z, &y, 0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y, + &y, 0, &z, 0, &z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z, + &y, &z, &z, &y, 0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, + &z, &y, &y, 0, &z, 0, &z, 0, &y, &z, &z, 0, 0, &z, 0, &z, &z, &z, + &y, &z, &z, &y, &z, &z, &y, 0, &z, 0, 0, &z, &z}; + for (; i; i++) + bd[i] = p; + h __attribute__((vector_size(32 * sizeof(h)))) + bi = {2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, + 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, + 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681}, + bj = __builtin_convertvector( + (c __attribute__((vector_size(32)))){ + aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, + aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw}, + h __attribute__((vector_size(32 * sizeof(h))))), + bk = __builtin_convertvector( + __builtin_shufflevector(bb, bb, 4, 8, 7, 9, 1, 10, 4, 7, 0, 4, 3, 5, 6, 7, + 6, 2, 2, 20, 6, 4, 7, 7, 9, 7, 4, 9, 8, 6, 1, 0, + 6, 9), + h __attribute__((vector_size(32 * sizeof(h))))); + bb = __builtin_convertvector( + ab(__builtin_shufflevector( + __builtin_shufflevector( + __builtin_convertvector( + __builtin_shufflevector(bb, bb, 1, 31, 8, 2, 3, 7, 4, 0, 7, + 3, 4, 6, 7, 1, 9, 3, 8, 7, 1, 8, 5, + 3, 9, 9, 0, 3, 2, 8, 5, 2, 5, 3), + f __attribute__((vector_size(32 * sizeof(f))))), + (f __attribute__((vector_size(32 * sizeof(f))))){ + 800761418310502961587690471176286910032020044212442466872080013589354162852207417903424527024812447907811618435019152886919380169872910001752451018659493155196043018716516518746289614523948734758456011127254301274351182132760058399143431214610613191313926994549901191890929084305862034120561651877003645}, + 32, 44), + (f __attribute__((vector_size(2 * sizeof(f))))){o}, 1, 0, 3, 0, 2, + 1, 3, 3), + ad(__builtin_clzg((g)aw, (f)bb[9]), + (h __attribute__((vector_size(32 * sizeof(h))))){ + bi[0] ?: bk[0], bi[1] ? 1 : bk[1], bi[2] ? 2 : bk[2], + bi[3] ? 3 : bk[3], bi[4] ? 4 : bk[4], bi[5] ? 5 : bk[5], + bi[6] ? 6 : bk[6], bi[7] ? 7 : bk[7], bi[8] ? 8 : bk[8], + bi[9] ? 9 : bk[9], bi[0] ? 10 : bk[0], bi[1] ? 1 : bk[1], + bi[2] ? 2 : bk[2], bi[3] ? 3 : bk[3], bi[4] ? 4 : bk[4], + bi[5] ? 5 : bk[5], bi[6] ? 6 : bk[6], bi[7] ? 7 : bk[7], + bi[8] ? 8 : bk[8], bi[9] ? 9 : bk[9], bi[0] ? 20 : bk[0], + bi[1] ? 1 : bk[1], bi[2] ? 2 : bk[2], bi[3] ? 3 : bk[3], + bi[4] ? bj[4] : 4, bi[5] ?: 5, bi[6] ?: 6, + bi[7] ? 0 : 7, bi[8] ?: 8, bi[9] ? 0 : 9, + bi[0] ? 0 : 30, bi[1] ?: 1}), + (d __attribute__((vector_size(2 * sizeof(d))))) + __builtin_shufflevector( + __builtin_convertvector( + __builtin_shufflevector(bb, bb, 2, 7, 21, 6), + e __attribute__((vector_size(4 * sizeof(e))))), + __builtin_convertvector( + (c __attribute__((vector_size(4)))){aw, aw}, + e __attribute__((vector_size(4 * sizeof(e))))), + 5, 1) + + (__builtin_convertvector( + __builtin_shufflevector(bb, bb, 4, 5), + e __attribute__((vector_size(2 * sizeof(e))))) <= + __builtin_convertvector( + (c __attribute__((vector_size(2)))){aw}, + e __attribute__((vector_size(2 * sizeof(e)))))), + n ? bb[5] << n : aw), + g __attribute__((vector_size(16 * sizeof(g))))); + ag(aw & t); + at = aj(aw, v[1]); + au = ah(at, aw); + ba = af((1 == ax != aw) <= aw <= au, aw); + ao(0, &bd[0], &r); + o = ay; + an(aq, aw, k); + av = am(ar, l, k); + *be = ai(*be); + al(x, as, &bd[0], aw); + bg = ak(u, &s, &bf, aw, aw); + as = *aa; + return m; +} diff --git a/gcc/testsuite/gcc.target/sh/pr67731.c b/gcc/testsuite/gcc.target/sh/pr67731.c new file mode 100644 index 0000000..43c1657 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr67731.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -m4 -ml" } */ + +typedef struct +{ + _Bool a : 1; + _Bool b : 1; + _Bool c : 1; + _Bool d : 1; + unsigned int e : 4; +} S; + +_Bool test_00 (S* s) +{ + return s->b | s->c; +} + +_Bool test_01 (S* s) +{ + return s->b | s->c | s->d; +} + +/* { dg-final { scan-assembler-times {\ttst} 2 } } */ +/* { dg-final { scan-assembler-times {\tnegc} 2 } } */ +/* { dg-final { scan-assembler-not {\tor} } } */ diff --git a/gcc/testsuite/gcc.target/sparc/cbcond-1.c b/gcc/testsuite/gcc.target/sparc/cbcond-1.c index 74fe475..742ab1d 100644 --- a/gcc/testsuite/gcc.target/sparc/cbcond-1.c +++ b/gcc/testsuite/gcc.target/sparc/cbcond-1.c @@ -34,5 +34,5 @@ void cbcondle (int a) /* { dg-final { scan-assembler "cwbe\t%" { target ilp32 } } } */ /* { dg-final { scan-assembler "cwbne\t%" { target ilp32 } } } */ -/* { dg-final { scan-assembler "cwbl\t%" } } */ -/* { dg-final { scan-assembler "cwble\t%" } } */ +/* { dg-final { scan-assembler "cwbl|cwbge\t%" } } */ +/* { dg-final { scan-assembler "cwble|cwbg\t%" } } */ diff --git a/gcc/testsuite/gcc.target/sparc/cbcond-2.c b/gcc/testsuite/gcc.target/sparc/cbcond-2.c index da6c617..c55f9e9 100644 --- a/gcc/testsuite/gcc.target/sparc/cbcond-2.c +++ b/gcc/testsuite/gcc.target/sparc/cbcond-2.c @@ -35,5 +35,5 @@ void cbcondle (long a) /* { dg-final { scan-assembler "cxbe\t%" } } */ /* { dg-final { scan-assembler "cxbne\t%" } } */ -/* { dg-final { scan-assembler "cxbl\t%" } } */ -/* { dg-final { scan-assembler "cxble\t%" } } */ +/* { dg-final { scan-assembler "cxbl|cxbge\t%" } } */ +/* { dg-final { scan-assembler "cxble|cxbg\t%" } } */ diff --git a/gcc/testsuite/gcc.target/sparc/overflow-3.c b/gcc/testsuite/gcc.target/sparc/overflow-3.c index 52d6ab2..ce52de0 100644 --- a/gcc/testsuite/gcc.target/sparc/overflow-3.c +++ b/gcc/testsuite/gcc.target/sparc/overflow-3.c @@ -38,6 +38,6 @@ bool my_neg_overflow (int32_t a, int32_t *res) /* { dg-final { scan-assembler-times "addcc\t%" 2 } } */ /* { dg-final { scan-assembler-times "subcc\t%" 4 } } */ /* { dg-final { scan-assembler-times "addx\t%" 3 } } */ -/* { dg-final { scan-assembler-times "bvs" 3 } } */ +/* { dg-final { scan-assembler-times "bvs|bvc" 3 } } */ /* { dg-final { scan-assembler-not "cmp\t%" } } */ /* { dg-final { scan-assembler-not "save\t%" } } */ diff --git a/gcc/testsuite/gcc.target/sparc/overflow-4.c b/gcc/testsuite/gcc.target/sparc/overflow-4.c index c6121b9..2b62edf 100644 --- a/gcc/testsuite/gcc.target/sparc/overflow-4.c +++ b/gcc/testsuite/gcc.target/sparc/overflow-4.c @@ -38,7 +38,7 @@ bool my_neg_overflow (int64_t a, int64_t *res) /* { dg-final { scan-assembler-times "addcc\t%" 2 } } */ /* { dg-final { scan-assembler-times "subcc\t%" 4 } } */ /* { dg-final { scan-assembler-times "movlu\t%" 1 } } */ -/* { dg-final { scan-assembler-times "blu" 2 } } */ -/* { dg-final { scan-assembler-times "bvs" 3 } } */ +/* { dg-final { scan-assembler-times "blu|bgeu" 2 } } */ +/* { dg-final { scan-assembler-times "bvs|bvc" 3 } } */ /* { dg-final { scan-assembler-not "cmp\t%" } } */ /* { dg-final { scan-assembler-not "save\t%" } } */ diff --git a/gcc/testsuite/gcc.target/sparc/overflow-5.c b/gcc/testsuite/gcc.target/sparc/overflow-5.c index f00283f..0459a65 100644 --- a/gcc/testsuite/gcc.target/sparc/overflow-5.c +++ b/gcc/testsuite/gcc.target/sparc/overflow-5.c @@ -38,6 +38,6 @@ bool my_neg_overflow (int64_t a, int64_t *res) /* { dg-final { scan-assembler-times "addcc\t%" 2 } } */ /* { dg-final { scan-assembler-times "subcc\t%" 4 } } */ /* { dg-final { scan-assembler-times "addxc\t%" 3 } } */ -/* { dg-final { scan-assembler-times "bvs" 3 } } */ +/* { dg-final { scan-assembler-times "bvs|bvc" 3 } } */ /* { dg-final { scan-assembler-not "cmp\t%" } } */ /* { dg-final { scan-assembler-not "save\t%" } } */ diff --git a/gcc/testsuite/gcc.target/sparc/small-struct-1.c b/gcc/testsuite/gcc.target/sparc/small-struct-1.c index 4897288..1ceccd5 100644 --- a/gcc/testsuite/gcc.target/sparc/small-struct-1.c +++ b/gcc/testsuite/gcc.target/sparc/small-struct-1.c @@ -42,5 +42,5 @@ double get2x (struct vec2x v) return v.x + v.y; } -/* { dg-final { scan-assembler-not "ldx" } } */ -/* { dg-final { scan-assembler-not "stx" } } */ +/* { dg-final { scan-assembler-not "ldx" { target *-*-solaris* } } } */ +/* { dg-final { scan-assembler-not "stx" { target *-*-solaris* } } } */ diff --git a/gcc/testsuite/gfortran.dg/pure_result.f90 b/gcc/testsuite/gfortran.dg/pure_result.f90 new file mode 100644 index 0000000..a4d30aa --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pure_result.f90 @@ -0,0 +1,49 @@ +! { dg-do compile } +! PR fortran/78640 - constraints on pure function results +! +! F2018:C1585, F2023:C1594: +! "The function result of a pure function shall not be both polymorphic and +! allocatable, or have a polymorphic allocatable ultimate component." + +program pr78640 + implicit none + + type foo_t + end type + + type bar_t + integer, allocatable :: dummy + class(*), allocatable :: c + end type bar_t + +contains + + pure function f() result(foo) ! { dg-error "is polymorphic allocatable" } + class(foo_t), allocatable :: foo + foo = foo_t() + end function + + pure function f2() ! { dg-error "is polymorphic allocatable" } + class(foo_t), allocatable :: f2 + f2 = foo_t() + end function + + pure function g() result(foo) ! { dg-error "is polymorphic allocatable" } + class(*), allocatable :: foo + foo = foo_t() + end function + + pure function g2() ! { dg-error "is polymorphic allocatable" } + class(*), allocatable :: g2 + g2 = foo_t() + end function + + pure function h() result(bar) ! { dg-error "polymorphic allocatable component" } + type(bar_t) :: bar + end function + + pure function h2() ! { dg-error "polymorphic allocatable component" } + type(bar_t) :: h2 + end function + +end diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod new file mode 100644 index 0000000..63fd338 --- /dev/null +++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod @@ -0,0 +1,12 @@ + +(* { dg-do compile } *) +(* { dg-options "-g -c" } *) + +MODULE badimport2 ; + +FROM StrIO IMPORT Writestring ; + (* { dg-error "error: In program module 'badimport2': unknown symbol 'Writestring', did you mean WriteString?" "Writestring" { target *-*-* } 7 } *) + +BEGIN + +END badimport2. diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod new file mode 100644 index 0000000..ab82cd5 --- /dev/null +++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod @@ -0,0 +1,17 @@ + +(* { dg-do compile } *) +(* { dg-options "-g -c" } *) + +MODULE badimport3 ; + +CONST + Foo = 42 ; + +MODULE inner ; +IMPORT foo ; + (* { dg-error "error: In inner module 'inner': unknown symbol 'foo', did you mean Foo?" "foo" { target *-*-* } 11 } *) +END inner ; + + +BEGIN +END badimport3. diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod new file mode 100644 index 0000000..1b310d7 --- /dev/null +++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod @@ -0,0 +1,17 @@ + +(* { dg-do compile } *) +(* { dg-options "-g -c" } *) + +MODULE badimport4 ; + +CONST + Foo = 42 ; + +MODULE inner ; +IMPORT foo ; + (* { dg-error "error: In inner module 'inner': unknown symbol 'foo', did you mean Foo?" "foo" { target *-*-* } 11 } *) +END inner ; + + +BEGIN +END badimport4. diff --git a/gcc/testsuite/gnat.dg/specs/unknown_discr1.ads b/gcc/testsuite/gnat.dg/specs/unknown_discr1.ads new file mode 100644 index 0000000..d1c85e1 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/unknown_discr1.ads @@ -0,0 +1,23 @@ +-- { dg-do compile } + +with Unknown_Discr1_Pkg; use Unknown_Discr1_Pkg; +with Unknown_Discr1_Pkg.Child; +with Unknown_Discr1_Pkg.Inst; + +package Unknown_Discr1 is + + A : Tagged_Type (0); -- { dg-error "type has unknown discriminants" } + + B : Child.Derived_1 (1); -- { dg-error "type has unknown discriminants" } + + C : Child.Derived_2 (2); -- { dg-error "type has unknown discriminants" } + + D : Child.Nested.Derived_3 (3); -- { dg-error "type has unknown discriminants" } + + E : Inst.Derived_1 (1); -- { dg-error "type has unknown discriminants" } + + F : Inst.Derived_2 (2); -- { dg-error "type has unknown discriminants" } + + G : Inst.Nested.Derived_3 (3); -- { dg-error "type has unknown discriminants" } + +end Unknown_Discr1; diff --git a/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-child.ads b/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-child.ads new file mode 100644 index 0000000..681efbc --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-child.ads @@ -0,0 +1,17 @@ +package Unknown_Discr1_Pkg.Child is + + type Derived_1 is new Tagged_Type with null record; + + type Derived_2 is new Derived_1 with null record; + + package Nested is + + type Derived_3 is new Tagged_Type with private; + + private + + type Derived_3 is new Tagged_Type with null record; + + end Nested; + +end Unknown_Discr1_Pkg.Child; diff --git a/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-g.ads b/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-g.ads new file mode 100644 index 0000000..1570405 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-g.ads @@ -0,0 +1,21 @@ +generic + + type Base (<>) is new Tagged_Type with private; + +package Unknown_Discr1_Pkg.G is + + type Derived_1 is new Base with null record; + + type Derived_2 is new Derived_1 with null record; + + package Nested is + + type Derived_3 is new Tagged_Type with private; + + private + + type Derived_3 is new Tagged_Type with null record; + + end Nested; + +end Unknown_Discr1_Pkg.G; diff --git a/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-inst.ads b/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-inst.ads new file mode 100644 index 0000000..5dfe119 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg-inst.ads @@ -0,0 +1,3 @@ +with Unknown_Discr1_Pkg.G; + +package Unknown_Discr1_Pkg.Inst is new Unknown_Discr1_Pkg.G (Tagged_Type); diff --git a/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg.ads b/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg.ads new file mode 100644 index 0000000..d769b4d --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/unknown_discr1_pkg.ads @@ -0,0 +1,9 @@ +package Unknown_Discr1_Pkg is + + type Tagged_Type (<>) is tagged limited private; + +private + + type Tagged_Type (Kind : Integer) is tagged limited null record; + +end Unknown_Discr1_Pkg; diff --git a/gcc/testsuite/gnat.dg/use_type4.adb b/gcc/testsuite/gnat.dg/use_type4.adb new file mode 100644 index 0000000..5ceb288 --- /dev/null +++ b/gcc/testsuite/gnat.dg/use_type4.adb @@ -0,0 +1,29 @@ +-- { dg-do compile } + +procedure Use_Type4 is + + package P1 is + type T is new Integer; + function "and" (L, R : in Integer) return T; + end P1; + + package body P1 is + function "and" (L, R : in Integer) return T is + begin + return T (L * R); + end "and"; + end P1; + + use type P1.T; + + package Renaming renames P1; + + package P2 is + use Renaming; + end P2; + + G : P1.T := Integer'(1) and Integer'(2); + +begin + null; +end; diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index 28f0e8c..11a8d4f 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -2185,9 +2185,9 @@ export namespace std using std::print; using std::println; using std::vprint_unicode; - //FIXME using std::vprint_unicode_buffered; + using std::vprint_unicode_buffered; using std::vprint_nonunicode; - //FIXME using std::vprint_nonunicode_buffered; + using std::vprint_nonunicode_buffered; } #endif |
