[PATCH] Fix LTO type mismatch warning on transparent union
Hi, Ada doesn't have an equivalent to transparent union types in GNU C so, when it needs to interface a C function that takes a parameter of a transparent union type, GNAT uses the type of the first member of the union on the Ada side (which is the type used to determine the passing mechanism of the parameter). This works fine, except that LTO may warn about it; for the attached testcase: .> gcc -c t.c -O2 -flto -D_GNU_SOURCE .> gnatmake -q p -O2 -flto -largs t.o q.ads:6:12: warning: type of 'q__c_getpeername' does not match original declaration [-Wlto-type-mismatch] 6 | function C_Getpeername |^ /usr/include/sys/socket.h:130:12: note: type mismatch in parameter 2 130 | extern int getpeername (int __fd, __SOCKADDR_ARG __addr, |^ /usr/include/sys/socket.h:130:12: note: 'getpeername' was previously declared here /usr/include/sys/socket.h:130:12: note: code may be misoptimized unless '-fno- strict-aliasing' is used The attached patch recognizes the situation and checks the compatibility with the type of the first member of the union in this case. Tested on x86-64/Linux, OK for the mainline? 2024-05-29 Eric Botcazou * lto/lto-symtab.cc (warn_type_compatibility_p): Deal with parameters whose type is a transparent union specially. -- Eric Botcazoudiff --git a/gcc/lto/lto-symtab.cc b/gcc/lto/lto-symtab.cc index a40218beac5..ca5a79610bb 100644 --- a/gcc/lto/lto-symtab.cc +++ b/gcc/lto/lto-symtab.cc @@ -233,8 +233,20 @@ warn_type_compatibility_p (tree prevailing_type, tree type, parm1 && parm2; parm1 = TREE_CHAIN (parm1), parm2 = TREE_CHAIN (parm2)) - lev |= warn_type_compatibility_p (TREE_VALUE (parm1), - TREE_VALUE (parm2), false); + /* If a function with a transparent union parameter is interfaced + with another type, check that the latter is compatible with the + type of the first field of the union, which is the type used to + set the calling convention for the argument. */ + if (TREE_CODE (TREE_VALUE (parm1)) == UNION_TYPE + && TYPE_TRANSPARENT_AGGR (TREE_VALUE (parm1)) + && TREE_CODE (TREE_VALUE (parm2)) != UNION_TYPE + && common_or_extern) + lev |= warn_type_compatibility_p + (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (parm1))), + TREE_VALUE (parm2), false); + else + lev |= warn_type_compatibility_p (TREE_VALUE (parm1), + TREE_VALUE (parm2), false); if (parm1 || parm2) lev |= odr_p ? 3 : 1; } with Interfaces.C; use Interfaces.C; with System; with Q; use Q; procedure P is L : aliased unsigned; I : int := C_Getpeername (0, System.Null_Address, L'Access); begin null; end; with Interfaces.C; with System; package Q is function C_Getpeername (S : Interfaces.C.int; Name: System.Address; Namelen : not null access Interfaces.C.unsigned) return Interfaces.C.int; pragma Import (C, C_Getpeername, "getpeername"); procedure Foo; pragma Import (C, Foo, "foo"); end Q; #include #include void foo (void) { int i = getpeername (0, NULL, NULL); }
[Ada] Fix PR ada/115270
This fixes the link failure of the GNAT tools on 32-bit SPARC/Linux (as well as on 32-bit PowerPC/Linux probably) coming from an incorrect binding to the 64-bit compare-and-exchange builtin. Tested by Rainer on 32-bit SPARC/Linux, applied on mainline and 14 branch. 2024-05-29 Eric Botcazou PR ada/115270 * Makefile.rtl (PowerPC/Linux): Use libgnat/s-atopri__32.ads for the 32-bit library. (SPARC/Linux): Likewise. -- Eric Botcazoudiff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 570d0b2703d..0f5ebb87d73 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -2266,15 +2266,18 @@ ifeq ($(strip $(filter-out powerpc% linux%,$(target_cpu) $(target_os))),) system.ads
[gcc r14-10258] Fix link failure of GNAT tools on 32-bit SPARC/Linux
https://gcc.gnu.org/g:fba2843b9b35b9700155677f90555700b6ad4e16 commit r14-10258-gfba2843b9b35b9700155677f90555700b6ad4e16 Author: Eric Botcazou Date: Wed May 29 12:06:32 2024 +0200 Fix link failure of GNAT tools on 32-bit SPARC/Linux There is an incorrect binding to the 64-bit compare-and-exchange builtin. gcc/ada/ PR ada/115270 * Makefile.rtl (PowerPC/Linux): Use libgnat/s-atopri__32.ads for the 32-bit library. (SPARC/Linux): Likewise. Diff: --- gcc/ada/Makefile.rtl | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 6e1ca305faf..32cbdb69247 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -2238,15 +2238,18 @@ ifeq ($(strip $(filter-out powerpc% linux%,$(target_cpu) $(target_os))),) system.ads
[gcc r15-894] Fix link failure of GNAT tools on 32-bit SPARC/Linux
https://gcc.gnu.org/g:9c6e75a6d1cc2858fc945266a5edb700edb44389 commit r15-894-g9c6e75a6d1cc2858fc945266a5edb700edb44389 Author: Eric Botcazou Date: Wed May 29 12:06:32 2024 +0200 Fix link failure of GNAT tools on 32-bit SPARC/Linux There is an incorrect binding to the 64-bit compare-and-exchange builtin. gcc/ada/ PR ada/115270 * Makefile.rtl (PowerPC/Linux): Use libgnat/s-atopri__32.ads for the 32-bit library. (SPARC/Linux): Likewise. Diff: --- gcc/ada/Makefile.rtl | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 570d0b2703d..0f5ebb87d73 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -2266,15 +2266,18 @@ ifeq ($(strip $(filter-out powerpc% linux%,$(target_cpu) $(target_os))),) system.ads
[c-family] Small enhancement to implementation of -fdump-ada-spec
This lets it recognize more preprocessing floating constants. Tested on x86-64/Linux, applied on the mainline. 2024-05-24 Eric Botcazou * c-ada-spec.cc (is_cpp_float): New predicate. (dump_number): Deal with more preprocessing floating constants. (dump_ada_macros) : Use is_cpp_float. -- Eric Botcazoudiff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index 8f0849bd427..0bea923220b 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -113,6 +113,26 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len, (*buffer_len)++; } +/* Return true if NUMBER is a preprocessing floating-point number. */ + +static bool +is_cpp_float (unsigned char *number) +{ + /* In C, a floating constant need not have a point. */ + while (*number != '\0') +{ + if (*number == '.') + return true; + else if ((*number == 'e' || *number == 'E') + && (*(number + 1) == '+' || *(number + 1) == '-')) + return true; + else + number++; +} + + return false; +} + /* Dump all digits/hex chars from NUMBER to BUFFER and return a pointer to the character after the last character written. If FLOAT_P is true, this is a floating-point number. */ @@ -120,12 +140,45 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len, static unsigned char * dump_number (unsigned char *number, unsigned char *buffer, bool float_p) { - while (*number != '\0' - && *number != (float_p ? 'F' : 'U') - && *number != (float_p ? 'f' : 'u') - && *number != 'l' - && *number != 'L') -*buffer++ = *number++; + /* In Ada, a real literal is a numeric literal that includes a point. */ + if (float_p) +{ + bool point_seen = false; + + while (*number != '\0') + { + if (ISDIGIT (*number)) + *buffer++ = *number++; + else if (*number == '.') + { + *buffer++ = *number++; + point_seen = true; + } + else if ((*number == 'e' || *number == 'E') + && (*(number + 1) == '+' || *(number + 1) == '-')) + { + if (!point_seen) + { + *buffer++ = '.'; + *buffer++ = '0'; + point_seen = true; + } + *buffer++ = *number++; + *buffer++ = *number++; + } + else + break; + } +} + + /* An integer literal is a numeric literal without a point. */ + else +while (*number != '\0' + && *number != 'U' + && *number != 'u' + && *number != 'l' + && *number != 'L') + *buffer++ = *number++; return buffer; } @@ -450,7 +503,7 @@ dump_ada_macros (pretty_printer *pp, const char* file) default: /* Dump floating-point constant unmodified. */ -if (strchr ((const char *)tmp, '.')) +if (is_cpp_float (tmp)) buffer = dump_number (tmp, buffer, true); else { @@ -480,8 +533,7 @@ dump_ada_macros (pretty_printer *pp, const char* file) default: buffer - = dump_number (tmp, buffer, - strchr ((const char *)tmp, '.')); + = dump_number (tmp, buffer, is_cpp_float (tmp)); break; } break;
[gcc r15-826] Small enhancement to implementation of -fdump-ada-spec
https://gcc.gnu.org/g:73eef7a04453d01147cbf4642fe6626350dded75 commit r15-826-g73eef7a04453d01147cbf4642fe6626350dded75 Author: Eric Botcazou Date: Fri May 24 19:48:18 2024 +0200 Small enhancement to implementation of -fdump-ada-spec This lets it recognize more preprocessing floating constants. gcc/c-family/ * c-ada-spec.cc (is_cpp_float): New predicate. (dump_number): Deal with more preprocessing floating constants. (dump_ada_macros) : Use is_cpp_float. Diff: --- gcc/c-family/c-ada-spec.cc | 70 -- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index 8f0849bd427..0bea923220b 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -113,6 +113,26 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len, (*buffer_len)++; } +/* Return true if NUMBER is a preprocessing floating-point number. */ + +static bool +is_cpp_float (unsigned char *number) +{ + /* In C, a floating constant need not have a point. */ + while (*number != '\0') +{ + if (*number == '.') + return true; + else if ((*number == 'e' || *number == 'E') + && (*(number + 1) == '+' || *(number + 1) == '-')) + return true; + else + number++; +} + + return false; +} + /* Dump all digits/hex chars from NUMBER to BUFFER and return a pointer to the character after the last character written. If FLOAT_P is true, this is a floating-point number. */ @@ -120,12 +140,45 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len, static unsigned char * dump_number (unsigned char *number, unsigned char *buffer, bool float_p) { - while (*number != '\0' -&& *number != (float_p ? 'F' : 'U') -&& *number != (float_p ? 'f' : 'u') -&& *number != 'l' -&& *number != 'L') -*buffer++ = *number++; + /* In Ada, a real literal is a numeric literal that includes a point. */ + if (float_p) +{ + bool point_seen = false; + + while (*number != '\0') + { + if (ISDIGIT (*number)) + *buffer++ = *number++; + else if (*number == '.') + { + *buffer++ = *number++; + point_seen = true; + } + else if ((*number == 'e' || *number == 'E') + && (*(number + 1) == '+' || *(number + 1) == '-')) + { + if (!point_seen) + { + *buffer++ = '.'; + *buffer++ = '0'; + point_seen = true; + } + *buffer++ = *number++; + *buffer++ = *number++; + } + else + break; + } +} + + /* An integer literal is a numeric literal without a point. */ + else +while (*number != '\0' + && *number != 'U' + && *number != 'u' + && *number != 'l' + && *number != 'L') + *buffer++ = *number++; return buffer; } @@ -450,7 +503,7 @@ dump_ada_macros (pretty_printer *pp, const char* file) default: /* Dump floating-point constant unmodified. */ - if (strchr ((const char *)tmp, '.')) + if (is_cpp_float (tmp)) buffer = dump_number (tmp, buffer, true); else { @@ -480,8 +533,7 @@ dump_ada_macros (pretty_printer *pp, const char* file) default: buffer - = dump_number (tmp, buffer, - strchr ((const char *)tmp, '.')); + = dump_number (tmp, buffer, is_cpp_float (tmp)); break; } break;
[c-family] Another small fix to implementation of -fdump-ada-spec
This avoids generating invalid Ada code for functions with a multidimensional array parameter and also cleans things up left and right. Tested on x86-64/Linux, applied on the mainline. 2024-05-23 Eric Botcazou * c-ada-spec.cc (check_type_name_conflict): Add guard. (is_char_array): Simplify. (dump_ada_array_type): Use strip_array_types. (dump_ada_node) : Deal with anonymous array types. (dump_nested_type): Use strip_array_types. -- Eric Botcazoudiff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index 46fee30b6b9..8f0849bd427 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -1558,7 +1558,7 @@ check_type_name_conflict (pretty_printer *buffer, tree t) while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp)) tmp = TREE_TYPE (tmp); - if (TREE_CODE (tmp) != FUNCTION_TYPE) + if (TREE_CODE (tmp) != FUNCTION_TYPE && tmp != error_mark_node) { const char *s; @@ -1788,17 +1788,9 @@ dump_sloc (pretty_printer *buffer, tree node) static bool is_char_array (tree t) { - int num_dim = 0; - - while (TREE_CODE (t) == ARRAY_TYPE) -{ - num_dim++; - t = TREE_TYPE (t); -} - - return num_dim == 1 - && TREE_CODE (t) == INTEGER_TYPE - && id_equal (DECL_NAME (TYPE_NAME (t)), "char"); + return TREE_CODE (t) == ARRAY_TYPE + && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE + && id_equal (DECL_NAME (TYPE_NAME (TREE_TYPE (t))), "char"); } /* Dump in BUFFER an array type NODE in Ada syntax. SPC is the indentation @@ -1821,9 +1813,7 @@ dump_ada_array_type (pretty_printer *buffer, tree node, int spc) /* Print the component type. */ if (!char_array) { - tree tmp = node; - while (TREE_CODE (tmp) == ARRAY_TYPE) - tmp = TREE_TYPE (tmp); + tree tmp = strip_array_types (node); pp_string (buffer, " of "); @@ -2350,6 +2340,11 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, && DECL_ORIGINAL_TYPE (DECL_CHAIN (stub)) == ref_type) ref_type = TREE_TYPE (DECL_CHAIN (stub)); + /* If this is a pointer to an anonymous array type, then use + the name of the component type. */ + else if (!type_name && is_access) + ref_type = strip_array_types (ref_type); + /* Generate "access " instead of "access " if the subtype comes from another file, because subtype declarations do not contribute to the limited view of a @@ -2639,10 +2634,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, int spc) if (!bitmap_set_bit (dumped_anonymous_types, TYPE_UID (field_type))) return; - /* Recurse on the element type if need be. */ - tmp = TREE_TYPE (field_type); - while (TREE_CODE (tmp) == ARRAY_TYPE) - tmp = TREE_TYPE (tmp); + tmp = strip_array_types (field_type); decl = get_underlying_decl (tmp); if (decl && !DECL_NAME (decl)
[gcc r15-795] Another small fix to implementation of -fdump-ada-spec
https://gcc.gnu.org/g:0b3b6a8df77b0ae15078402ea5fb933d6fccd585 commit r15-795-g0b3b6a8df77b0ae15078402ea5fb933d6fccd585 Author: Eric Botcazou Date: Thu May 23 18:26:12 2024 +0200 Another small fix to implementation of -fdump-ada-spec This avoids generating invalid Ada code for function with a multidimensional array parameter and also cleans things up left and right. gcc/c-family/ * c-ada-spec.cc (check_type_name_conflict): Add guard. (is_char_array): Simplify. (dump_ada_array_type): Use strip_array_types. (dump_ada_node) : Deal with anonymous array types. (dump_nested_type): Use strip_array_types. Diff: --- gcc/c-family/c-ada-spec.cc | 30 +++--- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index 46fee30b6b9..8f0849bd427 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -1558,7 +1558,7 @@ check_type_name_conflict (pretty_printer *buffer, tree t) while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp)) tmp = TREE_TYPE (tmp); - if (TREE_CODE (tmp) != FUNCTION_TYPE) + if (TREE_CODE (tmp) != FUNCTION_TYPE && tmp != error_mark_node) { const char *s; @@ -1788,17 +1788,9 @@ dump_sloc (pretty_printer *buffer, tree node) static bool is_char_array (tree t) { - int num_dim = 0; - - while (TREE_CODE (t) == ARRAY_TYPE) -{ - num_dim++; - t = TREE_TYPE (t); -} - - return num_dim == 1 -&& TREE_CODE (t) == INTEGER_TYPE -&& id_equal (DECL_NAME (TYPE_NAME (t)), "char"); + return TREE_CODE (t) == ARRAY_TYPE +&& TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE +&& id_equal (DECL_NAME (TYPE_NAME (TREE_TYPE (t))), "char"); } /* Dump in BUFFER an array type NODE in Ada syntax. SPC is the indentation @@ -1821,9 +1813,7 @@ dump_ada_array_type (pretty_printer *buffer, tree node, int spc) /* Print the component type. */ if (!char_array) { - tree tmp = node; - while (TREE_CODE (tmp) == ARRAY_TYPE) - tmp = TREE_TYPE (tmp); + tree tmp = strip_array_types (node); pp_string (buffer, " of "); @@ -2350,6 +2340,11 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, && DECL_ORIGINAL_TYPE (DECL_CHAIN (stub)) == ref_type) ref_type = TREE_TYPE (DECL_CHAIN (stub)); + /* If this is a pointer to an anonymous array type, then use +the name of the component type. */ + else if (!type_name && is_access) + ref_type = strip_array_types (ref_type); + /* Generate "access " instead of "access " if the subtype comes from another file, because subtype declarations do not contribute to the limited view of a @@ -2639,10 +2634,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, int spc) if (!bitmap_set_bit (dumped_anonymous_types, TYPE_UID (field_type))) return; - /* Recurse on the element type if need be. */ - tmp = TREE_TYPE (field_type); - while (TREE_CODE (tmp) == ARRAY_TYPE) - tmp = TREE_TYPE (tmp); + tmp = strip_array_types (field_type); decl = get_underlying_decl (tmp); if (decl && !DECL_NAME (decl)
[gcc r14-10233] Fix internal error in seh_cfa_offset with -O2 -fno-omit-frame-pointer
https://gcc.gnu.org/g:2f0e0862406a17bb8bf4ad948ae22916bae092a0 commit r14-10233-g2f0e0862406a17bb8bf4ad948ae22916bae092a0 Author: Eric Botcazou Date: Wed May 22 18:10:39 2024 +0200 Fix internal error in seh_cfa_offset with -O2 -fno-omit-frame-pointer The problem directly comes from the -ffold-mem-offsets pass messing up with the prologue and the frame-related instructions, which is a no-no with SEH, so the fix simply disconnects the pass in these circumstances. gcc/ PR rtl-optimization/115038 * fold-mem-offsets.cc (fold_offsets): Return 0 if the defining instruction of the register is frame related. gcc/testsuite/ * g++.dg/opt/fmo1.C: New test. Diff: --- gcc/fold-mem-offsets.cc | 2 +- gcc/testsuite/g++.dg/opt/fmo1.C | 25 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/gcc/fold-mem-offsets.cc b/gcc/fold-mem-offsets.cc index 2e15b05529e..84b9623058b 100644 --- a/gcc/fold-mem-offsets.cc +++ b/gcc/fold-mem-offsets.cc @@ -491,7 +491,7 @@ fold_offsets (rtx_insn *insn, rtx reg, bool analyze, bitmap foldable_insns) { rtx_insn *def = get_single_def_in_bb (insn, reg); - if (!def || GET_CODE (PATTERN (def)) != SET) + if (!def || RTX_FRAME_RELATED_P (def) || GET_CODE (PATTERN (def)) != SET) return 0; rtx dest = SET_DEST (PATTERN (def)); diff --git a/gcc/testsuite/g++.dg/opt/fmo1.C b/gcc/testsuite/g++.dg/opt/fmo1.C new file mode 100644 index 000..f0ae624c61a --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/fmo1.C @@ -0,0 +1,25 @@ +// PR rtl-optimization/115038 +// Reported by Christoph Reiter + +// { dg-do compile } +// { dg-options "-O2 -fno-omit-frame-pointer" } + +struct d { + d(); +}; + +struct e { + e() : c(1.0) {} + float c; +}; + +class k { + d g; + e h; +}; + +class a { + k f; +} a; + +k b;
[gcc r15-776] Fix internal error in seh_cfa_offset with -O2 -fno-omit-frame-pointer
https://gcc.gnu.org/g:f14ef5cfd4c1ba1d34afda9174935e40d3c0a3ce commit r15-776-gf14ef5cfd4c1ba1d34afda9174935e40d3c0a3ce Author: Eric Botcazou Date: Wed May 22 18:10:39 2024 +0200 Fix internal error in seh_cfa_offset with -O2 -fno-omit-frame-pointer The problem directly comes from the -ffold-mem-offsets pass messing up with the prologue and the frame-related instructions, which is a no-no with SEH, so the fix simply disconnects the pass in these circumstances. gcc/ PR rtl-optimization/115038 * fold-mem-offsets.cc (fold_offsets): Return 0 if the defining instruction of the register is frame related. gcc/testsuite/ * g++.dg/opt/fmo1.C: New test. Diff: --- gcc/fold-mem-offsets.cc | 2 +- gcc/testsuite/g++.dg/opt/fmo1.C | 25 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/gcc/fold-mem-offsets.cc b/gcc/fold-mem-offsets.cc index 2e15b05529e..84b9623058b 100644 --- a/gcc/fold-mem-offsets.cc +++ b/gcc/fold-mem-offsets.cc @@ -491,7 +491,7 @@ fold_offsets (rtx_insn *insn, rtx reg, bool analyze, bitmap foldable_insns) { rtx_insn *def = get_single_def_in_bb (insn, reg); - if (!def || GET_CODE (PATTERN (def)) != SET) + if (!def || RTX_FRAME_RELATED_P (def) || GET_CODE (PATTERN (def)) != SET) return 0; rtx dest = SET_DEST (PATTERN (def)); diff --git a/gcc/testsuite/g++.dg/opt/fmo1.C b/gcc/testsuite/g++.dg/opt/fmo1.C new file mode 100644 index 000..f0ae624c61a --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/fmo1.C @@ -0,0 +1,25 @@ +// PR rtl-optimization/115038 +// Reported by Christoph Reiter + +// { dg-do compile } +// { dg-options "-O2 -fno-omit-frame-pointer" } + +struct d { + d(); +}; + +struct e { + e() : c(1.0) {} + float c; +}; + +class k { + d g; + e h; +}; + +class a { + k f; +} a; + +k b;
[Ada] Fix PR ada/115168
Recent changes made to the runtime library broke again its build on Solaris because it uses Solaris threads instead of POSIX threads on this platform. Tested by Rainer, applied on the mainline. 2024-05-21 Eric Botcazou PR ada/115168 * libgnarl/s-taprop__solaris.adb (Initialize): Fix pasto. * libgnat/s-oslock__solaris.ads (Owner_Int): Delete. (Owner_ID): Change the designated type to Integer. -- Eric Botcazoudiff --git a/gcc/ada/libgnarl/s-taprop__solaris.adb b/gcc/ada/libgnarl/s-taprop__solaris.adb index 09f90e6e204..6d05e8db004 100644 --- a/gcc/ada/libgnarl/s-taprop__solaris.adb +++ b/gcc/ada/libgnarl/s-taprop__solaris.adb @@ -424,7 +424,7 @@ package body System.Task_Primitives.Operations is begin Environment_Task_Id := Environment_Task; - Self_ID.Common.LL.Thread := thr_self; + Environment_Task.Common.LL.Thread := thr_self; Interrupt_Management.Initialize; diff --git a/gcc/ada/libgnat/s-oslock__solaris.ads b/gcc/ada/libgnat/s-oslock__solaris.ads index cc5a83df02e..56a242c8070 100644 --- a/gcc/ada/libgnat/s-oslock__solaris.ads +++ b/gcc/ada/libgnat/s-oslock__solaris.ads @@ -42,10 +42,7 @@ package System.OS_Locks is type Private_Task_Serial_Number is mod 2 ** Long_Long_Integer'Size; -- Used to give each task a unique serial number - type Owner_Int is new Integer; - for Owner_Int'Alignment use Standard'Maximum_Alignment; - - type Owner_ID is access all Owner_Int; + type Owner_ID is access all Integer; function To_Owner_ID is new Ada.Unchecked_Conversion (System.Address, Owner_ID);
[gcc r15-751] Fix Ada runtime library breakage on Solaris (bis)
https://gcc.gnu.org/g:7b215c867629e095a4ac403bd026b6eb293962b4 commit r15-751-g7b215c867629e095a4ac403bd026b6eb293962b4 Author: Eric Botcazou Date: Tue May 21 11:11:02 2024 +0200 Fix Ada runtime library breakage on Solaris (bis) Recent changes made to the runtime library broke again its build on Solaris because it uses Solaris threads instead of POSIX threads on this platform. gcc/ada/ PR ada/115168 * libgnarl/s-taprop__solaris.adb (Initialize): Fix pasto. * libgnat/s-oslock__solaris.ads (Owner_Int): Delete. (Owner_ID): Change the designated type to Integer. Diff: --- gcc/ada/libgnarl/s-taprop__solaris.adb | 2 +- gcc/ada/libgnat/s-oslock__solaris.ads | 5 + 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/gcc/ada/libgnarl/s-taprop__solaris.adb b/gcc/ada/libgnarl/s-taprop__solaris.adb index 09f90e6e204..6d05e8db004 100644 --- a/gcc/ada/libgnarl/s-taprop__solaris.adb +++ b/gcc/ada/libgnarl/s-taprop__solaris.adb @@ -424,7 +424,7 @@ package body System.Task_Primitives.Operations is begin Environment_Task_Id := Environment_Task; - Self_ID.Common.LL.Thread := thr_self; + Environment_Task.Common.LL.Thread := thr_self; Interrupt_Management.Initialize; diff --git a/gcc/ada/libgnat/s-oslock__solaris.ads b/gcc/ada/libgnat/s-oslock__solaris.ads index cc5a83df02e..56a242c8070 100644 --- a/gcc/ada/libgnat/s-oslock__solaris.ads +++ b/gcc/ada/libgnat/s-oslock__solaris.ads @@ -42,10 +42,7 @@ package System.OS_Locks is type Private_Task_Serial_Number is mod 2 ** Long_Long_Integer'Size; -- Used to give each task a unique serial number - type Owner_Int is new Integer; - for Owner_Int'Alignment use Standard'Maximum_Alignment; - - type Owner_ID is access all Owner_Int; + type Owner_ID is access all Integer; function To_Owner_ID is new Ada.Unchecked_Conversion (System.Address, Owner_ID);
[PATCH] Fix PR rtl-optimization/115038
Hi, this is a regression present on mainline and 14 branch under the form of an ICE in seh_cfa_offset from config/i386/winnt.cc on the attached C++ testcase compiled with -O2 -fno-omit-frame-pointer. The problem directly comes from the -ffold-mem-offsets pass messing up with the prologue and the frame-related instructions, which is a no-no with SEH, so the fix simply disconnects the pass in these circumstances, the question being whether this should be done unconditionally as in the fix or only with SEH. Tested on x86-64/Linux, OK for the mainline and 14 branch? 2024-05-20 Eric Botcazou PR rtl-optimization/115038 * fold-mem-offsets.cc (fold_offsets): Return 0 if the defining instruction of the register is frame related. 2024-05-20 Eric Botcazou * g++.dg/opt/fmo1.C: New test. -- Eric Botcazoudiff --git a/gcc/fold-mem-offsets.cc b/gcc/fold-mem-offsets.cc index 2e15b05529e..84b9623058b 100644 --- a/gcc/fold-mem-offsets.cc +++ b/gcc/fold-mem-offsets.cc @@ -491,7 +491,7 @@ fold_offsets (rtx_insn *insn, rtx reg, bool analyze, bitmap foldable_insns) { rtx_insn *def = get_single_def_in_bb (insn, reg); - if (!def || GET_CODE (PATTERN (def)) != SET) + if (!def || RTX_FRAME_RELATED_P (def) || GET_CODE (PATTERN (def)) != SET) return 0; rtx dest = SET_DEST (PATTERN (def)); // PR rtl-optimization/115038 // Reported by Christoph Reiter // { dg-do compile } // { dg-options "-O2 -fno-omit-frame-pointer" } struct d { d(); }; struct e { e() : c(1.0) {} float c; }; class k { d g; e h; }; class a { k f; } a; k b;
Re: [PATCH] Add widening expansion of MULT_HIGHPART_EXPR for integral modes
Hi, > Just notice that this patch may result in some ICE when build libc++ for the > riscv port, details as below. Please note not all configuration can > reproduce this issue, feel free to ping me if you cannot reproduce this > issue. CC more riscv port people for awareness. Sorry for the breakage, fixed thus, applied as obvious. * optabs-query.cc (can_mult_highpart_p): Test for the existence of a wider mode instead of requiring it. -- Eric Botcazoudiff --git a/gcc/optabs-query.cc b/gcc/optabs-query.cc index de145be7075..5149de57468 100644 --- a/gcc/optabs-query.cc +++ b/gcc/optabs-query.cc @@ -510,17 +510,16 @@ int can_mult_highpart_p (machine_mode mode, bool uns_p) { optab op; - scalar_int_mode int_mode; + scalar_int_mode int_mode, wider_mode; op = uns_p ? umul_highpart_optab : smul_highpart_optab; if (optab_handler (op, mode) != CODE_FOR_nothing) return 1; /* If the mode is integral, synth from widening or larger operations. */ - if (is_a (mode, _mode)) + if (is_a (mode, _mode) + && GET_MODE_WIDER_MODE (int_mode).exists (_mode)) { - scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (int_mode).require (); - op = uns_p ? umul_widen_optab : smul_widen_optab; if (convert_optab_handler (op, wider_mode, mode) != CODE_FOR_nothing) return 2;
[gcc r15-649] Fix oversight in latest change to can_mult_highpart_p
https://gcc.gnu.org/g:3db8dd4139a7a5ce941684f1fc05ee0652e35544 commit r15-649-g3db8dd4139a7a5ce941684f1fc05ee0652e35544 Author: Eric Botcazou Date: Sun May 19 11:38:40 2024 +0200 Fix oversight in latest change to can_mult_highpart_p gcc/ * optabs-query.cc (can_mult_highpart_p): Test for the existence of a wider mode instead of requiring it. Diff: --- gcc/optabs-query.cc | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gcc/optabs-query.cc b/gcc/optabs-query.cc index de145be7075f..5149de57468d 100644 --- a/gcc/optabs-query.cc +++ b/gcc/optabs-query.cc @@ -510,17 +510,16 @@ int can_mult_highpart_p (machine_mode mode, bool uns_p) { optab op; - scalar_int_mode int_mode; + scalar_int_mode int_mode, wider_mode; op = uns_p ? umul_highpart_optab : smul_highpart_optab; if (optab_handler (op, mode) != CODE_FOR_nothing) return 1; /* If the mode is integral, synth from widening or larger operations. */ - if (is_a (mode, _mode)) + if (is_a (mode, _mode) + && GET_MODE_WIDER_MODE (int_mode).exists (_mode)) { - scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (int_mode).require (); - op = uns_p ? umul_widen_optab : smul_widen_optab; if (convert_optab_handler (op, wider_mode, mode) != CODE_FOR_nothing) return 2;
[Ada] Fix PR ada/115133
The recent changes made to the runtime library broke its build on Solaris because it uses Solaris threads instead of POSIX threads on this platform. Tested by Rainer, applied on the mainline. 2024-05-17 Eric Botcazou Rainer Orth PR ada/115133 * libgnarl/s-osinte__solaris.ads (mutex_t): Fix typo. * libgnarl/s-taprop__solaris.adb (Record_Lock): Add conversion. (Check_Sleep): Likewise. (Record_Wakeup): Likewise. (Check_Unlock): Likewise. * libgnarl/s-tasini.adb (Initialize_RTS_Lock): Add pragma Import on the overlaid variable. (Finalize_RTS_Lock): Likewise. (Acquire_RTS_Lock): Likewise. (Release_RTS_Lock): Likewise. * libgnarl/s-taspri__solaris.ads (To_RTS_Lock_Ptr): New instance of Ada.Unchecked_Conversion. * libgnat/s-oslock__solaris.ads: Add with clause for Ada.Unchecked_Conversion. (array_type_9): Add missing name qualification. (record_type_3): Likewise. (mutex_t): Fix formatting. -- Eric Botcazoudiff --git a/gcc/ada/libgnarl/s-osinte__solaris.ads b/gcc/ada/libgnarl/s-osinte__solaris.ads index 12ad52bb48e..3703697ef44 100644 --- a/gcc/ada/libgnarl/s-osinte__solaris.ads +++ b/gcc/ada/libgnarl/s-osinte__solaris.ads @@ -298,7 +298,7 @@ package System.OS_Interface is function To_thread_t is new Ada.Unchecked_Conversion (Integer, thread_t); - subtype mutex_t is System.OS_Lock.mutex_t; + subtype mutex_t is System.OS_Locks.mutex_t; type cond_t is limited private; diff --git a/gcc/ada/libgnarl/s-taprop__solaris.adb b/gcc/ada/libgnarl/s-taprop__solaris.adb index 88b77b09820..82e51b8d25c 100644 --- a/gcc/ada/libgnarl/s-taprop__solaris.adb +++ b/gcc/ada/libgnarl/s-taprop__solaris.adb @@ -1399,7 +1399,7 @@ package body System.Task_Primitives.Operations is P := Self_ID.Common.LL.Locks; if P /= null then - L.Next := P; + L.Next := To_RTS_Lock_Ptr (P); end if; Self_ID.Common.LL.Locking := null; @@ -1440,7 +1440,7 @@ package body System.Task_Primitives.Operations is Self_ID.Common.LL.L.Owner := null; P := Self_ID.Common.LL.Locks; - Self_ID.Common.LL.Locks := Self_ID.Common.LL.Locks.Next; + Self_ID.Common.LL.Locks := To_Lock_Ptr (Self_ID.Common.LL.Locks.Next); P.Next := null; return True; end Check_Sleep; @@ -1468,7 +1468,7 @@ package body System.Task_Primitives.Operations is P := Self_ID.Common.LL.Locks; if P /= null then - L.Next := P; + L.Next := To_RTS_Lock_Ptr (P); end if; Self_ID.Common.LL.Locking := null; @@ -1549,7 +1549,7 @@ package body System.Task_Primitives.Operations is L.Owner := null; P := Self_ID.Common.LL.Locks; - Self_ID.Common.LL.Locks := Self_ID.Common.LL.Locks.Next; + Self_ID.Common.LL.Locks := To_Lock_Ptr (Self_ID.Common.LL.Locks.Next); P.Next := null; return True; end Check_Unlock; diff --git a/gcc/ada/libgnarl/s-tasini.adb b/gcc/ada/libgnarl/s-tasini.adb index 794183f5356..d42d2881df4 100644 --- a/gcc/ada/libgnarl/s-tasini.adb +++ b/gcc/ada/libgnarl/s-tasini.adb @@ -246,6 +246,7 @@ package body System.Tasking.Initialization is procedure Initialize_RTS_Lock (Addr : Address) is Lock : aliased SOL.RTS_Lock; for Lock'Address use Addr; + pragma Import (Ada, Lock); begin Initialize_Lock (Lock'Unchecked_Access, PO_Level); @@ -258,6 +259,7 @@ package body System.Tasking.Initialization is procedure Finalize_RTS_Lock (Addr : Address) is Lock : aliased SOL.RTS_Lock; for Lock'Address use Addr; + pragma Import (Ada, Lock); begin Finalize_Lock (Lock'Unchecked_Access); @@ -270,6 +272,7 @@ package body System.Tasking.Initialization is procedure Acquire_RTS_Lock (Addr : Address) is Lock : aliased SOL.RTS_Lock; for Lock'Address use Addr; + pragma Import (Ada, Lock); begin Write_Lock (Lock'Unchecked_Access); @@ -282,6 +285,7 @@ package body System.Tasking.Initialization is procedure Release_RTS_Lock (Addr : Address) is Lock : aliased SOL.RTS_Lock; for Lock'Address use Addr; + pragma Import (Ada, Lock); begin Unlock (Lock'Unchecked_Access); diff --git a/gcc/ada/libgnarl/s-taspri__solaris.ads b/gcc/ada/libgnarl/s-taspri__solaris.ads index ca40229993b..16fc4196b00 100644 --- a/gcc/ada/libgnarl/s-taspri__solaris.ads +++ b/gcc/ada/libgnarl/s-taspri__solaris.ads @@ -47,6 +47,8 @@ package System.Task_Primitives is function To_Lock_Ptr is new Ada.Unchecked_Conversion (OS_Locks.RTS_Lock_Ptr, Lock_Ptr); + function To_RTS_Lock_Ptr is + new Ada.Unchecked_Conversion (Lock_Ptr, OS_Locks.RTS_Lock_Ptr); type Suspension_Object is limited private; -- Should be used for the implementation of Ada.Synchronous_Task_Control diff --git a/gcc/ada/libgnat/s-oslock__solaris.ads b/gcc/ada/libgnat/s
[gcc r15-641] Fix Ada runtime library breakage on Solaris
https://gcc.gnu.org/g:5812e1bbb1c8a7a90d995a0165cddae4d450d6cf commit r15-641-g5812e1bbb1c8a7a90d995a0165cddae4d450d6cf Author: Eric Botcazou Date: Sat May 18 00:21:56 2024 +0200 Fix Ada runtime library breakage on Solaris The recent changes made to the runtime library broke its build on Solaris because it uses Solaris threads instead of POSIX threads on this platform. gcc/ada/ PR ada/115133 * libgnarl/s-osinte__solaris.ads (mutex_t): Fix typo. * libgnarl/s-taprop__solaris.adb (Record_Lock): Add conversion. (Check_Sleep): Likewise. (Record_Wakeup): Likewise. (Check_Unlock): Likewise. * libgnarl/s-tasini.adb (Initialize_RTS_Lock): Add pragma Import on the overlaid variable. (Finalize_RTS_Lock): Likewise. (Acquire_RTS_Lock): Likewise. (Release_RTS_Lock): Likewise. * libgnarl/s-taspri__solaris.ads (To_RTS_Lock_Ptr): New instance of Ada.Unchecked_Conversion. * libgnat/s-oslock__solaris.ads: Add with clause for Ada.Unchecked_Conversion. (array_type_9): Add missing name qualification. (record_type_3): Likewise. (mutex_t): Fix formatting. Diff: --- gcc/ada/libgnarl/s-osinte__solaris.ads | 2 +- gcc/ada/libgnarl/s-taprop__solaris.adb | 8 gcc/ada/libgnarl/s-tasini.adb | 4 gcc/ada/libgnarl/s-taspri__solaris.ads | 2 ++ gcc/ada/libgnat/s-oslock__solaris.ads | 7 --- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/gcc/ada/libgnarl/s-osinte__solaris.ads b/gcc/ada/libgnarl/s-osinte__solaris.ads index 12ad52bb48ed..3703697ef44f 100644 --- a/gcc/ada/libgnarl/s-osinte__solaris.ads +++ b/gcc/ada/libgnarl/s-osinte__solaris.ads @@ -298,7 +298,7 @@ package System.OS_Interface is function To_thread_t is new Ada.Unchecked_Conversion (Integer, thread_t); - subtype mutex_t is System.OS_Lock.mutex_t; + subtype mutex_t is System.OS_Locks.mutex_t; type cond_t is limited private; diff --git a/gcc/ada/libgnarl/s-taprop__solaris.adb b/gcc/ada/libgnarl/s-taprop__solaris.adb index 88b77b09820d..82e51b8d25c5 100644 --- a/gcc/ada/libgnarl/s-taprop__solaris.adb +++ b/gcc/ada/libgnarl/s-taprop__solaris.adb @@ -1399,7 +1399,7 @@ package body System.Task_Primitives.Operations is P := Self_ID.Common.LL.Locks; if P /= null then - L.Next := P; + L.Next := To_RTS_Lock_Ptr (P); end if; Self_ID.Common.LL.Locking := null; @@ -1440,7 +1440,7 @@ package body System.Task_Primitives.Operations is Self_ID.Common.LL.L.Owner := null; P := Self_ID.Common.LL.Locks; - Self_ID.Common.LL.Locks := Self_ID.Common.LL.Locks.Next; + Self_ID.Common.LL.Locks := To_Lock_Ptr (Self_ID.Common.LL.Locks.Next); P.Next := null; return True; end Check_Sleep; @@ -1468,7 +1468,7 @@ package body System.Task_Primitives.Operations is P := Self_ID.Common.LL.Locks; if P /= null then - L.Next := P; + L.Next := To_RTS_Lock_Ptr (P); end if; Self_ID.Common.LL.Locking := null; @@ -1549,7 +1549,7 @@ package body System.Task_Primitives.Operations is L.Owner := null; P := Self_ID.Common.LL.Locks; - Self_ID.Common.LL.Locks := Self_ID.Common.LL.Locks.Next; + Self_ID.Common.LL.Locks := To_Lock_Ptr (Self_ID.Common.LL.Locks.Next); P.Next := null; return True; end Check_Unlock; diff --git a/gcc/ada/libgnarl/s-tasini.adb b/gcc/ada/libgnarl/s-tasini.adb index 794183f5356a..d42d2881df45 100644 --- a/gcc/ada/libgnarl/s-tasini.adb +++ b/gcc/ada/libgnarl/s-tasini.adb @@ -246,6 +246,7 @@ package body System.Tasking.Initialization is procedure Initialize_RTS_Lock (Addr : Address) is Lock : aliased SOL.RTS_Lock; for Lock'Address use Addr; + pragma Import (Ada, Lock); begin Initialize_Lock (Lock'Unchecked_Access, PO_Level); @@ -258,6 +259,7 @@ package body System.Tasking.Initialization is procedure Finalize_RTS_Lock (Addr : Address) is Lock : aliased SOL.RTS_Lock; for Lock'Address use Addr; + pragma Import (Ada, Lock); begin Finalize_Lock (Lock'Unchecked_Access); @@ -270,6 +272,7 @@ package body System.Tasking.Initialization is procedure Acquire_RTS_Lock (Addr : Address) is Lock : aliased SOL.RTS_Lock; for Lock'Address use Addr; + pragma Import (Ada, Lock); begin Write_Lock (Lock'Unchecked_Access); @@ -282,6 +285,7 @@ package body System.Tasking.Initialization is procedure Release_RTS_Lock (Addr : Address) is Lock : aliased SOL.RTS_Lock; for Lock'Address use Addr; + pragma Import (Ada, Lock); begin Unlock (Lock'Unchecked_Access); diff --git a/gcc/ada/libgnarl/s-taspri__solaris.ads b/gcc/ada/libgnarl/s-taspri__solaris.ads index ca40229993bd..16fc4196b005 100644 --- a/gcc/ada
[gcc r15-623] Add widening expansion of MULT_HIGHPART_EXPR for integral modes
https://gcc.gnu.org/g:f53f8a859631bef97adba1522a8049a8fce57c1b commit r15-623-gf53f8a859631bef97adba1522a8049a8fce57c1b Author: Eric Botcazou Date: Wed May 8 10:07:56 2024 +0200 Add widening expansion of MULT_HIGHPART_EXPR for integral modes For integral modes the expansion of MULT_HIGHPART_EXPR requires the presence of an {s,u}mul_highpart optab whereas, for vector modes, widening expansion is supported. This adds a widening expansion for integral modes too, which is in fact already implemented in expmed_mult_highpart_optab. gcc/ * expmed.h (expmed_mult_highpart_optab): Declare. * expmed.cc (expmed_mult_highpart_optab): Remove static keyword. Do not assume that OP1 is a constant integer. Fix pasto. (expmed_mult_highpart): Pass OP1 narrowed to MODE in all the calls to expmed_mult_highpart_optab. * optabs-query.cc (can_mult_highpart_p): Use 2 for integer widening and shift subsequent values accordingly. * optabs.cc (expand_mult_highpart): Call expmed_mult_highpart_optab when can_mult_highpart_p returns 2 and adjust to above change. Diff: --- gcc/expmed.cc | 54 + gcc/expmed.h| 2 ++ gcc/optabs-query.cc | 24 gcc/optabs.cc | 7 +-- 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/gcc/expmed.cc b/gcc/expmed.cc index 248940fe4147..50d22762cae0 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -2748,8 +2748,7 @@ static rtx expand_mult_const (machine_mode, rtx, HOST_WIDE_INT, rtx, static unsigned HOST_WIDE_INT invert_mod2n (unsigned HOST_WIDE_INT, int); static rtx extract_high_half (scalar_int_mode, rtx); static rtx expmed_mult_highpart (scalar_int_mode, rtx, rtx, rtx, int, int); -static rtx expmed_mult_highpart_optab (scalar_int_mode, rtx, rtx, rtx, - int, int); + /* Compute and return the best algorithm for multiplying by T. The algorithm must cost less than cost_limit If retval.cost >= COST_LIMIT, no algorithm was found and all @@ -3856,30 +3855,25 @@ extract_high_half (scalar_int_mode mode, rtx op) return convert_modes (mode, wider_mode, op, 0); } -/* Like expmed_mult_highpart, but only consider using a multiplication - optab. OP1 is an rtx for the constant operand. */ +/* Like expmed_mult_highpart, but only consider using multiplication optab. */ -static rtx +rtx expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1, rtx target, int unsignedp, int max_cost) { - rtx narrow_op1 = gen_int_mode (INTVAL (op1), mode); + const scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (mode).require (); + const bool speed = optimize_insn_for_speed_p (); + const int size = GET_MODE_BITSIZE (mode); optab moptab; rtx tem; - int size; - bool speed = optimize_insn_for_speed_p (); - - scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (mode).require (); - - size = GET_MODE_BITSIZE (mode); /* Firstly, try using a multiplication insn that only generates the needed high part of the product, and in the sign flavor of unsignedp. */ if (mul_highpart_cost (speed, mode) < max_cost) { moptab = unsignedp ? umul_highpart_optab : smul_highpart_optab; - tem = expand_binop (mode, moptab, op0, narrow_op1, target, - unsignedp, OPTAB_DIRECT); + tem = expand_binop (mode, moptab, op0, op1, target, unsignedp, + OPTAB_DIRECT); if (tem) return tem; } @@ -3892,12 +3886,12 @@ expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1, + 4 * add_cost (speed, mode) < max_cost)) { moptab = unsignedp ? smul_highpart_optab : umul_highpart_optab; - tem = expand_binop (mode, moptab, op0, narrow_op1, target, - unsignedp, OPTAB_DIRECT); + tem = expand_binop (mode, moptab, op0, op1, target, !unsignedp, + OPTAB_DIRECT); if (tem) /* We used the wrong signedness. Adjust the result. */ - return expand_mult_highpart_adjust (mode, tem, op0, narrow_op1, - tem, unsignedp); + return expand_mult_highpart_adjust (mode, tem, op0, op1, tem, + unsignedp); } /* Try widening multiplication. */ @@ -3905,8 +3899,8 @@ expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1, if (convert_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing && mul_widen_cost (speed, wider_mode) < max_cost) { - tem = expand_binop (wider_mode, moptab, op0, narrow_op1, 0, - unsignedp, OPTAB_WIDEN); + tem = expand_binop (wider_mode, moptab, op0, op1, NULL_RTX, unsignedp, + OPTAB_WIDEN); if
[c-family] Small fix to implementation of -fdump-ada-spec
This avoids declaring anonymous array types as having an aliased component when the layout is packed, as is already done for named array types. Tested on x86-64/Linux, applied on the mainline. 2024-05-17 Eric Botcazou * c-ada-spec.cc (bitfield_used): Move around. (packed_layout): Likewise. (dump_ada_array_type): Do not put "aliased" for a packed layout. -- Eric Botcazoudiff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index e56ef10f443..46fee30b6b9 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -699,6 +699,8 @@ compare_comment (const void *lp, const void *rp) static tree *to_dump = NULL; static int to_dump_count = 0; +static bool bitfield_used = false; +static bool packed_layout = false; /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped by a subsequent call to dump_ada_nodes. */ @@ -1825,7 +1827,7 @@ dump_ada_array_type (pretty_printer *buffer, tree node, int spc) pp_string (buffer, " of "); - if (TREE_CODE (tmp) != POINTER_TYPE) + if (TREE_CODE (tmp) != POINTER_TYPE && !packed_layout) pp_string (buffer, "aliased "); if (TYPE_NAME (tmp) @@ -2083,9 +2085,6 @@ is_float128 (tree node) || id_equal (name, "_Float128x"); } -static bool bitfield_used = false; -static bool packed_layout = false; - /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE can be referenced via a "limited with" clause. NAME_ONLY indicates whether
[gcc r15-625] Small fix to implementation of -fdump-ada-spec
https://gcc.gnu.org/g:6a0a46c57999d1f805f6c604a8868ae588a104f2 commit r15-625-g6a0a46c57999d1f805f6c604a8868ae588a104f2 Author: Eric Botcazou Date: Fri May 17 11:44:30 2024 +0200 Small fix to implementation of -fdump-ada-spec gcc/c-family/ * c-ada-spec.cc (bitfield_used): Move around. (packed_layout): Likewise. (dump_ada_array_type): Do not put "aliased" for a packed layout. Diff: --- gcc/c-family/c-ada-spec.cc | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index e56ef10f443a..46fee30b6b90 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -699,6 +699,8 @@ compare_comment (const void *lp, const void *rp) static tree *to_dump = NULL; static int to_dump_count = 0; +static bool bitfield_used = false; +static bool packed_layout = false; /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped by a subsequent call to dump_ada_nodes. */ @@ -1825,7 +1827,7 @@ dump_ada_array_type (pretty_printer *buffer, tree node, int spc) pp_string (buffer, " of "); - if (TREE_CODE (tmp) != POINTER_TYPE) + if (TREE_CODE (tmp) != POINTER_TYPE && !packed_layout) pp_string (buffer, "aliased "); if (TYPE_NAME (tmp) @@ -2083,9 +2085,6 @@ is_float128 (tree node) || id_equal (name, "_Float128x"); } -static bool bitfield_used = false; -static bool packed_layout = false; - /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE can be referenced via a "limited with" clause. NAME_ONLY indicates whether
[gcc r15-624] Remove spurious line
https://gcc.gnu.org/g:4da8be4f46b5dad4f5f610fc142538054446f44b commit r15-624-g4da8be4f46b5dad4f5f610fc142538054446f44b Author: Eric Botcazou Date: Wed May 8 11:20:40 2024 +0200 Remove spurious line Diff: --- gcc/ada/ChangeLog | 1 - 1 file changed, 1 deletion(-) diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2095166460ec..f0ec83e56d39 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1139,7 +1139,6 @@ 2024-05-06 Eric Botcazou * fe.h: Remove unused declarations and add 'extern' to others. - no-issue-check 2024-05-06 Piotr Trojanek
[wwwdocs] Document reimplementation of GNU threads library on Windows
... which happened in GCC 13. Validated with W3C's Validator and applied. -- Eric Botcazoudiff --git a/htdocs/gcc-13/changes.html b/htdocs/gcc-13/changes.html index e324b782..3ab4a101 100644 --- a/htdocs/gcc-13/changes.html +++ b/htdocs/gcc-13/changes.html @@ -770,8 +770,17 @@ You may also want to check out our - - +Windows + + The GNU threads library used by the win32 thread model has + been reimplemented using direct Win32 API calls, except for the Objective-C + specific subset. It requires Windows XP/Server 2003 or later. The new + implementation also adds the support needed for the C++11 threads, using + again direct Win32 API calls; this additional layer requires Windows + Vista/Server 2008 or later. It is recommended to use a recent version of + MinGW-W64 in conjunction with the win32 thread model. + +
gcc-wwwdocs branch master updated. ed9ceba9b8b038f0e0f333798da7abe046679d0c
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "gcc-wwwdocs". The branch, master has been updated via ed9ceba9b8b038f0e0f333798da7abe046679d0c (commit) from 8f193930f0beb38d06b143bcc1d5632f457e0cdf (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log - commit ed9ceba9b8b038f0e0f333798da7abe046679d0c Author: Eric Botcazou Date: Thu May 16 12:38:25 2024 +0200 Document reimplementation of GNU threads library on Windows (PR web/115105) diff --git a/htdocs/gcc-13/changes.html b/htdocs/gcc-13/changes.html index e324b782..3ab4a101 100644 --- a/htdocs/gcc-13/changes.html +++ b/htdocs/gcc-13/changes.html @@ -770,8 +770,17 @@ You may also want to check out our - - +Windows + + The GNU threads library used by the win32 thread model has + been reimplemented using direct Win32 API calls, except for the Objective-C + specific subset. It requires Windows XP/Server 2003 or later. The new + implementation also adds the support needed for the C++11 threads, using + again direct Win32 API calls; this additional layer requires Windows + Vista/Server 2008 or later. It is recommended to use a recent version of + MinGW-W64 in conjunction with the win32 thread model. + + --- Summary of changes: htdocs/gcc-13/changes.html | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) hooks/post-receive -- gcc-wwwdocs
[gcc r15-314] Minor tweaks to code computing modular multiplicative inverse
https://gcc.gnu.org/g:10e34aa5b1d23e1517f0ca5cfae3cac3b51a7a53 commit r15-314-g10e34aa5b1d23e1517f0ca5cfae3cac3b51a7a53 Author: Eric Botcazou Date: Mon Apr 29 17:46:20 2024 +0200 Minor tweaks to code computing modular multiplicative inverse This removes the last parameter of choose_multiplier, which is unused, adds another assertion and more details to the description and various comments. Likewise to the closely related invert_mod2n, except for the last parameter. [changelog] * expmed.h (choose_multiplier): Tweak description and remove last parameter. * expmed.cc (choose_multiplier): Likewise. Add assertion for the third parameter and adds details to various comments. (invert_mod2n): Tweak description and add assertion for the first parameter. (expand_divmod): Adjust calls to choose_multiplier. * tree-vect-generic.cc (expand_vector_divmod): Likewise. * tree-vect-patterns.cc (vect_recog_divmod_pattern): Likewise. Diff: --- gcc/expmed.cc | 95 ++- gcc/expmed.h | 9 +++-- gcc/tree-vect-generic.cc | 13 +++ gcc/tree-vect-patterns.cc | 14 +++ 4 files changed, 71 insertions(+), 60 deletions(-) diff --git a/gcc/expmed.cc b/gcc/expmed.cc index 20f3a36f38cc..248940fe4147 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -3695,50 +3695,62 @@ expand_widening_mult (machine_mode mode, rtx op0, rtx op1, rtx target, unsignedp, OPTAB_LIB_WIDEN); } -/* Choose a minimal N + 1 bit approximation to 1/D that can be used to - replace division by D, and put the least significant N bits of the result - in *MULTIPLIER_PTR and return the most significant bit. +/* Choose a minimal N + 1 bit approximation to 2**K / D that can be used to + replace division by D, put the least significant N bits of the result in + *MULTIPLIER_PTR, the value K - N in *POST_SHIFT_PTR, and return the most + significant bit. The width of operations is N (should be <= HOST_BITS_PER_WIDE_INT), the - needed precision is in PRECISION (should be <= N). + needed precision is PRECISION (should be <= N). - PRECISION should be as small as possible so this function can choose - multiplier more freely. + PRECISION should be as small as possible so this function can choose the + multiplier more freely. If PRECISION is <= N - 1, the most significant + bit returned by the function will be zero. - The rounded-up logarithm of D is placed in *lgup_ptr. A shift count that - is to be used for a final right shift is placed in *POST_SHIFT_PTR. - - Using this function, x/D will be equal to (x * m) >> (*POST_SHIFT_PTR), - where m is the full HOST_BITS_PER_WIDE_INT + 1 bit multiplier. */ + Using this function, x / D is equal to (x*m) / 2**N >> (*POST_SHIFT_PTR), + where m is the full N + 1 bit multiplier. */ unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision, unsigned HOST_WIDE_INT *multiplier_ptr, - int *post_shift_ptr, int *lgup_ptr) + int *post_shift_ptr) { int lgup, post_shift; - int pow, pow2; + int pow1, pow2; - /* lgup = ceil(log2(divisor)); */ + /* lgup = ceil(log2(d)) */ + /* Assuming d > 1, we have d >= 2^(lgup-1) + 1 */ lgup = ceil_log2 (d); gcc_assert (lgup <= n); + gcc_assert (lgup <= precision); - pow = n + lgup; + pow1 = n + lgup; pow2 = n + lgup - precision; - /* mlow = 2^(N + lgup)/d */ - wide_int val = wi::set_bit_in_zero (pow, HOST_BITS_PER_DOUBLE_INT); + /* mlow = 2^(n + lgup)/d */ + /* Trivially from above we have mlow < 2^(n+1) */ + wide_int val = wi::set_bit_in_zero (pow1, HOST_BITS_PER_DOUBLE_INT); wide_int mlow = wi::udiv_trunc (val, d); - /* mhigh = (2^(N + lgup) + 2^(N + lgup - precision))/d */ + /* mhigh = (2^(n + lgup) + 2^(n + lgup - precision))/d */ + /* From above we have mhigh < 2^(n+1) assuming lgup <= precision */ + /* From precision <= n, the difference between the numerators of mhigh and + mlow is >= 2^lgup >= d. Therefore the difference of the quotients in + the Euclidean division by d is at least 1, so we have mlow < mhigh and + the exact value of 2^(n + lgup)/d lies in the interval [mlow; mhigh). */ val |= wi::set_bit_in_zero (pow2, HOST_BITS_PER_DOUBLE_INT); wide_int mhigh = wi::udiv_trunc (val, d); - /* If precision == N, then mlow, mhigh exceed 2^N - (but they do not exceed 2^(N+1)). */ - /* Reduce to lowest terms. */ + /* If precision <= n - 1, then the difference between the numerators of + mhigh and mlow is >= 2^(lgup + 1) >= 2 * 2^lgup >= 2 * d. Therefore + the difference of the quotients in the Euclidean division by d is at + least 2, which means that mhigh and mlow di
[PATCH] Add widening expansion of MULT_HIGHPART_EXPR for integral modes
Hi, for integral modes, the expansion of MULT_HIGHPART_EXPR requires the presence of an {s,u}mul_highpart optab whereas, for vector modes, widening expansion is supported. This adds a widening expansion for integral modes too, which is in fact already implemented in expmed_mult_highpart_optab. We'll use that in a subsequent change to the Ada front-end to generate fast modulo reduction for modular types with nonbinary modulus (a little controversial Ada 95 feature). Tested on x86-64/Linux, OK for the mainline? 2024-04-29 Eric Botcazou * expmed.h (expmed_mult_highpart_optab): Declare. * expmed.cc (expmed_mult_highpart_optab): Remove static keyword. Do not assume that OP1 is a constant integer. Fix pasto. (expmed_mult_highpart): Pass OP1 narrowed to MODE in all the calls to expmed_mult_highpart_optab. * optabs-query.cc (can_mult_highpart_p): Use 2 for integer widening and shift subsequent values accordingly. * optabs.cc (expand_mult_highpart): Call expmed_mult_highpart_optab when can_mult_highpart_p returns 2 and adjust to above change. -- Eric Botcazoudiff --git a/gcc/expmed.cc b/gcc/expmed.cc index 60f65c7acc5..ccc671e922d 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -2742,8 +2742,7 @@ static rtx expand_mult_const (machine_mode, rtx, HOST_WIDE_INT, rtx, static unsigned HOST_WIDE_INT invert_mod2n (unsigned HOST_WIDE_INT, int); static rtx extract_high_half (scalar_int_mode, rtx); static rtx expmed_mult_highpart (scalar_int_mode, rtx, rtx, rtx, int, int); -static rtx expmed_mult_highpart_optab (scalar_int_mode, rtx, rtx, rtx, - int, int); + /* Compute and return the best algorithm for multiplying by T. The algorithm must cost less than cost_limit If retval.cost >= COST_LIMIT, no algorithm was found and all @@ -3850,30 +3849,25 @@ extract_high_half (scalar_int_mode mode, rtx op) return convert_modes (mode, wider_mode, op, 0); } -/* Like expmed_mult_highpart, but only consider using a multiplication - optab. OP1 is an rtx for the constant operand. */ +/* Like expmed_mult_highpart, but only consider using multiplication optab. */ -static rtx +rtx expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1, rtx target, int unsignedp, int max_cost) { - rtx narrow_op1 = gen_int_mode (INTVAL (op1), mode); + const scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (mode).require (); + const bool speed = optimize_insn_for_speed_p (); + const int size = GET_MODE_BITSIZE (mode); optab moptab; rtx tem; - int size; - bool speed = optimize_insn_for_speed_p (); - - scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (mode).require (); - - size = GET_MODE_BITSIZE (mode); /* Firstly, try using a multiplication insn that only generates the needed high part of the product, and in the sign flavor of unsignedp. */ if (mul_highpart_cost (speed, mode) < max_cost) { moptab = unsignedp ? umul_highpart_optab : smul_highpart_optab; - tem = expand_binop (mode, moptab, op0, narrow_op1, target, - unsignedp, OPTAB_DIRECT); + tem = expand_binop (mode, moptab, op0, op1, target, unsignedp, + OPTAB_DIRECT); if (tem) return tem; } @@ -3886,12 +3880,12 @@ expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1, + 4 * add_cost (speed, mode) < max_cost)) { moptab = unsignedp ? smul_highpart_optab : umul_highpart_optab; - tem = expand_binop (mode, moptab, op0, narrow_op1, target, - unsignedp, OPTAB_DIRECT); + tem = expand_binop (mode, moptab, op0, op1, target, !unsignedp, + OPTAB_DIRECT); if (tem) /* We used the wrong signedness. Adjust the result. */ - return expand_mult_highpart_adjust (mode, tem, op0, narrow_op1, - tem, unsignedp); + return expand_mult_highpart_adjust (mode, tem, op0, op1, tem, + unsignedp); } /* Try widening multiplication. */ @@ -3899,8 +3893,8 @@ expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1, if (convert_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing && mul_widen_cost (speed, wider_mode) < max_cost) { - tem = expand_binop (wider_mode, moptab, op0, narrow_op1, 0, - unsignedp, OPTAB_WIDEN); + tem = expand_binop (wider_mode, moptab, op0, op1, NULL_RTX, unsignedp, + OPTAB_WIDEN); if (tem) return extract_high_half (mode, tem); } @@ -3941,14 +3935,14 @@ expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1, + 2 * shift_cost (speed, mode, size-1) + 4 * add_cost (speed, mode) < max_cost)) { - tem = expand_binop (wider_mode, moptab, op0, narrow_op1, - NULL_RTX, ! unsignedp, OPTAB_WIDEN); + tem = expand_binop (wider_mode, moptab, op0, op1, NULL_RTX, !unsignedp, + OPTAB_WIDEN); if (tem != 0) { tem = extract_high_half (mode, tem); /* We used the wrong signedness. Adjust the
Re: [PATCH] Minor tweaks to code computing modular multiplicative inverse
> OK. Consider waiting to commit though as we want to make it easy to > cherry pick patches over to the release branch if needed. Sure. There are a couple more changes on top of it, but all can wait a bit. -- Eric Botcazou
[PATCH] Minor tweaks to code computing modular multiplicative inverse
Hi, this removes the last parameter of choose_multiplier, which is unused, adds another assertion and more details to the description and various comments. Likewise to the closely related invert_mod2n, except for the last parameter. Tested on x86-64/Linux, OK for the mainline? 2024-04-29 Eric Botcazou * expmed.h (choose_multiplier): Tweak description and remove last parameter. * expmed.cc (choose_multiplier): Likewise. Add assertion for the third parameter and adds details to various comments. (invert_mod2n): Tweak description and add assertion for the first parameter. (expand_divmod): Adjust calls to choose_multiplier. * tree-vect-generic.cc (expand_vector_divmod): Likewise. * tree-vect-patterns.cc (vect_recog_divmod_pattern): Likewise. -- Eric Botcazoudiff --git a/gcc/expmed.cc b/gcc/expmed.cc index 4ec035e4843..60f65c7acc5 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -3689,50 +3689,62 @@ expand_widening_mult (machine_mode mode, rtx op0, rtx op1, rtx target, unsignedp, OPTAB_LIB_WIDEN); } -/* Choose a minimal N + 1 bit approximation to 1/D that can be used to - replace division by D, and put the least significant N bits of the result - in *MULTIPLIER_PTR and return the most significant bit. +/* Choose a minimal N + 1 bit approximation to 2**K / D that can be used to + replace division by D, put the least significant N bits of the result in + *MULTIPLIER_PTR, the value K - N in *POST_SHIFT_PTR, and return the most + significant bit. The width of operations is N (should be <= HOST_BITS_PER_WIDE_INT), the - needed precision is in PRECISION (should be <= N). + needed precision is PRECISION (should be <= N). - PRECISION should be as small as possible so this function can choose - multiplier more freely. + PRECISION should be as small as possible so this function can choose the + multiplier more freely. If PRECISION is <= N - 1, the most significant + bit returned by the function will be zero. - The rounded-up logarithm of D is placed in *lgup_ptr. A shift count that - is to be used for a final right shift is placed in *POST_SHIFT_PTR. - - Using this function, x/D will be equal to (x * m) >> (*POST_SHIFT_PTR), - where m is the full HOST_BITS_PER_WIDE_INT + 1 bit multiplier. */ + Using this function, x / D is equal to (x*m) / 2**N >> (*POST_SHIFT_PTR), + where m is the full N + 1 bit multiplier. */ unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision, unsigned HOST_WIDE_INT *multiplier_ptr, - int *post_shift_ptr, int *lgup_ptr) + int *post_shift_ptr) { int lgup, post_shift; - int pow, pow2; + int pow1, pow2; - /* lgup = ceil(log2(divisor)); */ + /* lgup = ceil(log2(d)) */ + /* Assuming d > 1, we have d >= 2^(lgup-1) + 1 */ lgup = ceil_log2 (d); gcc_assert (lgup <= n); + gcc_assert (lgup <= precision); - pow = n + lgup; + pow1 = n + lgup; pow2 = n + lgup - precision; - /* mlow = 2^(N + lgup)/d */ - wide_int val = wi::set_bit_in_zero (pow, HOST_BITS_PER_DOUBLE_INT); + /* mlow = 2^(n + lgup)/d */ + /* Trivially from above we have mlow < 2^(n+1) */ + wide_int val = wi::set_bit_in_zero (pow1, HOST_BITS_PER_DOUBLE_INT); wide_int mlow = wi::udiv_trunc (val, d); - /* mhigh = (2^(N + lgup) + 2^(N + lgup - precision))/d */ + /* mhigh = (2^(n + lgup) + 2^(n + lgup - precision))/d */ + /* From above we have mhigh < 2^(n+1) assuming lgup <= precision */ + /* From precision <= n, the difference between the numerators of mhigh and + mlow is >= 2^lgup >= d. Therefore the difference of the quotients in + the Euclidean division by d is at least 1, so we have mlow < mhigh and + the exact value of 2^(n + lgup)/d lies in the interval [mlow; mhigh(. */ val |= wi::set_bit_in_zero (pow2, HOST_BITS_PER_DOUBLE_INT); wide_int mhigh = wi::udiv_trunc (val, d); - /* If precision == N, then mlow, mhigh exceed 2^N - (but they do not exceed 2^(N+1)). */ - /* Reduce to lowest terms. */ + /* If precision <= n - 1, then the difference between the numerators of + mhigh and mlow is >= 2^(lgup + 1) >= 2 * 2^lgup >= 2 * d. Therefore + the difference of the quotients in the Euclidean division by d is at + least 2, which means that mhigh and mlow differ by at least one bit + not in the last place. The conclusion is that the first iteration of + the loop below completes and shifts mhigh and mlow by 1 bit, which in + particular means that mhigh < 2^n, that is to say, the most significant + bit in the n + 1 bit value is zero. */ for (post_shift = lgup; post_shift > 0; post_shift--) { unsigned HOST_WIDE_INT ml_lo = wi::extract_uhwi (mlow, 1, @@ -3747,7 +3759,7 @@ choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision, } *post_shift
Re: [SPARC] Fix PR target/114416
> For the 20th anniversary of https://gcc.gnu.org/gcc-3.4/sparc-abi.html, a > new calling convention incompatibility with the vendor compiler (and the > ABI) has been discovered in 64-bit mode, affecting small structures > containing arrays of floating-point components. The decision has been made > to fix it on Solaris only at this point. Documented by the attached patch, validated with W3C's Validator and applied. -- Eric Botcazoudiff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html index f0f0efe0..83b1016c 100644 --- a/htdocs/gcc-14/changes.html +++ b/htdocs/gcc-14/changes.html @@ -136,7 +136,7 @@ a work-in-progress. int foo (int n) { int res = 0; - for (int i = 0; i < n; i++) + for (int i = 0; i n; i++) { y[i] = x[i] * 2; res += x[i] + y[i]; @@ -1212,7 +1212,17 @@ __asm (".global __flmap_lock" "\n\t" - +SPARC + + + +The implementation of calling conventions for small structures containing +arrays of floating-point components has been changed in 64-bit mode for +the Solaris port to match the implementation of the vendor compiler (and +the ABI). As a result, the code generated will not be binary compatible +with earlier releases in these cases. + +
gcc-wwwdocs branch master updated. 688a21c3093f0d3dbf7248066b5c9c00802bdf89
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "gcc-wwwdocs". The branch, master has been updated via 688a21c3093f0d3dbf7248066b5c9c00802bdf89 (commit) from 215f3f4f7d8ad162a9a3f5e48b475d82ee4cfb3d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log - commit 688a21c3093f0d3dbf7248066b5c9c00802bdf89 Author: Eric Botcazou Date: Thu Apr 25 19:37:27 2024 +0200 gcc-14/changes.html: Add SPARC section and fix syntax error diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html index f0f0efe0..83b1016c 100644 --- a/htdocs/gcc-14/changes.html +++ b/htdocs/gcc-14/changes.html @@ -136,7 +136,7 @@ a work-in-progress. int foo (int n) { int res = 0; - for (int i = 0; i < n; i++) + for (int i = 0; i n; i++) { y[i] = x[i] * 2; res += x[i] + y[i]; @@ -1212,7 +1212,17 @@ __asm (".global __flmap_lock" "\n\t" - +SPARC + + + +The implementation of calling conventions for small structures containing +arrays of floating-point components has been changed in 64-bit mode for +the Solaris port to match the implementation of the vendor compiler (and +the ABI). As a result, the code generated will not be binary compatible +with earlier releases in these cases. + + --- Summary of changes: htdocs/gcc-14/changes.html | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) hooks/post-receive -- gcc-wwwdocs
[SPARC] Fix PR target/114416
For the 20th anniversary of https://gcc.gnu.org/gcc-3.4/sparc-abi.html, a new calling convention incompatibility with the vendor compiler (and the ABI) has been discovered in 64-bit mode, affecting small structures containing arrays of floating-point components. The decision has been made to fix it on Solaris only at this point. Bootstrapped/regtested on SPARC/Solaris 11.4 and SPARC64/Linux by Rainer (many thanks again) and applied on the mainline. 2024-04-25 Eric Botcazou PR target/114416 * config/sparc/sparc.h (SUN_V9_ABI_COMPATIBILITY): New macro. * config/sparc/sol2.h (SUN_V9_ABI_COMPATIBILITY): Redefine it. * config/sparc/sparc.cc (fp_type_for_abi): New predicate. (traverse_record_type): Use it to spot floating-point types. (compute_fp_layout): Also deal with array types. 2024-04-25 Eric Botcazou * gcc.target/sparc/small-struct-1.c: New test. -- Eric Botcazoudiff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h index e849af9038b..552f58b2cc8 100644 --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -456,3 +456,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #undef SPARC_LOW_FE_EXCEPT_VALUES #define SPARC_LOW_FE_EXCEPT_VALUES 1 + +#undef SUN_V9_ABI_COMPATIBILITY +#define SUN_V9_ABI_COMPATIBILITY 1 diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc index 30fa4474bbd..8a5f76c8885 100644 --- a/gcc/config/sparc/sparc.cc +++ b/gcc/config/sparc/sparc.cc @@ -6782,6 +6782,22 @@ sparc_pass_by_reference (cumulative_args_t, const function_arg_info ) || GET_MODE_SIZE (mode) > 16); } +/* Return true if TYPE is considered as a floating-point type by the ABI. */ + +static bool +fp_type_for_abi (const_tree type) +{ + /* This is the original GCC implementation. */ + if (FLOAT_TYPE_P (type) || VECTOR_TYPE_P (type)) +return true; + + /* This has been introduced in GCC 14 to match the vendor compiler. */ + if (SUN_V9_ABI_COMPATIBILITY && TREE_CODE (type) == ARRAY_TYPE) +return fp_type_for_abi (TREE_TYPE (type)); + + return false; +} + /* Traverse the record TYPE recursively and call FUNC on its fields. NAMED is true if this is for a named parameter. DATA is passed to FUNC for each field. OFFSET is the starting position and @@ -6820,8 +6836,7 @@ traverse_record_type (const_tree type, bool named, T *data, packed); else { - const bool fp_type - = FLOAT_TYPE_P (field_type) || VECTOR_TYPE_P (field_type); + const bool fp_type = fp_type_for_abi (field_type); Func (field, bitpos, fp_type && named && !packed && TARGET_FPU, data); } @@ -7072,6 +7087,13 @@ compute_fp_layout (const_tree field, int bitpos, assign_data_t *data, mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field))); nregs = 2; } + else if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE) +{ + tree elt_type = strip_array_types (TREE_TYPE (field)); + mode = TYPE_MODE (elt_type); + nregs + = int_size_in_bytes (TREE_TYPE (field)) / int_size_in_bytes (elt_type); +} else nregs = 1; diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index fb074808d30..232ecb30ddc 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1700,3 +1700,6 @@ extern int sparc_indent_opcode; #define SPARC_LOW_FE_EXCEPT_VALUES 0 #define TARGET_SUPPORTS_WIDE_INT 1 + +/* Define this to 1 to accept ABI changes to match the vendor compiler. */ +#define SUN_V9_ABI_COMPATIBILITY 0 /* PR target/114416 */ /* Reported by Rainer Orth */ /* { dg-do compile } */ /* { dg-options "-O" } */ /* { dg-require-effective-target lp64 } */ struct vec2 { double x[2]; }; struct vec2x { double x; double y; }; struct vec2 sum2 (double val) { struct vec2 v; v.x[0] = val; v.x[1] = val; return v; } struct vec2x sum2x (double val) { struct vec2x v; v.x = val; v.y = val; return v; } double get2 (struct vec2 v) { return v.x[0] + v.x[1]; } double get2x (struct vec2x v) { return v.x + v.y; } /* { dg-final { scan-assembler-not "ldx" } } */ /* { dg-final { scan-assembler-not "stx" } } */
[gcc r14-10119] Fix calling convention incompatibility with vendor compiler
https://gcc.gnu.org/g:1d238c84025aaef1641e4000bd2a8f4328b474dd commit r14-10119-g1d238c84025aaef1641e4000bd2a8f4328b474dd Author: Eric Botcazou Date: Thu Apr 25 12:44:14 2024 +0200 Fix calling convention incompatibility with vendor compiler For the 20th anniversary of https://gcc.gnu.org/gcc-3.4/sparc-abi.html, a new calling convention incompatibility with the vendor compiler (and the ABI) has been discovered in 64-bit mode, affecting small structures containing arrays of floating-point components. The decision has been made to fix it on Solaris only at this point. gcc/ PR target/114416 * config/sparc/sparc.h (SUN_V9_ABI_COMPATIBILITY): New macro. * config/sparc/sol2.h (SUN_V9_ABI_COMPATIBILITY): Redefine it. * config/sparc/sparc.cc (fp_type_for_abi): New predicate. (traverse_record_type): Use it to spot floating-point types. (compute_fp_layout): Also deal with array types. gcc/testsuite/ * gcc.target/sparc/small-struct-1.c: New test. * gcc.target/sparc/pr105573.c: Rename to... * gcc.target/sparc/20230425-1.c: ...this. * gcc.target/sparc/pr109541.c: Rename to... * gcc.target/sparc/20230607-1.c: ...this Diff: --- gcc/config/sparc/sol2.h| 3 ++ gcc/config/sparc/sparc.cc | 26 +++- gcc/config/sparc/sparc.h | 3 ++ .../gcc.target/sparc/{pr105573.c => 20230425-1.c} | 3 ++ .../gcc.target/sparc/{pr109541.c => 20230607-1.c} | 3 ++ gcc/testsuite/gcc.target/sparc/small-struct-1.c| 46 ++ 6 files changed, 82 insertions(+), 2 deletions(-) diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h index e849af9038b..552f58b2cc8 100644 --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -456,3 +456,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #undef SPARC_LOW_FE_EXCEPT_VALUES #define SPARC_LOW_FE_EXCEPT_VALUES 1 + +#undef SUN_V9_ABI_COMPATIBILITY +#define SUN_V9_ABI_COMPATIBILITY 1 diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc index 30fa4474bbd..8a5f76c8885 100644 --- a/gcc/config/sparc/sparc.cc +++ b/gcc/config/sparc/sparc.cc @@ -6782,6 +6782,22 @@ sparc_pass_by_reference (cumulative_args_t, const function_arg_info ) || GET_MODE_SIZE (mode) > 16); } +/* Return true if TYPE is considered as a floating-point type by the ABI. */ + +static bool +fp_type_for_abi (const_tree type) +{ + /* This is the original GCC implementation. */ + if (FLOAT_TYPE_P (type) || VECTOR_TYPE_P (type)) +return true; + + /* This has been introduced in GCC 14 to match the vendor compiler. */ + if (SUN_V9_ABI_COMPATIBILITY && TREE_CODE (type) == ARRAY_TYPE) +return fp_type_for_abi (TREE_TYPE (type)); + + return false; +} + /* Traverse the record TYPE recursively and call FUNC on its fields. NAMED is true if this is for a named parameter. DATA is passed to FUNC for each field. OFFSET is the starting position and @@ -6820,8 +6836,7 @@ traverse_record_type (const_tree type, bool named, T *data, packed); else { - const bool fp_type - = FLOAT_TYPE_P (field_type) || VECTOR_TYPE_P (field_type); + const bool fp_type = fp_type_for_abi (field_type); Func (field, bitpos, fp_type && named && !packed && TARGET_FPU, data); } @@ -7072,6 +7087,13 @@ compute_fp_layout (const_tree field, int bitpos, assign_data_t *data, mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field))); nregs = 2; } + else if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE) +{ + tree elt_type = strip_array_types (TREE_TYPE (field)); + mode = TYPE_MODE (elt_type); + nregs + = int_size_in_bytes (TREE_TYPE (field)) / int_size_in_bytes (elt_type); +} else nregs = 1; diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index fb074808d30..232ecb30ddc 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1700,3 +1700,6 @@ extern int sparc_indent_opcode; #define SPARC_LOW_FE_EXCEPT_VALUES 0 #define TARGET_SUPPORTS_WIDE_INT 1 + +/* Define this to 1 to accept ABI changes to match the vendor compiler. */ +#define SUN_V9_ABI_COMPATIBILITY 0 diff --git a/gcc/testsuite/gcc.target/sparc/pr105573.c b/gcc/testsuite/gcc.target/sparc/20230425-1.c similarity index 82% rename from gcc/testsuite/gcc.target/sparc/pr105573.c rename to gcc/testsuite/gcc.target/sparc/20230425-1.c index 14043a5fdad..c07dd3261fc 100644 --- a/gcc/testsuite/gcc.target/sparc/pr105573.c +++ b/gcc/testsuite/gcc.target/sparc/20230425-1.c @@ -1,3 +1,6 @@ +/* PR target/105573 */ +/* Reported by Sam James */ + /* { dg-do compile } */ /* { dg-options "-O3 -mvis3"
[gcc r13-8436] ada: Fix error message for Aggregate aspect
https://gcc.gnu.org/g:618db8d5ecd6d113d3089fda6fbf8bf472ddfc25 commit r13-8436-g618db8d5ecd6d113d3089fda6fbf8bf472ddfc25 Author: Marc Poulhiès Date: Wed Mar 8 20:39:45 2023 +0100 ada: Fix error message for Aggregate aspect The error message was wrongly using % instead of & in the format string, causing the displayed message to refer to incorrect names in some cases. gcc/ada/ * sem_ch13.adb (Check_Aspect_At_Freeze_Point): fix format string, use existing local Ident. Diff: --- gcc/ada/sem_ch13.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 073e8f9b0d8..550f10366f2 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -11147,8 +11147,8 @@ package body Sem_Ch13 is when Aspect_Aggregate => if Is_Array_Type (Entity (ASN)) then Error_Msg_N - ("aspect% can only be applied to non-array type", - Identifier (ASN)); + ("aspect& can only be applied to non-array type", + Ident); end if; Resolve_Aspect_Aggregate (Entity (ASN), Expression (ASN)); return;
[gcc r13-8435] ada: Fix (again) incorrect handling of Aggregate aspect
https://gcc.gnu.org/g:6c8e7aa2ce1d51050c59c1492be2a29890d2c172 commit r13-8435-g6c8e7aa2ce1d51050c59c1492be2a29890d2c172 Author: Marc Poulhiès Date: Mon Mar 6 12:15:13 2023 +0100 ada: Fix (again) incorrect handling of Aggregate aspect Previous fix stopped the processing of the Aggregate aspect early, skipping the call to Record_Rep_Item, making later call to Resolve_Container_Aggregate fail. Also, the previous fix would not handle correctly the case where the type is private and the check for non-array type can only be done at the freeze point with the full type. Adapt the resolving of the aspect when the input is not correct and the parameters can't be resolved. gcc/ada/ * sem_ch13.adb (Analyze_One_Aspect): Call Record_Rep_Item. (Check_Aspect_At_Freeze_Point): Check the aspect is specified on non-array type only... (Analyze_One_Aspect): ... instead of doing it too early here. * sem_aggr.adb (Resolve_Container_Aggregate): Do nothing in case the parameters failed to resolve. Diff: --- gcc/ada/sem_aggr.adb | 9 +++-- gcc/ada/sem_ch13.adb | 12 +++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb index 3ebb30d64ed..8d8a26329b5 100644 --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -3157,6 +3157,7 @@ package body Sem_Aggr is if Present (Add_Unnamed_Subp) and then No (New_Indexed_Subp) +and then Etype (Add_Unnamed_Subp) /= Any_Type then declare Elmt_Type : constant Entity_Id := @@ -3200,7 +3201,9 @@ package body Sem_Aggr is end if; end; - elsif Present (Add_Named_Subp) then + elsif Present (Add_Named_Subp) +and then Etype (Add_Named_Subp) /= Any_Type + then declare -- Retrieves types of container, key, and element from the -- specified insertion procedure. @@ -3242,7 +3245,9 @@ package body Sem_Aggr is end loop; end; - elsif Present (Assign_Indexed_Subp) then + elsif Present (Assign_Indexed_Subp) +and then Etype (Assign_Indexed_Subp) /= Any_Type + then -- Indexed Aggregate. Positional or indexed component -- can be present, but not both. Choices must be static -- values or ranges with static bounds. diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 317c4841d87..073e8f9b0d8 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -4211,11 +4211,8 @@ package body Sem_Ch13 is Aitem := Empty; when Aspect_Aggregate => - if Is_Array_Type (E) then - Error_Msg_N - ("aspect% can only be applied to non-array type", Id); - goto Continue; - end if; + -- We will be checking that the aspect is not specified on a + -- non-array type in Check_Aspect_At_Freeze_Point Validate_Aspect_Aggregate (Expr); Record_Rep_Item (E, Aspect); @@ -11148,6 +11145,11 @@ package body Sem_Ch13 is return; when Aspect_Aggregate => +if Is_Array_Type (Entity (ASN)) then + Error_Msg_N + ("aspect% can only be applied to non-array type", + Identifier (ASN)); +end if; Resolve_Aspect_Aggregate (Entity (ASN), Expression (ASN)); return;
[gcc r13-8434] ada: Fix incorrect handling of Aggregate aspect
https://gcc.gnu.org/g:bc97504e021fd8719fa6d9e31c311b38e87a3900 commit r13-8434-gbc97504e021fd8719fa6d9e31c311b38e87a3900 Author: Marc Poulhiès Date: Tue Feb 28 17:10:29 2023 +0100 ada: Fix incorrect handling of Aggregate aspect This change fixes 2 incorrect handlings of the aspect. The arguments are now correctly resolved and the aspect is rejected on non array types. gcc/ada/ * sem_ch13.adb (Analyze_One_Aspect): Mark Aggregate aspect as needing delayed resolution and reject the aspect on non-array type. Diff: --- gcc/ada/sem_ch13.adb | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index b81b6b02e1d..317c4841d87 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -2921,10 +2921,10 @@ package body Sem_Ch13 is end case; if Delay_Required - and then (A_Id = Aspect_Stable_Properties or else A_Id = Aspect_Designated_Storage_Model - or else A_Id = Aspect_Storage_Model_Type) + or else A_Id = Aspect_Storage_Model_Type + or else A_Id = Aspect_Aggregate) -- ??? It seems like we should do this for all aspects, not -- just these, but that causes as-yet-undiagnosed regressions. @@ -4211,6 +4211,12 @@ package body Sem_Ch13 is Aitem := Empty; when Aspect_Aggregate => + if Is_Array_Type (E) then + Error_Msg_N + ("aspect% can only be applied to non-array type", Id); + goto Continue; + end if; + Validate_Aspect_Aggregate (Expr); Record_Rep_Item (E, Aspect); goto Continue;
Re: [PATCH] Fix PR ipa/113996
> Patch is still OK, but ipa-ICF will only identify the functions if > static chain is unused. Perhaps just picking the winning candidate to be > version without static chain and making ipa-inline to not ICE when calls > with static chain lands to function with no static chain would help us > to optimize better. I see, thanks for the explanation. The attached patch appears to work. PR ipa/113996 * ipa-icf.h (sem_function): Add static_chain_p member. * ipa-icf.cc (sem_function::init): Initialize it. (sem_item_optimizer::merge_classes): If the class is made of functions, pick one without static chain as the target. -- Eric Botcazoudiff --git a/gcc/ipa-icf.cc b/gcc/ipa-icf.cc index 5d5a42f9c6c..4fc02831798 100644 --- a/gcc/ipa-icf.cc +++ b/gcc/ipa-icf.cc @@ -1368,6 +1368,8 @@ sem_function::init (ipa_icf_gimple::func_checker *checker) /* iterating all function arguments. */ arg_count = count_formal_params (fndecl); + static_chain_p = func->static_chain_decl != NULL_TREE; + edge_count = n_edges_for_fn (func); cgraph_node *cnode = dyn_cast (node); if (!cnode->thunk) @@ -3399,11 +3401,22 @@ sem_item_optimizer::merge_classes (unsigned int prev_class_count, sem_item *source = c->members[0]; - if (DECL_NAME (source->decl) - && MAIN_NAME_P (DECL_NAME (source->decl))) - /* If merge via wrappers, picking main as the target can be - problematic. */ - source = c->members[1]; + if (source->type == FUNC) + { + /* Pick a member without static chain, if any. */ + for (unsigned int j = 0; j < c->members.length (); j++) + if (!static_cast (c->members[j])->static_chain_p) + { + source = c->members[j]; + break; + } + + /* If merge via wrappers, picking main as the target can be + problematic. */ + if (DECL_NAME (source->decl) + && MAIN_NAME_P (DECL_NAME (source->decl))) + source = c->members[source == c->members[0] ? 1 : 0]; + } for (unsigned int j = 0; j < c->members.length (); j++) { diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h index ef7e41bfa88..da20862c306 100644 --- a/gcc/ipa-icf.h +++ b/gcc/ipa-icf.h @@ -355,6 +355,9 @@ public: parameters. */ bool compatible_parm_types_p (tree, tree); + /* Return true if parameter I may be used. */ + bool param_used_p (unsigned int i); + /* Exception handling region tree. */ eh_region region_tree; @@ -379,6 +382,9 @@ public: /* Total number of SSA names used in the function. */ unsigned ssa_names_size; + /* Whether the special PARM_DECL for the static chain is present. */ + bool static_chain_p; + /* Array of structures for all basic blocks. */ vec bb_sorted; @@ -386,9 +392,6 @@ public: function. */ hashval_t m_alias_sets_hash; - /* Return true if parameter I may be used. */ - bool param_used_p (unsigned int i); - private: /* Calculates hash value based on a BASIC_BLOCK. */ hashval_t get_bb_hash (const ipa_icf_gimple::sem_bb *basic_block);
[PATCH] Fix PR ipa/113996
Hi, this is a regression present on all active branches: the attached Ada testcase triggers an assertion failure when compiled with -O2 -gnatp -flto: /* Initialize the static chain. */ p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl; gcc_assert (fn != current_function_decl); if (p) { /* No static chain? Seems like a bug in tree-nested.cc. */ gcc_assert (static_chain); <--- here setup_one_parameter (id, p, static_chain, fn, bb, ); } The problem is that the ICF pass identifies two functions, one of which has a static chain but the other does not. The proposed fix is just to prevent this identification from occurring. Tested on x86-64/Linux, OK for all active branches? 2024-03-11 Eric Botcazou PR ipa/113996 * ipa-icf.h (sem_function): Add static_chain_present member. * ipa-icf.cc (sem_function::get_hash): Hash it. (sem_function::equals_wpa): Compare it. (sem_function::equals_private): Likewise. (sem_function::init): Initialize it. 2024-03-11 Eric Botcazou * gnat.dg/lto27.adb: New test. -- Eric Botcazou-- { dg-do link } -- { dg-options "-O2 -gnatp -flto" { target lto } } with Ada.Containers.Hashed_Maps; with Ada.Strings.Hash; procedure Lto27 is subtype Node_Name is String (1 .. 4); package Node_Maps is new Ada.Containers.Hashed_Maps (Key_Type=> Node_Name, Element_Type=> Integer, Hash=> Ada.Strings.Hash, Equivalent_Keys => "="); begin null; end; diff --git a/gcc/ipa-icf.cc b/gcc/ipa-icf.cc index 5d5a42f9c6c..dff7ad6efda 100644 --- a/gcc/ipa-icf.cc +++ b/gcc/ipa-icf.cc @@ -284,6 +284,7 @@ sem_function::get_hash (void) hstate.add_int (177454); /* Random number for function type. */ hstate.add_int (arg_count); + hstate.add_int (static_chain_present); hstate.add_int (cfg_checksum); hstate.add_int (gcode_hash); @@ -655,7 +656,10 @@ sem_function::equals_wpa (sem_item *item, } if (list1 || list2) -return return_false_with_msg ("Mismatched number of parameters"); +return return_false_with_msg ("mismatched number of parameters"); + + if (static_chain_present != m_compared_func->static_chain_present) +return return_false_with_msg ("static chain mismatch"); if (node->num_references () != item->node->num_references ()) return return_false_with_msg ("different number of references"); @@ -876,7 +880,10 @@ sem_function::equals_private (sem_item *item) return return_false (); } if (arg1 || arg2) -return return_false_with_msg ("Mismatched number of arguments"); +return return_false_with_msg ("mismatched number of arguments"); + + if (static_chain_present != m_compared_func->static_chain_present) +return return_false_with_msg ("static chain mismatch"); if (!dyn_cast (node)->has_gimple_body_p ()) return true; @@ -1368,6 +1375,8 @@ sem_function::init (ipa_icf_gimple::func_checker *checker) /* iterating all function arguments. */ arg_count = count_formal_params (fndecl); + static_chain_present = func->static_chain_decl != NULL_TREE; + edge_count = n_edges_for_fn (func); cgraph_node *cnode = dyn_cast (node); if (!cnode->thunk) diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h index ef7e41bfa88..bd9fd9fb294 100644 --- a/gcc/ipa-icf.h +++ b/gcc/ipa-icf.h @@ -355,6 +355,9 @@ public: parameters. */ bool compatible_parm_types_p (tree, tree); + /* Return true if parameter I may be used. */ + bool param_used_p (unsigned int i); + /* Exception handling region tree. */ eh_region region_tree; @@ -379,6 +382,9 @@ public: /* Total number of SSA names used in the function. */ unsigned ssa_names_size; + /* Whether the special PARM_DECL for the static chain is present. */ + bool static_chain_present; + /* Array of structures for all basic blocks. */ vec bb_sorted; @@ -386,9 +392,6 @@ public: function. */ hashval_t m_alias_sets_hash; - /* Return true if parameter I may be used. */ - bool param_used_p (unsigned int i); - private: /* Calculates hash value based on a BASIC_BLOCK. */ hashval_t get_bb_hash (const ipa_icf_gimple::sem_bb *basic_block);
Fix PR debug/113519 and debug/113777
They both come from an oversight of mine in the placement of the DIE created for an enumeration type with reverse scalar storage order. Tested on x86-64/Linux, both GCC and GDB, applied on mainline as obvious. 2024-03-11 Eric Botcazou PR debug/113519 PR debug/113777 * dwarf2out.cc (gen_enumeration_type_die): In the reverse case, generate the DIE with the same parent as in the regular case. 2024-03-11 Eric Botcazou * gcc.dg/sso-20.c: New test. * gcc.dg/sso-21.c: Likewise. -- Eric Botcazoudiff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 03d73f9eecd..9b1548e4ae3 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -22868,18 +22868,19 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die, bool reverse) if (type_die == NULL || reverse) { + dw_die_ref scope_die = scope_die_for (type, context_die); + /* The DIE with DW_AT_endianity is placed right after the naked DIE. */ if (reverse) { gcc_assert (type_die); dw_die_ref after_die = type_die; type_die = new_die_raw (DW_TAG_enumeration_type); - add_child_die_after (context_die, type_die, after_die); + add_child_die_after (scope_die, type_die, after_die); } else { - type_die = new_die (DW_TAG_enumeration_type, - scope_die_for (type, context_die), type); + type_die = new_die (DW_TAG_enumeration_type, scope_die, type); equate_type_number_to_die (type, type_die); } add_name_attribute (type_die, type_tag (type)); /* PR debug/113519 */ /* Reported by Zdenek Sojka */ /* { dg-do compile } */ /* { dg-options "-g -fdebug-types-section" } */ enum E { X }; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ struct __attribute__((scalar_storage_order("big-endian"))) { enum E e; } S; #else struct __attribute__((scalar_storage_order("little-endian"))) { enum E e; } S; #endif /* PR debug/113777 */ /* Reported by Zdenek Sojka */ /* { dg-do compile } */ /* { dg-options "-g" } */ typedef short __attribute__((__hardbool__)) hbool; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ struct __attribute__((scalar_storage_order("big-endian"))) { hbool a[2]; } S; #else struct __attribute__((scalar_storage_order("little-endian"))) { hbool a[2]; } S; #endif
[gcc r14-9423] Fix placement of recently implemented DIE
https://gcc.gnu.org/g:0c4df2c3c38ca15c123e9a801b617e63256c83a3 commit r14-9423-g0c4df2c3c38ca15c123e9a801b617e63256c83a3 Author: Eric Botcazou Date: Mon Mar 11 09:24:50 2024 +0100 Fix placement of recently implemented DIE It's the DIE added for enumeration types with reverse scalar storage order. gcc/ PR debug/113519 PR debug/113777 * dwarf2out.cc (gen_enumeration_type_die): In the reverse case, generate the DIE with the same parent as in the regular case. gcc/testsuite/ * gcc.dg/sso-20.c: New test. * gcc.dg/sso-21.c: Likewise. Diff: --- gcc/dwarf2out.cc | 7 --- gcc/testsuite/gcc.dg/sso-20.c | 19 +++ gcc/testsuite/gcc.dg/sso-21.c | 19 +++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 87e4240b871..8f18bc4fe64 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -22868,18 +22868,19 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die, bool reverse) if (type_die == NULL || reverse) { + dw_die_ref scope_die = scope_die_for (type, context_die); + /* The DIE with DW_AT_endianity is placed right after the naked DIE. */ if (reverse) { gcc_assert (type_die); dw_die_ref after_die = type_die; type_die = new_die_raw (DW_TAG_enumeration_type); - add_child_die_after (context_die, type_die, after_die); + add_child_die_after (scope_die, type_die, after_die); } else { - type_die = new_die (DW_TAG_enumeration_type, - scope_die_for (type, context_die), type); + type_die = new_die (DW_TAG_enumeration_type, scope_die, type); equate_type_number_to_die (type, type_die); } add_name_attribute (type_die, type_tag (type)); diff --git a/gcc/testsuite/gcc.dg/sso-20.c b/gcc/testsuite/gcc.dg/sso-20.c new file mode 100644 index 000..3bea38423a8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sso-20.c @@ -0,0 +1,19 @@ +/* PR debug/113519 */ +/* Reported by Zdenek Sojka */ + +/* { dg-do compile } */ +/* { dg-options "-g -fdebug-types-section" } */ + +enum E { X }; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +struct __attribute__((scalar_storage_order("big-endian"))) +{ + enum E e; +} S; +#else +struct __attribute__((scalar_storage_order("little-endian"))) +{ + enum E e; +} S; +#endif diff --git a/gcc/testsuite/gcc.dg/sso-21.c b/gcc/testsuite/gcc.dg/sso-21.c new file mode 100644 index 000..4b5d76d479b --- /dev/null +++ b/gcc/testsuite/gcc.dg/sso-21.c @@ -0,0 +1,19 @@ +/* PR debug/113777 */ +/* Reported by Zdenek Sojka */ + +/* { dg-do compile } */ +/* { dg-options "-g" } */ + +typedef short __attribute__((__hardbool__)) hbool; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +struct __attribute__((scalar_storage_order("big-endian"))) +{ + hbool a[2]; +} S; +#else +struct __attribute__((scalar_storage_order("little-endian"))) +{ + hbool a[2]; +} S; +#endif
[Ada] Fix PR ada/113979
This is a regression present on all active branches: the compiler gives a bogus error on an allocator for an unconstrained array type declared with a Dynamic_Predicate because Apply_Predicate_Check is invoked directly on a subtype reference, which it cannot handle. This moves the check to the resulting access value (after dereference) like in Expand_Allocator_Expression. Tested on x86-64/Linux, applied on all active branches. 2024-03-07 Eric Botcazou PR ada/113979 * exp_ch4.adb (Expand_N_Allocator): In the subtype indication case, call Apply_Predicate_Check on the resulting access value if needed. 2024-03-07 Eric Botcazou * testsuite/gnat.dg/predicate15.adb: New test. -- Eric Botcazoudiff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 4f83cd4737a..e4a40414872 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4657,8 +4657,6 @@ package body Exp_Ch4 is if Is_Array_Type (Dtyp) and then not No_Initialization (N) then Apply_Constraint_Check (Expression (N), Dtyp, No_Sliding => True); -Apply_Predicate_Check (Expression (N), Dtyp); - if Nkind (Expression (N)) = N_Raise_Constraint_Error then Rewrite (N, New_Copy (Expression (N))); Set_Etype (N, PtrT); @@ -4752,6 +4750,8 @@ package body Exp_Ch4 is Rewrite (N, New_Occurrence_Of (Temp, Loc)); Analyze_And_Resolve (N, PtrT); +Apply_Predicate_Check (N, Dtyp, Deref => True); + -- Case of no initialization procedure present elsif not Has_Non_Null_Base_Init_Proc (T) then @@ -5119,6 +5119,8 @@ package body Exp_Ch4 is Rewrite (N, New_Occurrence_Of (Temp, Loc)); Analyze_And_Resolve (N, PtrT); + Apply_Predicate_Check (N, Dtyp, Deref => True); + -- When designated type has Default_Initial_Condition aspects, -- make a call to the type's DIC procedure to perform the -- checks. Theoretically this might also be needed for cases -- { dg-do compile } -- { dg-options "-gnata" } procedure Predicate15 is type Grid is array (Positive range <>) of Integer with Dynamic_Predicate => Grid'First = 1; type Grid_Ptr is access Grid; Data : Grid_Ptr := new Grid (1 .. 10); begin null; end;
[gcc r11-11272] Fix bogus error on allocator for array type with Dynamic_Predicate
https://gcc.gnu.org/g:b26501b6e310345ad9f6423b3f8b9df178c5e7d9 commit r11-11272-gb26501b6e310345ad9f6423b3f8b9df178c5e7d9 Author: Eric Botcazou Date: Thu Mar 7 15:05:54 2024 +0100 Fix bogus error on allocator for array type with Dynamic_Predicate This is a regression present on all active branches: the compiler gives a bogus error on an allocator for an unconstrained array type declared with a Dynamic_Predicate because Apply_Predicate_Check is invoked directly on a subtype reference, which it cannot handle. This moves the check to the resulting access value (after dereference) like in Expand_Allocator_Expression. gcc/ada/ PR ada/113979 * exp_ch4.adb (Expand_N_Allocator): In the subtype indication case, remove call to Apply_Predicate_Check. gcc/testsuite/ * gnat.dg/predicate15.adb: New test. Diff: --- gcc/ada/exp_ch4.adb | 2 -- gcc/testsuite/gnat.dg/predicate15.adb | 15 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 44370786a3d..48dae8396d0 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4970,8 +4970,6 @@ package body Exp_Ch4 is if Is_Array_Type (Dtyp) and then not No_Initialization (N) then Apply_Constraint_Check (Expression (N), Dtyp, No_Sliding => True); -Apply_Predicate_Check (Expression (N), Dtyp); - if Nkind (Expression (N)) = N_Raise_Constraint_Error then Rewrite (N, New_Copy (Expression (N))); Set_Etype (N, PtrT); diff --git a/gcc/testsuite/gnat.dg/predicate15.adb b/gcc/testsuite/gnat.dg/predicate15.adb new file mode 100644 index 000..cf9e1d9e17f --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate15.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +procedure Predicate15 is + + type Grid is array (Positive range <>) of Integer with + Dynamic_Predicate => Grid'First = 1; + + type Grid_Ptr is access Grid; + + Data : Grid_Ptr := new Grid (1 .. 10); + +begin + null; +end;
[gcc r12-10197] Fix bogus error on allocator for array type with Dynamic_Predicate
https://gcc.gnu.org/g:f9e1d7aa8b4f0b8afff1de59fcadf1db0244b4e1 commit r12-10197-gf9e1d7aa8b4f0b8afff1de59fcadf1db0244b4e1 Author: Eric Botcazou Date: Thu Mar 7 15:05:54 2024 +0100 Fix bogus error on allocator for array type with Dynamic_Predicate This is a regression present on all active branches: the compiler gives a bogus error on an allocator for an unconstrained array type declared with a Dynamic_Predicate because Apply_Predicate_Check is invoked directly on a subtype reference, which it cannot handle. This moves the check to the resulting access value (after dereference) like in Expand_Allocator_Expression. gcc/ada/ PR ada/113979 * exp_ch4.adb (Expand_N_Allocator): In the subtype indication case, remove call to Apply_Predicate_Check. gcc/testsuite/ * gnat.dg/predicate15.adb: New test. Diff: --- gcc/ada/exp_ch4.adb | 2 -- gcc/testsuite/gnat.dg/predicate15.adb | 15 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 2506c67e936..6429c6e9d69 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4823,8 +4823,6 @@ package body Exp_Ch4 is if Is_Array_Type (Dtyp) and then not No_Initialization (N) then Apply_Constraint_Check (Expression (N), Dtyp, No_Sliding => True); -Apply_Predicate_Check (Expression (N), Dtyp); - if Nkind (Expression (N)) = N_Raise_Constraint_Error then Rewrite (N, New_Copy (Expression (N))); Set_Etype (N, PtrT); diff --git a/gcc/testsuite/gnat.dg/predicate15.adb b/gcc/testsuite/gnat.dg/predicate15.adb new file mode 100644 index 000..cf9e1d9e17f --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate15.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +procedure Predicate15 is + + type Grid is array (Positive range <>) of Integer with + Dynamic_Predicate => Grid'First = 1; + + type Grid_Ptr is access Grid; + + Data : Grid_Ptr := new Grid (1 .. 10); + +begin + null; +end;
[gcc r13-8409] Fix bogus error on allocator for array type with Dynamic_Predicate
https://gcc.gnu.org/g:0e591e6f27a20c26672ea8c0550a6ef673c1fccf commit r13-8409-g0e591e6f27a20c26672ea8c0550a6ef673c1fccf Author: Eric Botcazou Date: Thu Mar 7 15:05:54 2024 +0100 Fix bogus error on allocator for array type with Dynamic_Predicate This is a regression present on all active branches: the compiler gives a bogus error on an allocator for an unconstrained array type declared with a Dynamic_Predicate because Apply_Predicate_Check is invoked directly on a subtype reference, which it cannot handle. This moves the check to the resulting access value (after dereference) like in Expand_Allocator_Expression. gcc/ada/ PR ada/113979 * exp_ch4.adb (Expand_N_Allocator): In the subtype indication case, remove call to Apply_Predicate_Check. gcc/testsuite/ * gnat.dg/predicate15.adb: New test. Diff: --- gcc/ada/exp_ch4.adb | 2 -- gcc/testsuite/gnat.dg/predicate15.adb | 15 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 8442de6f90c..5cb6ee25702 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4785,8 +4785,6 @@ package body Exp_Ch4 is if Is_Array_Type (Dtyp) and then not No_Initialization (N) then Apply_Constraint_Check (Expression (N), Dtyp, No_Sliding => True); -Apply_Predicate_Check (Expression (N), Dtyp); - if Nkind (Expression (N)) = N_Raise_Constraint_Error then Rewrite (N, New_Copy (Expression (N))); Set_Etype (N, PtrT); diff --git a/gcc/testsuite/gnat.dg/predicate15.adb b/gcc/testsuite/gnat.dg/predicate15.adb new file mode 100644 index 000..cf9e1d9e17f --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate15.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +procedure Predicate15 is + + type Grid is array (Positive range <>) of Integer with + Dynamic_Predicate => Grid'First = 1; + + type Grid_Ptr is access Grid; + + Data : Grid_Ptr := new Grid (1 .. 10); + +begin + null; +end;
[gcc r14-9361] Fix bogus error on allocator for array type with Dynamic_Predicate
https://gcc.gnu.org/g:e71a4e81729516eed8782a255ff37617e6fd4b69 commit r14-9361-ge71a4e81729516eed8782a255ff37617e6fd4b69 Author: Eric Botcazou Date: Thu Mar 7 15:05:54 2024 +0100 Fix bogus error on allocator for array type with Dynamic_Predicate This is a regression present on all active branches: the compiler gives a bogus error on an allocator for an unconstrained array type declared with a Dynamic_Predicate because Apply_Predicate_Check is invoked directly on a subtype reference, which it cannot handle. This moves the check to the resulting access value (after dereference) like in Expand_Allocator_Expression. gcc/ada/ PR ada/113979 * exp_ch4.adb (Expand_N_Allocator): In the subtype indication case, call Apply_Predicate_Check on the resulting access value if needed. gcc/testsuite/ * gnat.dg/predicate15.adb: New test. Diff: --- gcc/ada/exp_ch4.adb | 6 -- gcc/testsuite/gnat.dg/predicate15.adb | 15 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 4f83cd4737a..e4a40414872 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4657,8 +4657,6 @@ package body Exp_Ch4 is if Is_Array_Type (Dtyp) and then not No_Initialization (N) then Apply_Constraint_Check (Expression (N), Dtyp, No_Sliding => True); -Apply_Predicate_Check (Expression (N), Dtyp); - if Nkind (Expression (N)) = N_Raise_Constraint_Error then Rewrite (N, New_Copy (Expression (N))); Set_Etype (N, PtrT); @@ -4752,6 +4750,8 @@ package body Exp_Ch4 is Rewrite (N, New_Occurrence_Of (Temp, Loc)); Analyze_And_Resolve (N, PtrT); +Apply_Predicate_Check (N, Dtyp, Deref => True); + -- Case of no initialization procedure present elsif not Has_Non_Null_Base_Init_Proc (T) then @@ -5119,6 +5119,8 @@ package body Exp_Ch4 is Rewrite (N, New_Occurrence_Of (Temp, Loc)); Analyze_And_Resolve (N, PtrT); + Apply_Predicate_Check (N, Dtyp, Deref => True); + -- When designated type has Default_Initial_Condition aspects, -- make a call to the type's DIC procedure to perform the -- checks. Theoretically this might also be needed for cases diff --git a/gcc/testsuite/gnat.dg/predicate15.adb b/gcc/testsuite/gnat.dg/predicate15.adb new file mode 100644 index 000..cf9e1d9e17f --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate15.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +procedure Predicate15 is + + type Grid is array (Positive range <>) of Integer with + Dynamic_Predicate => Grid'First = 1; + + type Grid_Ptr is access Grid; + + Data : Grid_Ptr := new Grid (1 .. 10); + +begin + null; +end;
[PATCH] Fix internal error in GIMPLE DSE
Hi, this is a regression present on the mainline, 13 and 12 branches. For the attached Ada case, it's a tree checking failure on the mainline at -O: +===GNAT BUG DETECTED==+ | 14.0.1 20240226 (experimental) [master r14-9171-g4972f97a265] GCC error:| | tree check: expected tree that contains 'decl common' structure, | | have 'component_ref' in tree_could_trap_p, at tree-eh.cc:2733| | Error detected around /home/eric/cvs/gcc/gcc/testsuite/gnat.dg/opt104.adb: Time is a 10-byte record and Packed_Rec.T is placed at bit-offset 65 because of the packing. so tree-ssa-dse.cc:setup_live_bytes_from_ref has computed a const_size of 88 from ref->offset of 65 and ref->max_size of 80. Then in tree-ssa-dse.cc:compute_trims: 411 int last_live = bitmap_last_set_bit (live); (gdb) next 412 if (ref->size.is_constant (_size)) (gdb) 414 int last_orig = (const_size / BITS_PER_UNIT) - 1; (gdb) 418 *trim_tail = last_orig - last_live; (gdb) call debug_bitmap (live) n_bits = 256, set = {0 1 2 3 4 5 6 7 8 9 10 } (gdb) p last_live $33 = 10 (gdb) p const_size $34 = 80 (gdb) p last_orig $35 = 9 (gdb) p *trim_tail $36 = -1 In other words, compute_trims is overlooking the alignment adjustments applied earlier by setup_live_bytes_from_ref. Moveover it reads: /* We use sbitmaps biased such that ref->offset is bit zero and the bitmap extends through ref->size. So we know that in the original bitmap bits 0..ref->size were true. We don't actually need the bitmap, just the REF to compute the trims. */ But setup_live_bytes_from_ref used ref->max_size instead of ref->size. It appears that all the callers of compute_trims assume that ref->offset is byte aligned and that the trimmed bytes are relative to ref->size, so the patch simply adds an early return if either condition is not fulfilled Tested on x86-64/Linux, OK for all the affected branches? 2024-02-27 Eric Botcazou * tree-ssa-dse.cc (compute_trims): Fix description. Return early if ref->offset is not byte aligned or ref->size is not known to be equal to ref->max_size. (maybe_trim_complex_store): Fix description. (maybe_trim_constructor_store): Likewise. (maybe_trim_partially_dead_store): Likewise. 2024-02-27 Eric Botcazou * gnat.dg/opt104.ads, gnat.dg/opt104.adb! New test. -- Eric Botcazoudiff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc index 81b65125409..5869010287c 100644 --- a/gcc/tree-ssa-dse.cc +++ b/gcc/tree-ssa-dse.cc @@ -403,11 +403,11 @@ setup_live_bytes_from_ref (ao_ref *ref, sbitmap live_bytes) return false; } -/* Compute the number of elements that we can trim from the head and - tail of ORIG resulting in a bitmap that is a superset of LIVE. +/* Compute the number of stored bytes that we can trim from the head and + tail of REF. LIVE is the bitmap of stores to REF that are still live. - Store the number of elements trimmed from the head and tail in - TRIM_HEAD and TRIM_TAIL. + Store the number of bytes trimmed from the head and tail in TRIM_HEAD + and TRIM_TAIL respectively. STMT is the statement being trimmed and is used for debugging dump output only. */ @@ -416,10 +416,16 @@ static void compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail, gimple *stmt) { - /* We use sbitmaps biased such that ref->offset is bit zero and the bitmap - extends through ref->size. So we know that in the original bitmap - bits 0..ref->size were true. We don't actually need the bitmap, just - the REF to compute the trims. */ + *trim_head = 0; + *trim_tail = 0; + + /* We use bitmaps biased such that ref->offset is contained in bit zero and + the bitmap extends through ref->max_size and we know that in the original + bitmap bits 0 .. ref->max_size were true. But we need to check that this + covers exactly the bytes of REF. */ + const unsigned int align = known_alignment (ref->offset); + if ((align && align < BITS_PER_UNIT) || !known_eq (ref->size, ref->max_size)) +return; /* Now identify how much, if any of the tail we can chop off. */ HOST_WIDE_INT const_size; @@ -444,8 +450,6 @@ compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail, last_orig) <= 0) *trim_tail = 0; } - else -*trim_tail = 0; /* Identify how much, if any of the head we can chop off. */ int first_orig = 0; @@ -503,8 +507,7 @@ compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail, } } - if ((*trim_head || *trim_tail) - && dump_file && (dump_flags & TDF_DETAILS)) + if ((*trim_head || *trim_tail) && dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, " Trimming statement (
[Ada] Fix PR ada/113893
The finalization of objects dynamically allocated through an anonymous access type is deferred to the enclosing library unit in the current implementation and a warning is given on each of them. However this cannot be done if the designated type is local, because this would generate dangling references to the local finalization routine, so the finalization needs to be dropped in this case and the warning adjusted. Tested on x86-64/Linux, applied on all active branches. 2024-02-26 Eric Botcazou PR ada/113893 * exp_ch7.adb (Build_Anonymous_Master): Do not build the master for a local designated type. * exp_util.adb (Build_Allocate_Deallocate_Proc): Force Needs_Fin to false if no finalization master is attached to an access type and assert that it is anonymous in this case. * sem_res.adb (Resolve_Allocator): Mention that the object might not be finalized at all in the warning given when the type is an anonymous access-to-controlled type. 2024-02-26 Eric Botcazou * gnat.dg/access10.adb: New test. -- Eric Botcazoudiff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 2ac73101351..e594a534244 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -749,6 +749,7 @@ package body Exp_Ch7 is Desig_Typ : Entity_Id; FM_Id : Entity_Id; Priv_View : Entity_Id; + Scop : Entity_Id; Unit_Decl : Node_Id; Unit_Id : Entity_Id; @@ -787,6 +788,18 @@ package body Exp_Ch7 is Desig_Typ := Priv_View; end if; + -- For a designated type not declared at library level, we cannot create + -- a finalization collection attached to an outer unit since this would + -- generate dangling references to the dynamic scope through access-to- + -- procedure values designating the local Finalize_Address primitive. + + Scop := Enclosing_Dynamic_Scope (Desig_Typ); + if Scop /= Standard_Standard +and then Scope_Depth (Scop) > Scope_Depth (Unit_Id) + then + return; + end if; + -- Determine whether the current semantic unit already has an anonymous -- master which services the designated type. diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 31cd47de7d2..04d114694ab 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -936,6 +936,16 @@ package body Exp_Util is Needs_Finalization (Desig_Typ) and then not No_Heap_Finalization (Ptr_Typ); + -- The allocation/deallocation of a controlled object must be associated + -- with an attachment to/detachment from a finalization master, but the + -- implementation cannot guarantee this property for every anonymous + -- access tyoe, see Build_Anonymous_Collection. + + if Needs_Fin and then No (Finalization_Master (Ptr_Typ)) then + pragma Assert (Ekind (Ptr_Typ) = E_Anonymous_Access_Type); + Needs_Fin := False; + end if; + if Needs_Fin then -- Do nothing if the access type may never allocate / deallocate @@ -945,11 +955,6 @@ package body Exp_Util is return; end if; - -- The allocation / deallocation of a controlled object must be - -- chained on / detached from a finalization master. - - pragma Assert (Present (Finalization_Master (Ptr_Typ))); - -- The only other kind of allocation / deallocation supported by this -- routine is on / from a subpool. diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 8e9714c1c86..075c0d85ccd 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -5679,19 +5679,19 @@ package body Sem_Res is Set_Is_Dynamic_Coextension (N, False); Set_Is_Static_Coextension (N, False); - -- Anonymous access-to-controlled objects are not finalized on - -- time because this involves run-time ownership and currently - -- this property is not available. In rare cases the object may - -- not be finalized at all. Warn on potential issues involving - -- anonymous access-to-controlled objects. + -- Objects allocated through anonymous access types are not + -- finalized on time because this involves run-time ownership + -- and currently this property is not available. In rare cases + -- the object might not be finalized at all. Warn on potential + -- issues involving anonymous access-to-controlled types. if Ekind (Typ) = E_Anonymous_Access_Type and then Is_Controlled_Active (Desig_T) then Error_Msg_N -("??object designated by anonymous access object might " +("??object designated by anonymous access value might " &
[c-family] Fix PR ada/113397
It is a regression on the mainline for -fdump-ada-spec in a pathological case. Tested on x86-64/Linux, applied on the mainline. 2024-01-16 Eric Botcazou PR ada/113397 * c-ada-spec.cc (check_type_name_conflict): Add guard for the presence of DECL_NAME on a TYPE_DECL. -- Eric Botcazoudiff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index 7d886c0f92e..4b245ed6975 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -1566,6 +1566,8 @@ check_type_name_conflict (pretty_printer *buffer, tree t) s = ""; else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE) s = IDENTIFIER_POINTER (TYPE_NAME (tmp)); + else if (!DECL_NAME (TYPE_NAME (tmp))) + s = ""; else s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
Re: HELP: Questions on unshare_expr
> Okay, so, the "unsharing everything” is done automatically by the compiler > before gimplification? See the blurb at gimplify.cc:835 and below about this. -- Eric Botcazou
Re: [PATCH] Fix debug info for enumeration types with reverse Scalar_Storage_Order
> Can you elaborate on the DIE order constraint and why it was chosen? That > is, > > + /* The DIE with DW_AT_endianity is placed right after the naked DIE. > */ + if (reverse) > + { > + gcc_assert (type_die); > ... > > and > > + /* The DIE with DW_AT_endianity is placed right after the naked DIE. > */ + if (reverse_type) > + { > + dw_die_ref after_die > + = modified_type_die (type, cv_quals, false, context_die); > + gen_type_die (type, context_die, true); > + gcc_assert (after_die->die_sib > + && get_AT_unsigned (after_die->die_sib, > DW_AT_endianity)); + return after_die->die_sib; > > ? That's preexisting though, see line 13730 where there is a small blurb. The crux of the matter is that there is no scalar *_TYPE node with a reverse SSO, so there is nothing to equate with for the DIE carrying DW_AT_endianity, unlike for type variants (the reverse SSO is on the enclosing aggregate type instead but this does not match the way DWARF describes it). Therefore, in order to avoid building a new DIE with DW_AT_endianity each time, the DIE with DW_AT_endianity is placed right after the naked DIE, so that the lookup done at line 13730 for reverse SSO is immediate. > Likewise the extra argument to the functions is odd - is that not available > on the tree type? No, for the reason described above, so the extra parameter is preexisting for base_type_die, modified_type_die and add_type_attribute. -- Eric Botcazou
[PATCH] Fix debug info for enumeration types with reverse Scalar_Storage_Order
Hi, this is not really a regression but the patch was written last week and is quite straightforward, so hopefully can nevertheless be OK. It implements the support of DW_AT_endianity for enumeration types because they are scalar and, therefore, reverse Scalar_Storage_Order is supported for them, but only when the -gstrict-dwarf switch is not passed because this is an extension. There is an associated GDB patch to be submitted by Tom to grok the new DWARF. Tested on x86-64/Linux, OK for the mainline? It may also help the GDB side to backport it for the upcoming 13.3 release. 2024-01-09 Eric Botcazou * dwarf2out.cc (modified_type_die): Extend the support of reverse storage order to enumeration types if -gstrict-dwarf is not passed. (gen_enumeration_type_die): Add REVERSE parameter and generate the DIE immediately after the existing one if it is true. (gen_tagged_type_die): Add REVERSE parameter and pass it in the call to gen_enumeration_type_die. (gen_type_die_with_usage): Add REVERSE parameter and pass it in the first recursive call as well as the call to gen_tagged_type_die. (gen_type_die): Add REVERSE parameter and pass it in the call to gen_type_die_with_usage. -- Eric Botcazoudiff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 2f9010bc3cb..1c994bb8b9b 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -3940,7 +3940,7 @@ static void gen_descr_array_type_die (tree, struct array_descr_info *, dw_die_re #if 0 static void gen_entry_point_die (tree, dw_die_ref); #endif -static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref); +static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref, bool); static dw_die_ref gen_formal_parameter_die (tree, tree, bool, dw_die_ref); static dw_die_ref gen_formal_parameter_pack_die (tree, tree, dw_die_ref, tree*); static void gen_unspecified_parameters_die (tree, dw_die_ref); @@ -3960,7 +3960,7 @@ static void gen_struct_or_union_type_die (tree, dw_die_ref, enum debug_info_usage); static void gen_subroutine_type_die (tree, dw_die_ref); static void gen_typedef_die (tree, dw_die_ref); -static void gen_type_die (tree, dw_die_ref); +static void gen_type_die (tree, dw_die_ref, bool = false); static void gen_block_die (tree, dw_die_ref); static void decls_for_scope (tree, dw_die_ref, bool = true); static bool is_naming_typedef_decl (const_tree); @@ -3976,8 +3976,10 @@ static struct dwarf_file_data * lookup_filename (const char *); static void retry_incomplete_types (void); static void gen_type_die_for_member (tree, tree, dw_die_ref); static void gen_generic_params_dies (tree); -static void gen_tagged_type_die (tree, dw_die_ref, enum debug_info_usage); -static void gen_type_die_with_usage (tree, dw_die_ref, enum debug_info_usage); +static void gen_tagged_type_die (tree, dw_die_ref, enum debug_info_usage, + bool = false); +static void gen_type_die_with_usage (tree, dw_die_ref, enum debug_info_usage, + bool = false); static void splice_child_die (dw_die_ref, dw_die_ref); static int file_info_cmp (const void *, const void *); static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, var_loc_view, @@ -13665,8 +13667,11 @@ modified_type_die (tree type, int cv_quals, bool reverse, const int cv_qual_mask = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC | ENCODE_QUAL_ADDR_SPACE(~0U)); - const bool reverse_base_type -= need_endianity_attribute_p (reverse) && is_base_type (type); + /* DW_AT_endianity is specified only for base types in the standard. */ + const bool reverse_type += need_endianity_attribute_p (reverse) + && (is_base_type (type) + || (TREE_CODE (type) == ENUMERAL_TYPE && !dwarf_strict)); if (code == ERROR_MARK) return NULL; @@ -13726,9 +13731,9 @@ modified_type_die (tree type, int cv_quals, bool reverse, /* DW_AT_endianity doesn't come from a qualifier on the type, so it is dealt with specially: the DIE with the attribute, if it exists, is - placed immediately after the regular DIE for the same base type. */ + placed immediately after the regular DIE for the same type. */ if (mod_type_die - && (!reverse_base_type + && (!reverse_type || ((mod_type_die = mod_type_die->die_sib) != NULL && get_AT_unsigned (mod_type_die, DW_AT_endianity return mod_type_die; @@ -13745,7 +13750,7 @@ modified_type_die (tree type, int cv_quals, bool reverse, tree dtype = TREE_TYPE (name); /* Skip the typedef for base types with DW_AT_endianity, no big deal. */ - if (qualified_type == dtype && !reverse_base_type) + if (qualified_type == dtype && !reverse_type) { tree origin = decl_ultimate_origin (name); @@ -13952,7 +13957,7 @@ modified_type_die (tree type, int cv_quals, bool reverse, mod_type_die = base_type_die (type,
[Ada] Fix PR ada/112781 (2/2)
The problem occurs when this function call is the expression of a return in a function returning the limited interface; in this peculiar case, there is a mismatch between the callee, which has BIP formals but is not a BIP call, and the caller, which is a BIP function, that is spotted by an assertion. This is fixed by restoring the semantics of Is_Build_In_Place_Function_Call, which returns again true only for calls to BIP functions, introducing the Is_Function_Call_With_BIP_Formals predicate, which also returns true for calls to functions with BIP formals that are not BIP functions, and moving down the assertion in Expand_Simple_Function_Return. Tested on SPARC64/Linux, applied on the mainline and 13 branch. 2024-01-09 Eric Botcazou PR ada/112781 * exp_ch6.ads (Is_Build_In_Place_Function): Adjust description. * exp_ch6.adb (Is_True_Build_In_Place_Function_Call): Delete. (Is_Function_Call_With_BIP_Formals): New predicate. (Is_Build_In_Place_Function_Call): Restore original semantics. (Expand_Call_Helper): Adjust conditions guarding the calls to Add_Dummy_Build_In_Place_Actuals to above renaming. (Expand_N_Extended_Return_Statement): Adjust to above renaming. (Expand_Simple_Function_Return): Likewise. Move the assertion to after the transformation into an extended return statement. (Make_Build_In_Place_Call_In_Allocator): Remove unreachable code. (Make_Build_In_Place_Call_In_Assignment): Likewise. 2024-01-09 Eric Botcazou * gnat.dg/bip_prim_func2.adb: New test. * gnat.dg/bip_prim_func2_pkg.ads, gnat.dg/bip_prim_func2_pkg.adb: New helper package. -- Eric Botcazoudiff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 8e4c9035b22..939d3be57c3 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -316,11 +316,10 @@ package body Exp_Ch6 is -- Insert the Post_Call list previously produced by routine Expand_Actuals -- or Expand_Call_Helper into the tree. - function Is_True_Build_In_Place_Function_Call (N : Node_Id) return Boolean; + function Is_Function_Call_With_BIP_Formals (N : Node_Id) return Boolean; -- Ada 2005 (AI-318-02): Returns True if N denotes a call to a function - -- that requires handling as a build-in-place call; returns False for - -- non-BIP function calls and also for calls to functions with inherited - -- BIP formals that do not require BIP formals. For example: + -- that requires handling as a build-in-place call, that is, BIP function + -- calls and calls to functions with inherited BIP formals. For example: -- --type Iface is limited interface; --function Get_Object return Iface; @@ -330,15 +329,14 @@ package body Exp_Ch6 is --type T1 is new Root1 and Iface with ... --function Get_Object return T1; ---- This primitive requires the BIP formals, and the evaluation of - ---- Is_True_Build_In_Place_Function_Call returns True. + ---- Is_Build_In_Place_Function_Call returns True. -- --type Root2 is tagged record ... --type T2 is new Root2 and Iface with ... --function Get_Object return T2; ---- This primitive inherits the BIP formals of the interface primitive ---- but, given that T2 is not a limited type, it does not require such - ---- formals; therefore Is_True_Build_In_Place_Function_Call returns - ---- False. + ---- formals; therefore Is_Build_In_Place_Function_Call returns False. procedure Replace_Renaming_Declaration_Id (New_Decl : Node_Id; @@ -4906,8 +4904,8 @@ package body Exp_Ch6 is -- inherited the BIP extra actuals but does not require them. if Nkind (Call_Node) = N_Function_Call - and then Is_Build_In_Place_Function_Call (Call_Node) - and then not Is_True_Build_In_Place_Function_Call (Call_Node) + and then Is_Function_Call_With_BIP_Formals (Call_Node) + and then not Is_Build_In_Place_Function_Call (Call_Node) then Add_Dummy_Build_In_Place_Actuals (Subp, Num_Added_Extra_Actuals => Num_Extra_Actuals); @@ -4918,8 +4916,8 @@ package body Exp_Ch6 is -- inherited the BIP extra actuals but does not require them. elsif Nkind (Call_Node) = N_Function_Call -and then Is_Build_In_Place_Function_Call (Call_Node) -and then not Is_True_Build_In_Place_Function_Call (Call_Node) +and then Is_Function_Call_With_BIP_Formals (Call_Node) +and then not Is_Build_In_Place_Function_Call (Call_Node) then Add_Dummy_Build_In_Place_Actuals (Subp); end if; @@ -5614,7 +5612,7 @@ package body Exp_Ch6 is pragma Assert (Ekind (Current_Subprogram) = E_Function); pragma Assert (Is_Build_In_Place_Function (Current_Subprog
[Ada] Fix PR ada/112781 (1/2)
This is a regression present on the mainline and 13 branch, in the form of a series of internal errors (3) on a function call returning the extension of a limited interface. This is only a partial fix for the first two assertion failures triggered by this case; the third one is the most problematic and will be dealt with separately. The first issue is in Instantiate_Type, where we use Base_Type in a specific case to compute the ancestor of a derived type, which will later trigger the assertion on line 16960 of sem_ch3.adb since Parent_Base and Generic_Actual are the same node. This is changed to use Etype like in other cases around. The second issue is an unprotected use of Designated_Type on type T in Analyze_Explicit_Dereference, while another use in an equivalent context is guarded by Is_Access_Type a few lines above. Tested on SPARC64/Linux, applied on the mainline and 13 branch. 2024-01-09 Eric Botcazou PR ada/112781 * sem_ch12.adb (Instantiate_Type): Use Etype instead of Base_Type consistently to retrieve the ancestor for a derived type. * sem_ch4.adb (Analyze_Explicit_Dereference): Test Is_Access_Type consistently before accessing Designated_Type. -- Eric Botcazoudiff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index bfb400f5642..d2285082f97 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -13522,8 +13522,7 @@ package body Sem_Ch12 is Ancestor := Get_Instance_Of (Ancestor); else - Ancestor := - Get_Instance_Of (Base_Type (Get_Instance_Of (A_Gen_T))); + Ancestor := Get_Instance_Of (Etype (Get_Instance_Of (A_Gen_T))); end if; -- Check whether parent is a previous formal of the current generic diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 64aa9a84e60..85ae282dc37 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -2304,7 +2304,9 @@ package body Sem_Ch4 is while Present (It.Nam) loop T := It.Typ; - if No (First_Formal (Base_Type (Designated_Type (T then + if Is_Access_Type (T) + and then No (First_Formal (Base_Type (Designated_Type (T + then Set_Etype (P, T); else Remove_Interp (I);
[Ada] Fix PR ada/113195
This is a small regression present on the mainline and 13 branch, in the form of an internal error in gigi on anonymous access type equality. We now need to also accept them too for anonymous access types that point to compatible object subtypes in the language sense. Tested on SPARC64/Linux, applied on the mainline and 13 branch. 2024-01-09 Eric Botcazou PR ada/113195 * gcc-interface/utils2.cc (build_binary_op) : Relax assertion for regular pointer types. 2024-01-09 Eric Botcazou * gnat.dg/specs/anon4.ads: New test. -- Eric Botcazou-- { dg-do compile } package Anon4 is subtype I is Integer; A : access I; Acc : access Integer; function F return Boolean is (A = Acc); end Anon4; diff --git a/gcc/ada/gcc-interface/utils2.cc b/gcc/ada/gcc-interface/utils2.cc index 6a951093ff8..df11eef2101 100644 --- a/gcc/ada/gcc-interface/utils2.cc +++ b/gcc/ada/gcc-interface/utils2.cc @@ -1142,14 +1142,10 @@ build_binary_op (enum tree_code op_code, tree result_type, tree left_ref_type = TREE_TYPE (left_base_type); tree right_ref_type = TREE_TYPE (right_base_type); - /* Anonymous access types in Ada 2005 can point to different - members of a tagged hierarchy or different function types. */ - gcc_assert (TYPE_MAIN_VARIANT (left_ref_type) - == TYPE_MAIN_VARIANT (right_ref_type) - || (TYPE_ALIGN_OK (left_ref_type) - && TYPE_ALIGN_OK (right_ref_type)) - || (TREE_CODE (left_ref_type) == FUNCTION_TYPE - && TREE_CODE (right_ref_type) == FUNCTION_TYPE)); + /* Anonymous access types in Ada 2005 may point to compatible + object subtypes or function types in the language sense. */ + gcc_assert (FUNCTION_POINTER_TYPE_P (left_ref_type) + == FUNCTION_POINTER_TYPE_P (right_ref_type)); best_type = left_base_type; }
Fix PR rtl-optimization/113140
This is a small regression present on the mainline and 13 branch, although the underlying problem has probably been there for ages, in the form of a segfault during the delay slot scheduling pass, for a function that falls through to exit without any RTL instruction generated for the end of function. Tested on SPARC64/Linux, applied on the mainline and 13 branch. 2024-01-09 Eric Botcazou PR rtl-optimization/113140 * reorg.cc (fill_slots_from_thread): If we are to branch after the last instruction of the function, create an end label. 2024-01-09 Eric Botcazou * g++.dg/opt/delay-slot-2.C: New test. -- Eric Botcazoudiff --git a/gcc/reorg.cc b/gcc/reorg.cc index e85af7134f4..99228a22c69 100644 --- a/gcc/reorg.cc +++ b/gcc/reorg.cc @@ -2641,7 +2641,8 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition, arithmetic insn after the jump insn and put the arithmetic insn in the delay slot. If we can't do this, return. */ if (delay_list->is_empty () && likely - && new_thread && !ANY_RETURN_P (new_thread) + && new_thread + && !ANY_RETURN_P (new_thread) && NONJUMP_INSN_P (new_thread) && !RTX_FRAME_RELATED_P (new_thread) && GET_CODE (PATTERN (new_thread)) != ASM_INPUT @@ -2729,14 +2730,16 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition, gcc_assert (thread_if_true); - if (new_thread && simplejump_or_return_p (new_thread) + if (new_thread + && simplejump_or_return_p (new_thread) && redirect_with_delay_list_safe_p (insn, JUMP_LABEL (new_thread), *delay_list)) - new_thread = follow_jumps (JUMP_LABEL (new_thread), insn, - ); + new_thread = follow_jumps (JUMP_LABEL (new_thread), insn, ); - if (ANY_RETURN_P (new_thread)) + if (!new_thread) + label = find_end_label (simple_return_rtx); + else if (ANY_RETURN_P (new_thread)) label = find_end_label (new_thread); else if (LABEL_P (new_thread)) label = new_thread; // PR rtl-optimization/113140 // Reduced testcase by Rainer Orth // { dg-options "-O -w" } int *m(); struct StaticValue { long _val; void setM(int *) { _val = 0; } }; struct Value : StaticValue { template T *as(); }; Value *alloc(); struct Scoped { Scoped() { Value v; ptr = alloc(); Value *__trans_tmp_1 = v.as(); ptr->setM(__trans_tmp_1 ? m() : 0); } Value *ptr; }; struct QObjectMethod { unsigned long long callInternal() const; }; unsigned long long QObjectMethod::callInternal() const { [] { if (Scoped(); 0) ; }(); }
Fix PR rtl-optimization/113140
This is a small regression present on the mainline and 13 branch, although the underlying problem has probably been there for ages, in the form of a segfault during the delay slot scheduling pass, for a function that falls through to exit without any RTL instruction generated for the end of function. Tested on SPARC64/Linux, applied on the mainline and 13 branch. 2024-01-09 Eric Botcazou PR rtl-optimization/113140 * reorg.cc (fill_slots_from_thread): If we are to branch after the last instruction of the function, create an end label. 2024-01-09 Eric Botcazou * g++.dg/opt/delay-slot-2.C: New test. -- Eric Botcazoudiff --git a/gcc/reorg.cc b/gcc/reorg.cc index e85af7134f4..99228a22c69 100644 --- a/gcc/reorg.cc +++ b/gcc/reorg.cc @@ -2641,7 +2641,8 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition, arithmetic insn after the jump insn and put the arithmetic insn in the delay slot. If we can't do this, return. */ if (delay_list->is_empty () && likely - && new_thread && !ANY_RETURN_P (new_thread) + && new_thread + && !ANY_RETURN_P (new_thread) && NONJUMP_INSN_P (new_thread) && !RTX_FRAME_RELATED_P (new_thread) && GET_CODE (PATTERN (new_thread)) != ASM_INPUT @@ -2729,14 +2730,16 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition, gcc_assert (thread_if_true); - if (new_thread && simplejump_or_return_p (new_thread) + if (new_thread + && simplejump_or_return_p (new_thread) && redirect_with_delay_list_safe_p (insn, JUMP_LABEL (new_thread), *delay_list)) - new_thread = follow_jumps (JUMP_LABEL (new_thread), insn, - ); + new_thread = follow_jumps (JUMP_LABEL (new_thread), insn, ); - if (ANY_RETURN_P (new_thread)) + if (!new_thread) + label = find_end_label (simple_return_rtx); + else if (ANY_RETURN_P (new_thread)) label = find_end_label (new_thread); else if (LABEL_P (new_thread)) label = new_thread; // PR rtl-optimization/113140 // Reduced testcase by Rainer Orth // { dg-options "-O -w" } int *m(); struct StaticValue { long _val; void setM(int *) { _val = 0; } }; struct Value : StaticValue { template T *as(); }; Value *alloc(); struct Scoped { Scoped() { Value v; ptr = alloc(); Value *__trans_tmp_1 = v.as(); ptr->setM(__trans_tmp_1 ? m() : 0); } Value *ptr; }; struct QObjectMethod { unsigned long long callInternal() const; }; unsigned long long QObjectMethod::callInternal() const { [] { if (Scoped(); 0) ; }(); }
Re: [PATCH] testsuite: Skip ifcvt-4.c for SPARC V8
> Conditional moves are not available in SPARC V8. > > gcc/testsuite/ChangeLog: > > * gcc.dg/ifcvt-4.c: Skip for SPARC V8 OK. -- Eric Botcazou
Re: [PATCH] sparc: Char arrays are 64-bit aligned on SPARC
> Hello Eric! Thank you for reviewing the patches! You're welcome. > No, this warning is not from GCC, it is from binutils ld. I forgot to > mention that in the message. I get a similar warning from older versions > of ld, so I do not think it is a new warning. It is also there with GCC 10. I see, thanks for the explanation, the patch is OK then. > For the OK:ed patches (with your changes), can I push them to > release/gcc-13 in addition to master? Sure. -- Eric Botcazou
Re: [PATCH 2/2] sparc: Add errata workaround to membar patterns
> LEON now uses the standard V8 membar patterns that contains an ldstub > instruction. This instruction needs to be aligned properly when the > GR712RC errata workaround is enabled. > > gcc/ChangeLog: > > * config/sparc/sparc.cc (atomic_insn_for_leon3_p): Treat membar_storeload as atomic > * config/sparc/sync.md: Add GR712RC errata workaround The second ChangeLog entry should be more detailed: * config/sparc/sync.md (membar_storeload): Turn into named insn and add GR712RC errata workaround. (membar_v8): Add GR712RC errata workaround. OK with this change. -- Eric Botcazou
Re: [PATCH] sparc: Treat instructions with length 0 as empty
> This is to handle the membar_empty instruction that can be generated > when compiling for UT699. > > gcc/ChangeLog: > > * config/sparc/sparc.cc (next_active_non_empty_insn): Length 0 treated > as empty OK without the superfluous parentheses. -- Eric Botcazou
Re: [PATCH 1/2] sparc: Revert membar optimization that is not suitable for LEON5
> LEON5 has a deeper write-buffer and hence stb is not enough to flush a > write out. For compatibility, use the default V8 approach for both > LEON3 and LEON5. > > This reverts commit 49cc765db35a5a21cab2aece27a44983fa70b94b, > "sync.md (*membar_storeload_leon3): New insn." > > gcc/ChangeLog: > > * config/sparc/sync.md (*membar_storeload_leon3): Remove > (*membar_storeload): Enable for LEON OK. -- Eric Botcazou
Re: [PATCH] sparc: Char arrays are 64-bit aligned on SPARC
> pr88077 fails on SPARC since char HeaderStr[1] in pr88077_1.c and > long HeaderStr in pr88077_0.c differs in alignment. > > warning: alignment 4 of normal symbol `HeaderStr' in c_lto_pr88077_0.o is > smaller than 8 used by the common definition in c_lto_pr88077_1.o I have never seen it though. Is that really a warning issued by GCC? -- Eric Botcazou
Re: [PATCH] combine: Don't optimize paradoxical SUBREG AND CONST_INT on WORD_REGISTER_OPERATIONS targets [PR112758]
> Bootstrapped/regtested on x86_64-linux and i686-linux (neither of which > is WORD_REGISTER_OPERATIONS target), tested on the testcase using > cross to riscv64-linux but don't have an easy access to a > WORD_REGISTER_OPERATIONS target to bootstrap/regtest it there. > > Ok for trunk? Yes, thanks for fixing this. -- Eric Botcazou
Re: [gcc15] nested functions in C
> I think from a language standpoint, the general idea that nested > functions are just any functions inside functions (which is how the C > nested functions essentially behave) is too broad and they should be > restricted to minimal implementations that, e.g. don't have side-effects > or if they do, there's explicit syntactic sugar to make it clearer. That sounds totally arbitrary though. Algol-derived languages have had nested subprograms for ages, e.g. Pascal or Ada, and they can be very useful. -- Eric Botcazou
Re: [PATCH] gcc: Disallow trampolines when -fhardened
> I don't know either of these languages to write a test, and I don't see > anything that mentions the word trampoline in gfortran.dg/. Ada has > gnat.dg/trampoline3.adb but: > > $ gcc -c -Wtrampolines trampoline3.adb > trampoline3.adb:6:03: warning: variable "A" is read but never assigned > [-gnatwv] > > so there is no warning. Look at the last line of the test (Ada has not used trampolines for ages!). -- Eric Botcazou
Re: [PATCH] pro_and_epilogue: Call df_note_add_problem () if SHRINK_WRAPPING_ENABLED [PR112760]
> So sorry to be awkward, but I don't think this is the way to go. I think > we'll just end up playing whack-a-mole and adding df_note_add_problem to > lots of passes. We have doing that for the past 15 years though, so what has changed? > (FTR, I'm not saying passes have to avoid false negatives, just false > positives. If a pass updates an instruction with a REG_UNUSED note, > and the pass is no longer sure whether the register is unused or not, > the pass can just delete the note.) Reintroducing the manual management of such notes would be a step backward. -- Eric Botcazou
[Ada] Fix internal error on function returning dynamically-sized type
This is PR ada/109881, a tree sharing issue for the internal return type synthesized for a function returning a dynamically-sized type and taking an Out or In/Out parameter passed by copy. Tested on x86-64/Linux, applied on mainline, 13 and 12 branches. 2023-11-16 Eric Botcazou PR ada/109881 * gcc-interface/decl.cc (gnat_to_gnu_subprog_type): Also create a TYPE_DECL for the return type built for the CI/CO mechanism. 2023-11-16 Eric Botcazou * gnat.dg/varsize4.ads, gnat.dg/varsize4.adb: New test. * gnat.dg/varsize4_pkg.ads: New helper. -- Eric Botcazoudiff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc index 95fa508c559..9c7f6840e21 100644 --- a/gcc/ada/gcc-interface/decl.cc +++ b/gcc/ada/gcc-interface/decl.cc @@ -6329,6 +6329,12 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition, if (debug_info_p) rest_of_record_type_compilation (gnu_cico_return_type); + + /* Declare it now since it will never be declared otherwise. This + is necessary to ensure that its subtrees are properly marked. */ + create_type_decl (TYPE_NAME (gnu_cico_return_type), + gnu_cico_return_type, + true, debug_info_p, gnat_subprog); } gnu_return_type = gnu_cico_return_type; -- { dg-do compile } package body Varsize4 is function Func (bytes_read : out Natural) return Arr is Ret : Arr := (others => False); begin return Ret; end; function Get return Natural is Data : Arr; Bytes : Natural; begin Data := Func (Bytes); return Bytes; end; end Varsize4; with Varsize4_Pkg; package Varsize4 is type Arr is array (1 .. Varsize4_Pkg.F) of Boolean; function Get return Natural; end Varsize4; package Varsize4_Pkg is function F return Natural; end Varsize4_Pkg;
[PATCH] Handle addresses of more constants in IPA-CP
Hi, IPA-CP can currently handle addresses of scalar constants (CONST_DECL) so this extends that to addresses of constants in the pool (DECL_IN_CONSTANT_POOL). Again this is helpful for so-called fat pointers in Ada, i.e. objects that are semantically pointers but represented by structures made up of two pointers. This also moves the unused function print_ipcp_constant_value from ipa-cp.cc to ipa-prop.cc and renames it. I have an LTO testcase for which this makes a difference, but it's large so not really suitable for the testsuite. Bootstrapped/regtested on x86-64/Linux, OK for the mainline? 2023-11-11 Eric Botcazou * ipa-cp.cc (print_ipcp_constant_value): Move to... (values_equal_for_ipcp_p): Deal with VAR_DECLs from the constant pool. * ipa-prop.cc (ipa_print_constant_value): ...here. Likewise. (ipa_print_node_jump_functions_for_edge): Call the function ipa_print_constant_value to print IPA_JF_CONST elements. -- Eric Botcazoudiff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index 788157ebd55..34fae065454 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -478,31 +478,21 @@ values_equal_for_ipcp_p (tree x, tree y) if (TREE_CODE (x) == ADDR_EXPR && TREE_CODE (y) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL - && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL) -return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)), - DECL_INITIAL (TREE_OPERAND (y, 0)), 0); + && (TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL + || (TREE_CODE (TREE_OPERAND (x, 0)) == VAR_DECL + && DECL_IN_CONSTANT_POOL (TREE_OPERAND (x, 0 + && (TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL + || (TREE_CODE (TREE_OPERAND (y, 0)) == VAR_DECL + && DECL_IN_CONSTANT_POOL (TREE_OPERAND (y, 0) +return TREE_OPERAND (x, 0) == TREE_OPERAND (y, 0) + || operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)), + DECL_INITIAL (TREE_OPERAND (y, 0)), 0); else return operand_equal_p (x, y, 0); } /* Print V which is extracted from a value in a lattice to F. */ -static void -print_ipcp_constant_value (FILE * f, tree v) -{ - if (TREE_CODE (v) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL) -{ - fprintf (f, "& "); - print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0))); -} - else -print_generic_expr (f, v); -} - -/* Print V which is extracted from a value in a lattice to F. */ - static void print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v) { diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 827bdb691ba..7de2b788185 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -365,6 +365,24 @@ ipa_initialize_node_params (struct cgraph_node *node) ipa_populate_param_decls (node, *info->descriptors); } +/* Print VAL which is extracted from a jump function to F. */ + +static void +ipa_print_constant_value (FILE *f, tree val) +{ + print_generic_expr (f, val); + + /* This is in keeping with values_equal_for_ipcp_p. */ + if (TREE_CODE (val) == ADDR_EXPR + && (TREE_CODE (TREE_OPERAND (val, 0)) == CONST_DECL + || (TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL + && DECL_IN_CONSTANT_POOL (TREE_OPERAND (val, 0) +{ + fputs (" -> ", f); + print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (val, 0))); +} +} + /* Print the jump functions associated with call graph edge CS to file F. */ static void @@ -386,15 +404,8 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs) fprintf (f, "UNKNOWN\n"); else if (type == IPA_JF_CONST) { - tree val = jump_func->value.constant.value; fprintf (f, "CONST: "); - print_generic_expr (f, val); - if (TREE_CODE (val) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (val, 0)) == CONST_DECL) - { - fprintf (f, " -> "); - print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (val, 0))); - } + ipa_print_constant_value (f, jump_func->value.constant.value); fprintf (f, "\n"); } else if (type == IPA_JF_PASS_THROUGH) @@ -468,7 +479,7 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs) else if (item->jftype == IPA_JF_CONST) { fprintf (f, "CONST: "); - print_generic_expr (f, item->value.constant); + ipa_print_constant_value (f, item->value.constant); } else if (item->jftype == IPA_JF_UNKNOWN) fprintf (f, "UNKNOWN: " HOST_WIDE_INT_PRINT_DEC " bits",
[PATCH] Handle constant CONSTRUCTORs in operand_compare
Hi, this teaches operand_compare to compare constant CONSTRUCTORs, which is quite helpful for so-called fat pointers in Ada, i.e. objects that are semantically pointers but are represented by structures made up of two pointers. This is modeled on the implementation present in the ICF pass. Bootstrapped/regtested on x86-64/Linux, OK for the mainline? 2023-11-10 Eric Botcazou * fold-const.cc (operand_compare::operand_equal_p) : Deal with nonempty constant CONSTRUCTORs. (operand_compare::hash_operand) : Hash DECL_FIELD_OFFSET and DECL_FIELD_BIT_OFFSET for FIELD_DECLs. 2023-11-10 Eric Botcazou * gnat.dg/opt103.ads, gnat.dg/opt103.adb: New test. -- Eric Botcazoudiff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 40767736389..332bc8aead2 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -3315,9 +3315,65 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1, flags | OEP_ADDRESS_OF | OEP_MATCH_SIDE_EFFECTS); case CONSTRUCTOR: - /* In GIMPLE empty constructors are allowed in initializers of - aggregates. */ - return !CONSTRUCTOR_NELTS (arg0) && !CONSTRUCTOR_NELTS (arg1); + { + /* In GIMPLE empty constructors are allowed in initializers of + aggregates. */ + if (!CONSTRUCTOR_NELTS (arg0) && !CONSTRUCTOR_NELTS (arg1)) + return true; + + /* See sem_variable::equals in ipa-icf for a similar approach. */ + tree typ0 = TREE_TYPE (arg0); + tree typ1 = TREE_TYPE (arg1); + + if (TREE_CODE (typ0) != TREE_CODE (typ1)) + return false; + else if (TREE_CODE (typ0) == ARRAY_TYPE) + { + /* For arrays, check that the sizes all match. */ + const HOST_WIDE_INT siz0 = int_size_in_bytes (typ0); + if (TYPE_MODE (typ0) != TYPE_MODE (typ1) + || siz0 < 0 + || siz0 != int_size_in_bytes (typ1)) + return false; + } + else if (!types_compatible_p (typ0, typ1)) + return false; + + vec *v0 = CONSTRUCTOR_ELTS (arg0); + vec *v1 = CONSTRUCTOR_ELTS (arg1); + if (vec_safe_length (v0) != vec_safe_length (v1)) + return false; + + /* Address of CONSTRUCTOR is defined in GENERIC to mean the value + of the CONSTRUCTOR referenced indirectly. */ + flags &= ~OEP_ADDRESS_OF; + + for (unsigned idx = 0; idx < vec_safe_length (v0); ++idx) + { + constructor_elt *c0 = &(*v0)[idx]; + constructor_elt *c1 = &(*v1)[idx]; + + /* Check that the values are the same... */ + if (c0->value != c1->value + && !operand_equal_p (c0->value, c1->value, flags)) + return false; + + /* ... and that they apply to the same field! */ + if (c0->index != c1->index + && (TREE_CODE (typ0) == ARRAY_TYPE + ? !operand_equal_p (c0->index, c1->index, flags) + : !operand_equal_p (DECL_FIELD_OFFSET (c0->index), + DECL_FIELD_OFFSET (c1->index), + flags) + || !operand_equal_p (DECL_FIELD_BIT_OFFSET (c0->index), + DECL_FIELD_BIT_OFFSET (c1->index), + flags))) + return false; + } + + return true; + } + default: break; } @@ -3703,9 +3759,7 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1, elements. Individual elements in the constructor must be indexed in increasing order and form an initial sequence. - We make no effort to compare constructors in generic. - (see sem_variable::equals in ipa-icf which can do so for - constants). */ + We make no effort to compare nonconstant ones in GENERIC. */ if (!VECTOR_TYPE_P (TREE_TYPE (arg0)) || !VECTOR_TYPE_P (TREE_TYPE (arg1))) return false; @@ -3887,7 +3941,13 @@ operand_compare::hash_operand (const_tree t, inchash::hash , /* In GIMPLE the indexes can be either NULL or matching i. */ if (field == NULL_TREE) field = bitsize_int (idx); - hash_operand (field, hstate, flags); + if (TREE_CODE (field) == FIELD_DECL) + { + hash_operand (DECL_FIELD_OFFSET (field), hstate, flags); + hash_operand (DECL_FIELD_BIT_OFFSET (field), hstate, flags); + } + else + hash_operand (field, hstate, flags); hash_operand (value, hstate, flags); } return; -- { dg-do compile } -- { dg-options "-O -gnatn -fdump-tree-optimized" } package body Opt103 is function Read return Mode is S : String := Get; M : Mode; begin -- There should be a single call to Value_Enumeration_Pos after inlining if Mode'Valid_Value (S) then M := Mode'Value (S); else raise Program_Error; end if; return M; end; function Translate (S : String) return Mode is M : Mode; begin -- There should be a single call to Value_Enumeration_Pos after inlining if Mode'Valid_Value (S) then M := Mode'Value (S); else raise Program_Error; end if; return M; end; end Opt103; -- { dg-final {
[PATCH] Add missing return in gori_compute::logical_combine
Hi, the varying case currently falls through to the 1/true case. Tested on x86_64-suse-linux, OK for mainline, 13 and 12 branches? 2023-09-25 Eric Botcazou * gimple-range-gori.cc (gori_compute::logical_combine): Add missing return statement in the varying case. 2023-09-25 Eric Botcazou * gnat.dg/opt102.adb:New test. * gnat.dg/opt102_pkg.adb, gnat.dg/opt102_pkg.ads: New helper. -- Eric Botcazoudiff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 51fb542a19c..2694e551d73 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -876,6 +876,7 @@ gori_compute::logical_combine (vrange , enum tree_code code, r.dump (dump_file); fputc ('\n', dump_file); } + return res; } switch (code) package body Opt102_Pkg is function Get (E : Enum; F, M : access Integer) return Integer is begin case E is when One => return 0; when Two => return F.all; when Three => return M.all; end case; end; end Opt102_Pkg; -- { dg-do run } -- { dg-options "-O2 -gnata" } with Opt102_Pkg; use Opt102_Pkg; procedure Opt102 is I, F : aliased Integer; begin I := Get (Two, F'Access, null); end; package Opt102_Pkg is type Enum is (One, Two, Three); function Get (E : Enum; F, M : access Integer) return Integer with Pre => (E = One) = (F = null and M = null) and (E = Two) = (F /= null) and (E = Three) = (M /= null); end Opt102_Pkg;
Re: PING^5: [PATCH] rtl-optimization/110939 Really fix narrow comparison of memory and constant
> This is why I got a bit uncertain and hoped to get some feedback whether > my intuition is correct or not. Meanwhile I also found a comment in > the internals book at "14.7 Constant Expression Types" where we have: > >"Constants generated for modes with fewer bits than in HOST_WIDE_INT > must be sign extended to full width (e.g., with gen_int_mode). > [...] > Note however that values are neither inherently signed nor > inherently unsigned; where necessary, signedness is determined by > the rtl operation instead." > > At least this and the assert statement document that the normal form of > a CONST_INT is kind of special w.r.t. unsigned integers. Is there > anyone who can shed some light on _why_ such a normal form was chosen? In RTL integral values have no sign, they just represent a given pattern of bits so, in order to have a 1-to-1 mapping, you need to choose a canonical form. The signed form is probably more natural and, since CONST_INTs have no mode, the same objects are used for e.g. QImode and HImode, which means that you need to sign-extend the bit pattern. -- Eric Botcazou
Re: [PATCH] ssa_name_has_boolean_range vs signed-boolean:31 types
> Does Ada have signed booleans that are BOOLEAN_TYPE but do _not_ > have [-1, 0] as range? I think documenting [0, 1] for (single-bit > precision?) unsigned BOOLEAN_TYPE and [-1, 1] for signed BOOLEAN_TYPE would > be conservative. All BOOLEAN_TYPEs are unsigned in Ada but may have precision > 1, typically 8. -- Eric Botcazou
Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
> This should be fixed now. I rewrote the test to check the padding byte > directly, instead of inspecting a copy of it which might not preserve > the padding bits. Great, thanks! -- Eric Botcazou
Re: [PATCH v2] Store_bit_field_1: Use SUBREG instead of REG if possible
> I don't see that. That's definitely not what GCC expects here, > the left-most word of the doubleword should be unchanged. > > Your testcase should be a dg-do-run and probably more like > > NOMIPS16 int __attribute__((noipa)) test (const unsigned char *buf) > { > int val; > ((unsigned char*))[0] = *buf++; > ((unsigned char*))[1] = *buf++; > ((unsigned char*))[2] = *buf++; > ((unsigned char*))[3] = *buf++; > return val; > } > int main() > { > int val = 0x01020304; > val = test (); > if (val != 0x01020304) > abort (); > } > > not sure if I got endianess correct. Now, the question is what > WORD_REGISTER_OPERATIONS implies for a bitfield insert and what > the MIPS ABI says for returning SImode. WORD_REGISTER_OPERATIONS must *not* be taken account for bit-fields, see e;g. word_register_operation_p: /* Return true if X is an operation that always operates on the full registers for WORD_REGISTER_OPERATIONS architectures. */ inline bool word_register_operation_p (const_rtx x) { switch (GET_CODE (x)) { case CONST_INT: case ROTATE: case ROTATERT: case SIGN_EXTRACT: case ZERO_EXTRACT: return false; default: return true; } } -- Eric Botcazou
Re: [COMMITTED] ada: Follow-up fix for compilation issue with recent MinGW-w64 versions
> It turns out that adaint.c includes other Windows header files than just > windows.h, so defining WIN32_LEAN_AND_MEAN is not sufficient for it. > > gcc/ada/ > > * adaint.c [_WIN32]: Undefine 'abort' macro. I backported it onto the 13 branch. -- Eric Botcazou
Re: [COMMITTED] ada: Fix expanding container aggregates
> Ensure that that container aggregate expressions are expanded as > such and not as records even if the type of the expression is a > record. > > gcc/ada/ > > * exp_aggr.adb (Expand_N_Aggregate): Ensure that container > aggregate expressions do not get expanded as records but instead > as container aggregates. This is not a regression but the problem is quite visible in Ada 2022 so I backported the fix onto the 13 branch. -- Eric Botcazou
Re: [COMMITTED] ada: Fix internal error on aggregate within container aggregate
> This just applies the same fix to Expand_Array_Aggregate as the one that was > recently applied to Convert_To_Assignments. > > gcc/ada/ > > * exp_aggr.adb (Convert_To_Assignments): Tweak comment. > (Expand_Array_Aggregate): Do not delay the expansion if the parent > node is a container aggregate. This is not a regression but the problem is quite visible in Ada 2022 so I backported the fix onto the 13 branch. -- Eric Botcazou
Re: [COMMITTED] ada: Fix crash on vector initialization
> Such assignments to container aggregates are later transformed into > procedure calls to the procedures named in the Aggregate aspect > definition, for which the delayed expansion is not required/expected. > > gcc/ada/ > > * exp_aggr.adb (Convert_To_Assignments): Do not mark node for > delayed expansion if parent type has the Aggregate aspect. > * sem_util.adb (Is_Container_Aggregate): Move... > * sem_util.ads (Is_Container_Aggregate): ... here and make it > public. This is not a regression but the problem is quite visible in Ada 2022 so I backported the fix onto the 13 branch. -- Eric Botcazou
[PATCH] Fix couple of endianness issues in fold_ctor_reference
Hi, fold_ctor_reference attempts to use a recursive local processing in order to call native_encode_expr on the leaf nodes of the constructor, before falling back to calling native_encode_initializer if this fails. There are a couple of issues related to endianness present in it: 1) it does not specifically handle integral bit-fields; now these are left justified on big-endian platforms so cannot be treated like ordinary fields. 2) it does not check that the constructor uses the native storage order. Proposed fix attached, tested on x86-64/Linux and SPARC/Solaris, OK for the mainline and some branches? 2023-06-30 Eric Botcazou * gimple-fold.cc (fold_array_ctor_reference): Fix head comment. (fold_nonarray_ctor_reference): Likewise. Specifically deal with integral bit-fields. (fold_ctor_reference): Check that the constructor uses the native storage order. 2023-06-30 Eric Botcazou * gcc.c-torture/execute/20230630-1.c: New test. * gcc.c-torture/execute/20230630-2.c: Likewise. -- Eric Botcazoudiff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index 3d46b76edeb..e80a72dfa22 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -7849,12 +7849,11 @@ get_base_constructor (tree base, poly_int64_pod *bit_offset, } } -/* CTOR is CONSTRUCTOR of an array type. Fold a reference of SIZE bits - to the memory at bit OFFSET. When non-null, TYPE is the expected - type of the reference; otherwise the type of the referenced element - is used instead. When SIZE is zero, attempt to fold a reference to - the entire element which OFFSET refers to. Increment *SUBOFF by - the bit offset of the accessed element. */ +/* CTOR is a CONSTRUCTOR of an array or vector type. Fold a reference of SIZE + bits to the memory at bit OFFSET. If non-null, TYPE is the expected type of + the reference; otherwise the type of the referenced element is used instead. + When SIZE is zero, attempt to fold a reference to the entire element OFFSET + refers to. Increment *SUBOFF by the bit offset of the accessed element. */ static tree fold_array_ctor_reference (tree type, tree ctor, @@ -8019,13 +8018,11 @@ fold_array_ctor_reference (tree type, tree ctor, return type ? build_zero_cst (type) : NULL_TREE; } -/* CTOR is CONSTRUCTOR of an aggregate or vector. Fold a reference - of SIZE bits to the memory at bit OFFSET. When non-null, TYPE - is the expected type of the reference; otherwise the type of - the referenced member is used instead. When SIZE is zero, - attempt to fold a reference to the entire member which OFFSET - refers to; in this case. Increment *SUBOFF by the bit offset - of the accessed member. */ +/* CTOR is a CONSTRUCTOR of a record or union type. Fold a reference of SIZE + bits to the memory at bit OFFSET. If non-null, TYPE is the expected type of + the reference; otherwise the type of the referenced member is used instead. + When SIZE is zero, attempt to fold a reference to the entire member OFFSET + refers to. Increment *SUBOFF by the bit offset of the accessed member. */ static tree fold_nonarray_ctor_reference (tree type, tree ctor, @@ -8037,8 +8034,7 @@ fold_nonarray_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT cnt; tree cfield, cval; - FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, - cval) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval) { tree byte_offset = DECL_FIELD_OFFSET (cfield); tree field_offset = DECL_FIELD_BIT_OFFSET (cfield); @@ -8110,6 +8106,19 @@ fold_nonarray_ctor_reference (tree type, tree ctor, return NULL_TREE; offset_int inner_offset = offset_int (offset) - bitoffset; + + /* Integral bit-fields are left-justified on big-endian targets, so + we must arrange for native_encode_int to look at the MSB. */ + if (DECL_BIT_FIELD (cfield) && INTEGRAL_TYPE_P (TREE_TYPE (cfield))) + { + if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN) + return NULL_TREE; + const unsigned int encoding_size + = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (cfield))); + if (BYTES_BIG_ENDIAN) + inner_offset += encoding_size - wi::to_offset (field_size); + } + return fold_ctor_reference (type, cval, inner_offset.to_uhwi (), size, from_decl, suboff); @@ -8122,7 +8131,7 @@ fold_nonarray_ctor_reference (tree type, tree ctor, return build_zero_cst (type); } -/* CTOR is value initializing memory. Fold a reference of TYPE and +/* CTOR is a value initializing memory. Fold a reference of TYPE and bit size POLY_SIZE to the memory at bit POLY_OFFSET. When POLY_SIZE is zero, attempt to fold a reference to the entire subobject which OFFSET refers to. This is used when folding accesses to @@ -8163,7 +8172,8 @@ fold_ctor_reference (tree type, tree ctor, const poly_uint64 _offset, } re
Re: [PATCH] configure: Implement --enable-host-bind-now
> Arg, once again, I'm sorry. I don't know how this happened. It would > be trivial to fix it but since > > commit 4a48a38fa99f067b8f3a3d1a5dc7a1e602db351f > Author: Eric Botcazou > Date: Wed Jun 21 18:19:36 2023 +0200 > > ada: Fix build of GNAT tools > > the build with Ada included fails with --enable-host-pie. So that needs > to be fixed first. > > Eric, I'm not asking you to fix that, but I'm curious, what did the > commit above fix? The patch looks correct; I'm just puzzled why I > hadn't seen any build failures. The GNAT tools were failing to build for a compiler configured with --disable- host-pie --enable-default-pie. -- Eric Botcazou
Re: When do I need -fnon-call-exceptions?
> On x864 Linux -fasynchronous-unwind-tables is the default. That is > probably sufficient to make your test case work. The testcase g++.dg/torture/except-1.C you recently added to the testsuite does not pass at all if -fnon-call-exceptions is not specified (and does not pass with optimization if -fno-delete-dead-exceptions is not specified). -- Eric Botcazou
Re: [PATCH] tree: Fix up save_expr [PR52339]
> We want to be able to treat such things as invariant somehow even if we > can't do that for references to user data that might be changed by > intervening code. > > That is, indicate that we know that the _REF actually refers to a const > variable or is otherwise known to be unchanging. > > Perhaps that should be a new flag that tree_invariant_p can check > instead of TREE_READONLY. Richard earlier suggested a langhook; given that Ada will be the main (sole?) user of it, this would probably be better. -- Eric Botcazou
Re: [COMMITTED] ada: Remove the body of System.Storage_Elements
> Is this an issue with the patch? Or does it need a newer Ada compiler > to for building it? Neither, it's very likely an issue with your build procedure: you need to use a matching host Ada compiler to build a cross Ada compiler, that's documented in https://gcc.gnu.org/install/prerequisites.html#GNAT-prerequisite "In order to build a cross compiler, it is strongly recommended to install the new compiler as native first, and then use it to build the cross compiler. Other native compiler versions may work but this is not guaranteed and will typically fail with hard to understand compilation errors during the build." -- Eric Botcazou
Re: [PATCH] Fix artificial overflow during GENERIC folding
> But nobody is going to understand why the INTEGER_CST case goes the > other way. I can add a fat comment to that effect of course. :-) > As you say we don't have a good way to say we're doing > this to avoid undefined behavior, but then a view-convert back would > be a good way to indicate that? I can't come up with a better name > for a custom operator we could also use, > > (convert_without_overflow (negate (convert:utype @1 > > maybe? As said, if view_convert works I prefer that. Does it? Well, VIEW_CONVERT_EXPR adds its own set of problems in GENERIC and it will precisely survive when it is not needed, so I'm not sure that's any better. -- Eric Botcazou
Re: [PATCH] Fix artificial overflow during GENERIC folding
> I don't like littering the patterns with this and it's likely far from the > only cases we have? Maybe, but that's the only problematic case we have in Ada. It occurs only on mainline because we have streamlined address calculations there, from out-of- line to inline expansion, i.e. from run time to compile time. > Since we did move some of the patterns from fold-const.cc to match.pd and > the frontends might be interested in TREE_OVERFLOW (otherwise we'd just > scrap that!) I'm not sure removing the flag is good (and I never was really > convinced the setting for the implementation defined behavior on conversion > to unsigned is good). Yes, the Ada front-end relies on the TREE_OVERFLOW flag to detect overflows at compile time, so it cannot be removed, but it must be set correctly, which is not the case here: (T)p - (T) (p + 4) where T is signed should just yield -4. > Am I correct that the user writing such a conversion in Ada _should_ > get a constraint violation? So it's just the middle-end introducing it > to avoid undefined signed overflow that's on error? Yes, it's a Constraint_Error in Ada to convert a value of an unsigned type to a signed type if it does not fit in the signed type. > I'll also note that fold_convert_const_int_from_int shouldn't set > TREE_OVERFLOW on unsigned destination types? So it's the > outer conversion back to signed that generates the TREE_OVERFLOW? Yes, 4 is converted to unsigned, then negated, yielding a huge number, and the final conversion back to signed yields -4 with TREE_OVERFLOW set. > Would it help to use a (view_convert ...) here? For non-constants that > should be folded back to a sign changing (convert ...) but the constant > folding should hopefully happen earlier? But it's again implementation > defined behavior we have here, so not sure we need TREE_OVERFLOW at all. I'm not sure we need to jump through too many hoops here: the intermediate conversion trick is a kludge because we lack a proper method to selectively disable undefined overflow at run time, but that's not the case at compile time where we have a finer-grained control (and even different rules) so I don't really see a problem with handling the two cases differently. -- Eric Botcazou
[PATCH] Fix artificial overflow during GENERIC folding
Hi, on the attached testcase, the Ada compiler gives a bogus warning: storage_offset1.ads:16:52: warning: Constraint_Error will be raised at run time [enabled by default] This directly comes from the GENERIC folding setting a bogus TREE_OVERFLOW on an INTEGER_CST during the (T)P - (T)(P + A) -> -(T) A transformation: /* (T)P - (T)(P + A) -> -(T) A */ (simplify (minus (convert? @0) (convert (plus:c @@0 @1))) (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type) && element_precision (type) <= element_precision (TREE_TYPE (@1))) (with { tree utype = unsigned_type_for (type); } (convert (negate (convert:utype @1 (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For integer types, if A has a smaller type than T the result depends on the possible overflow in P + A. E.g. T=size_t, A=(unsigned)429497295, P>0. However, if an overflow in P + A would cause undefined behavior, we can assume that there is no overflow. */ || (INTEGRAL_TYPE_P (TREE_TYPE (@1)) && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1 (negate (convert @1) (simplify (minus (convert @0) (convert (pointer_plus @@0 @1))) (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type) && element_precision (type) <= element_precision (TREE_TYPE (@1))) (with { tree utype = unsigned_type_for (type); } (convert (negate (convert:utype @1 (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For pointer types, if the conversion of A to the final type requires a sign- or zero-extension, then we have to punt - it is not defined which one is correct. */ || (POINTER_TYPE_P (TREE_TYPE (@0)) && TREE_CODE (@1) == INTEGER_CST && tree_int_cst_sign_bit (@1) == 0)) (negate (convert @1) Ironically enough, this occurs because of the intermediate conversion to an unsigned type which is supposed to hide overflows, but is counter-productive for constants because TREE_OVERFLOW is always set for them, so it ends up setting a bogus TREE_OVERFLOW when converting back to the original type. The fix simply redirects INTEGER_CSTs to the other, direct path without the intermediate conversion to the unsigned type. Tested on x86-64/Linux, OK for the mainline? 2023-05-24 Eric Botcazou * match.pd ((T)P - (T)(P + A) -> -(T) A): Avoid artificial overflow on constants. 2023-05-24 Eric Botcazou * gnat.dg/specs/storage_offset1.ads: New test. -- Eric Botcazoudiff --git a/gcc/match.pd b/gcc/match.pd index 1fe0559acfb..b9d04dd423b 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3194,6 +3194,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (convert (plus:c @@0 @1))) (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type) + && TREE_CODE (@1) != INTEGER_CST && element_precision (type) <= element_precision (TREE_TYPE (@1))) (with { tree utype = unsigned_type_for (type); } (convert (negate (convert:utype @1 @@ -3213,6 +3214,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (convert (pointer_plus @@0 @1))) (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type) + && TREE_CODE (@1) != INTEGER_CST && element_precision (type) <= element_precision (TREE_TYPE (@1))) (with { tree utype = unsigned_type_for (type); } (convert (negate (convert:utype @1 -- { dg-do compile } with System.Storage_Elements; use System.Storage_Elements; with System; package Storage_Offset1 is type Rec is record I1, I2 : Integer; end record; type Ptr is access all Rec; R : Ptr := new Rec; Offset : constant Storage_Offset := R.I1'Address - R.I2'Address; end Storage_Offset1;
Re: [PATCH] Fix handling of non-integral bit-fields in native_encode_initializer
> OK. Thanks! > Can we handle non-integer bitfields by recursing with a temporary buffer to > encode it byte-aligned and then apply shifting and masking to get it in > place? Or is that not worth it? Certainly doable, something along these lines is implemented in varasm.c to output these non-integral bit-fields (output_constructor et al) so we could even try to share some code. However, in practice, these cases turn out to be rare because the tree_output_constant_def path in gimplify_init_constructor is well guarded. -- Eric Botcazou
[PATCH] Fix handling of non-integral bit-fields in native_encode_initializer
Hi, the encoder for CONSTRUCTORs assumes that all bit-fields (DECL_BIT_FIELD) have integral types, but that's not the case in Ada where they may have pretty much any type, resulting in a wrong encoding for them. The attached fix filters out non-integral bit-fields, except if they start and end on a byte boundary because they are correctly handled in this case. Bootstrapped/regtested on x86-64/Linux, OK for mainline and 13 branch? 2023-05-22 Eric Botcazou * fold-const.cc (native_encode_initializer) : Apply the specific treatment for bit-fields only if they have an integral type and filter out non-integral bit-fields that do not start and end on a byte boundary. 2023-05-22 Eric Botcazou * gnat.dg/opt101.adb: New test. * gnat.dg/opt101_pkg.ads: New helper. -- Eric Botcazoudiff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 25466e97220..57521501fff 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -8360,20 +8360,26 @@ native_encode_initializer (tree init, unsigned char *ptr, int len, if (fieldsize == 0) continue; + /* Prepare to deal with integral bit-fields and filter out other + bit-fields that do not start and end on a byte boundary. */ if (DECL_BIT_FIELD (field)) { if (!tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (field))) return 0; - fieldsize = TYPE_PRECISION (TREE_TYPE (field)); bpos = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)); - if (bpos % BITS_PER_UNIT) - bpos %= BITS_PER_UNIT; - else - bpos = 0; - fieldsize += bpos; - epos = fieldsize % BITS_PER_UNIT; - fieldsize += BITS_PER_UNIT - 1; - fieldsize /= BITS_PER_UNIT; + if (INTEGRAL_TYPE_P (TREE_TYPE (field))) + { + bpos %= BITS_PER_UNIT; + fieldsize = TYPE_PRECISION (TREE_TYPE (field)) + bpos; + epos = fieldsize % BITS_PER_UNIT; + fieldsize += BITS_PER_UNIT - 1; + fieldsize /= BITS_PER_UNIT; + } + else if (bpos % BITS_PER_UNIT + || DECL_SIZE (field) == NULL_TREE + || !tree_fits_shwi_p (DECL_SIZE (field)) + || tree_to_shwi (DECL_SIZE (field)) % BITS_PER_UNIT) + return 0; } if (off != -1 && pos + fieldsize <= off) @@ -8382,7 +8388,8 @@ native_encode_initializer (tree init, unsigned char *ptr, int len, if (val == NULL_TREE) continue; - if (DECL_BIT_FIELD (field)) + if (DECL_BIT_FIELD (field) + && INTEGRAL_TYPE_P (TREE_TYPE (field))) { /* FIXME: Handle PDP endian. */ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN) -- { dg-do run } -- { dg-options "-O" } pragma Optimize_Alignment (Space); with Opt101_Pkg; use Opt101_Pkg; procedure Opt101 is C1 : Cont1; C2 : Cont2; begin C1 := ((1234, 1, 2), 1, 2); if C1.R.I1 /= 1 or C1.I2 /= 2 then raise Program_Error; end if; C2 := (1, (1234, 1, 2), 2); if C2.R.I1 /= 1 or C2.I2 /= 2 then raise Program_Error; end if; end; package Opt101_Pkg is type Int is mod 16; type Rec is record S : Short_Integer; I1, I2 : Int; end record; pragma Pack (Rec); for Rec'Alignment use 4; type Cont1 is record R : Rec; I1, I2 : Int; end record; pragma Pack (Cont1); type Cont2 is record I1 : Int; R : Rec; I2 : Int; end record; pragma Pack (Cont2); pragma No_Component_Reordering (Cont2); end Opt101_Pkg;
Re: [PATCH] Fix internal error on small array with negative lower bound
> Would it be better to use > > wi::to_uhwi (wi::to_wide (local->index) - wi::to_wide (local->min_index)) > > to honor the actual sign of the indices? I think nothing forbids frontends > to use a signed TYPE_DOMAIN here? But the difference should be always > representable in an unsigned value of course. We use tree_to_uhwi everywhere else though, see categorize_ctor_elements_1: if (tree_fits_uhwi_p (lo_index) && tree_fits_uhwi_p (hi_index)) mult = (tree_to_uhwi (hi_index) - tree_to_uhwi (lo_index) + 1); or store_constructor this_node_count = (tree_to_uhwi (hi_index) - tree_to_uhwi (lo_index) + 1); so the proposed form looks better for the sake of consistency. -- Eric Botcazou
[PATCH] Fix internal error on small array with negative lower bound
Hi, Ada supports arrays with negative indices, although the internal index type is sizetype like in other languages, which is unsigned. This means that negative values are represented by very large numbers, which works with a bit of care. The attached test exposes a small loophole in output_constructor_bitfield. Tested on x86-64/Linux, OK for the mainline? 2023-05-18 Eric Botcazou * varasm.cc (output_constructor_bitfield): Call tree_to_uhwi instead of tree_to_shwi on array indices. Minor tweaks. 2023-05-18 Eric Botcazou * gnat.dg/specs/array6.ads: New test. -- Eric Botcazoudiff --git a/gcc/varasm.cc b/gcc/varasm.cc index 2256194d934..478cbfe6736 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -5585,19 +5585,18 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset) /* Relative index of this element if this is an array component. */ HOST_WIDE_INT relative_index -= (!local->field - ? (local->index - ? (tree_to_shwi (local->index) - - tree_to_shwi (local->min_index)) - : local->last_relative_index + 1) - : 0); += (local->field + ? 0 + : (local->index + ? tree_to_uhwi (local->index) - tree_to_uhwi (local->min_index) + : local->last_relative_index + 1)); /* Bit position of this element from the start of the containing constructor. */ HOST_WIDE_INT constructor_relative_ebitpos - = (local->field - ? int_bit_position (local->field) - : ebitsize * relative_index); += (local->field + ? int_bit_position (local->field) + : ebitsize * relative_index); /* Bit position of this element from the start of a possibly ongoing outer byte buffer. */ -- { dg-do compile } package Array6 is type Range_Type is range -10 .. 10; type Array_Type is array (Range_Type range <> ) of Short_Short_Integer; type Record_Type is record A : Array_Type(-2..4); end record ; Rec : Record_Type := (A => (others => -1)); end Array6;
Re: [PATCH 01/14] ada: use _P() defines from tree.h
> && DECL_RETURN_VALUE_P (inner)) > diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc > index 0c4f8b90c8e..460ef6f1f01 100644 > --- a/gcc/ada/gcc-interface/utils.cc > +++ b/gcc/ada/gcc-interface/utils.cc > @@ -1966,7 +1966,7 @@ finish_record_type (tree record_type, tree field_list, > int rep_level, bool debug_info_p) > { >const enum tree_code orig_code = TREE_CODE (record_type); > - const bool had_size = TYPE_SIZE (record_type) != NULL_TREE; > + const bool had_size = COMPLETE_TYPE_P (record_type); >const bool had_align = TYPE_ALIGN (record_type) > 0; >/* For all-repped records with a size specified, lay the QUAL_UNION_TYPE > out just like a UNION_TYPE, since the size will be fixed. */ This one is not an improvement but more of a coincidence; the rest is OK. -- Eric Botcazou
Re: [PATCH] tree: Fix up save_expr [PR52339]
> I think we really need Eric (as one who e.g. introduced the > DECL_INVARIANT_P apparently for this kind of stuff) to have a look at that > on the Ada side. I have been investigating this for a few days and it's no small change for Ada and probably for other languages with dynamic types. SAVE_EXPRs are delicate to handle because 1) they are TREE_SIDE_EFFECTS (it's explained in save_expr) so out of TREE_READONLY && !TREE_SIDE_EFFECTS trees, you now get side effects which then propagate to all parent nodes 2) their placement is problematic in conditional expressions, for example if you replace cond > 0 ? A : A + 1 with cond > 0 ? SAVE_EXPR (A) : SAVE_EXPR (A) + 1 then gimplification will, say, create the temporary and initialize it in the first arm so, if at runtime you take the second arm, you'll read the temporary uninitialized. That's caught for scalar values by the SSA form (if your patch is applied to a GCC 12 tree, you'll get ICEs in the ACATS testsuite because of this through finalize_type_size -> variable_size -> save_expr, it is probably mitigated/addressed in GCC 14 by 68e0063397ba820e71adc220b2da0581dce29ffa). That's also why making gnat_invariant_expr return (some of) them does not look really safe. In addition to this, in Ada we have bounds of unconstrained arrays which are both read-only and stored indirectly, i.e. you have an INDIRECT_REF in the tree (it is marked TREE_THIS_NOTRAP because the bounds are always present), and which obviously play a crucial role in loops running over the arrays. This issue is responsible for the regressions in the gnat.dg testsuite. I think that we can reasonably deal with the second issue in the Ada front-end because we know the semantics of the bounds of unconstrained arrays, and I'm testing a patch to that effect, but the first issue might be annoying too. -- Eric Botcazou
Re: [PATCH] tree: Fix up save_expr [PR52339]
> I think we really need Eric (as one who e.g. introduced the > DECL_INVARIANT_P apparently for this kind of stuff) to have a look at that > on the Ada side. DECL_INVARIANT_P is only set on discriminants with no default value and those are really invariant in Ada, i.e. do not change once set. > The question is if the posted tree.cc (smallest) patch + 3 new testcases > + the 7 ada testsuite workarounds are ok for trunk if it passes > bootstrap/regtest, then I'd file a PR about the Ada regression and only once > it is dealt with would consider backporting, or if we need to wait for Eric > before making progress. Let me have a quick look first, as pessimizing loop optimizations in Ada in order to fix a 11-year old PR seems to be a little bit hasty. -- Eric Botcazou
Re: Probe emission in fstack-clash-protection
> That may ultimately be better for -fstack-check to make it more robust, > but it still wouldn't be a viable alternative for stack clash protection > for the reasons laid out in that blog post. Well, -fstack-check does that when it's possible, e.g. on Windows, but it's not on x86[_64]/Linux where you *cannot* probe below the stack pointer. -- Eric Botcazou
Re: [PATCH] Avoid creating useless debug temporaries
> probably also helps PR109612 and the other similar PR referenced therein. Here's a more aggressive patch in this area, but it regresses guality tests, for example: +FAIL: gcc.dg/guality/ipa-sra-1.c -O2 -DPREVENT_OPTIMIZATION line 27 k == 3 +FAIL: gcc.dg/guality/ipa-sra-1.c -O3 -g -DPREVENT_OPTIMIZATION line 27 k == 3 +FAIL: gcc.dg/guality/ipa-sra-1.c -Os -DPREVENT_OPTIMIZATION line 27 k == 3 eric@fomalhaut:~/build/gcc/native> diff -u ipa-sra-1.c.254t.optimized.0 ipa- sra-1.c.254t.optimized --- ipa-sra-1.c.254t.optimized.02023-04-26 11:12:07.806357325 +0200 +++ ipa-sra-1.c.254t.optimized 2023-04-26 11:24:08.632874257 +0200 @@ -101,7 +101,6 @@ # DEBUG k => k_5 # DEBUG BEGIN_STMT _1 = get_val1 (); - # DEBUG D#6 => k_5 r_8 = foo.isra (_1); # DEBUG r => r_8 # DEBUG BEGIN_STMT and I don't understand why yet. * tree-ssa-dce.cc (find_debug_expr_decl): New callback. (mark_stmt_if_obviously_necessary): Add DECLS parameters. : Call find_debug_expr_decl on the value of DEBUG_BIND statements and record the results in DECLS. (find_obviously_necessary_stmts): If DEBUG_BIND statements may be present, get rid of those setting an unnecessary DEBUG_EXPR_DECL. -- Eric Botcazoudiff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc index 08876bfc1c7..09bbfaca22e 100644 --- a/gcc/tree-ssa-dce.cc +++ b/gcc/tree-ssa-dce.cc @@ -191,14 +191,35 @@ mark_operand_necessary (tree op) } +/* Called via walk_tree, look for DEBUG_EXPR_DECLs and mark them in DATA. */ + +static tree +find_debug_expr_decl (tree *tp, int *walk_subtrees, void *data) +{ + auto_bitmap *decls = (auto_bitmap *) data; + + if (TREE_CODE (*tp) == SSA_NAME || IS_TYPE_OR_DECL_P (*tp)) +{ + if (TREE_CODE (*tp) == DEBUG_EXPR_DECL) + bitmap_set_bit (*decls, DECL_UID (*tp)); + + *walk_subtrees = 0; +} + + return NULL_TREE; +} + /* Mark STMT as necessary if it obviously is. Add it to the worklist if it can make other statements necessary. + If STMT is a DEBUG_BIND, mark the necessary DEBUG_EXPR_DECLs in DECLS. + If AGGRESSIVE is false, control statements are conservatively marked as necessary. */ static void -mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive) +mark_stmt_if_obviously_necessary (gimple *stmt, auto_bitmap *decls, + bool aggressive) { /* Statements that are implicitly live. Most function calls, asm and return statements are required. Labels and GIMPLE_BIND nodes @@ -258,14 +279,28 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive) } case GIMPLE_DEBUG: - /* Debug temps without a value are not useful. ??? If we could - easily locate the debug temp bind stmt for a use thereof, - would could refrain from marking all debug temps here, and - mark them only if they're used. */ - if (gimple_debug_nonbind_marker_p (stmt) - || !gimple_debug_bind_p (stmt) - || gimple_debug_bind_has_value_p (stmt) - || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL) + if (gimple_debug_bind_p (stmt)) + { + tree var = gimple_debug_bind_get_var (stmt); + tree val = gimple_debug_bind_get_value (stmt); + bool necessary = false; + + /* A bind statement for a real variable is always necessary. */ + if (TREE_CODE (var) != DEBUG_EXPR_DECL) + necessary = true; + + /* A bind statement with a value is necessary for now and we look + into the value to find out necessary DEBUG_EXPR_DECLs. */ + if (val) + { + walk_tree (, find_debug_expr_decl, decls, NULL); + necessary = true; + } + + if (necessary ) + mark_stmt_necessary (stmt, false); + } + else mark_stmt_necessary (stmt, false); return; @@ -398,6 +433,7 @@ find_obviously_necessary_stmts (bool aggressive) gimple_stmt_iterator gsi; edge e; gimple *phi, *stmt; + auto_bitmap necessary_decls; int flags; FOR_EACH_BB_FN (bb, cfun) @@ -414,10 +450,35 @@ find_obviously_necessary_stmts (bool aggressive) { stmt = gsi_stmt (gsi); gimple_set_plf (stmt, STMT_NECESSARY, false); - mark_stmt_if_obviously_necessary (stmt, aggressive); + mark_stmt_if_obviously_necessary (stmt, _decls, aggressive); } } + /* Check all debug bind statements again in the basic blocks and find out + those which set an unnecessary DEBUG_EXPR_DECL to a value. */ + if (MAY_HAVE_DEBUG_BIND_STMTS) +FOR_EACH_BB_FN (bb, cfun) + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next ()) + { + stmt = gsi_stmt (gsi); + if (gimple_debug_bind_p (stmt) + && gimple_debug_bind_has_value_p (stmt)) + { + tree var = gimple_debug_bind_get_var (stmt); + if (TREE_CODE (var) == DEBUG_EXPR_DECL + && !bitmap_bit_p (necessary_decls, DECL_UID (var))) + { + gimple_set_plf (stmt, STMT_NECESSARY, false); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Unmarking useful stmt:
Re: [PATCH] Avoid creating useless debug temporaries
> Haven't looked into detail, but just saving compilation time shouldn't be > the only factor when deciding about debug info stuff, another and perhaps > even more important would be whether it affects the emitted debug info. At least it doesn't change the guality results. -- Eric Botcazou
[PATCH] Avoid creating useless debug temporaries
Hi, insert_debug_temp_for_var_def has some strange code whereby it creates debug temporaries for SINGLE_RHS (RHS for gimple_assign_single_p) but not for other RHS in the same situation. Removing it saves 25% of compilation time at -g -O for a pathological testcase I have. Bootstrapped/regtested on x86-64/Linux, OK for the mainline? 2023-04-25 Eric Botcazou * tree-ssa.cc (insert_debug_temp_for_var_def): Do not create superfluous debug temporaries for single GIMPLE assignments. -- Eric Botcazoudiff --git a/gcc/tree-ssa.cc b/gcc/tree-ssa.cc index a5cad2d344e..4ca1f5f3104 100644 --- a/gcc/tree-ssa.cc +++ b/gcc/tree-ssa.cc @@ -412,8 +412,7 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var) { /* If there's a single use of VAR, and VAR is the entire debug expression (usecount would have been incremented again - otherwise), and the definition involves only constants and - SSA names, then we can propagate VALUE into this single use, + otherwise), then we can propagate VALUE into this single use, avoiding the temp. We can also avoid using a temp if VALUE can be shared and @@ -424,11 +423,9 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var) are deferred to a debug temp, although we could avoid temps at the expense of duplication of expressions. */ - if (CONSTANT_CLASS_P (value) + if (usecount == 1 || gimple_code (def_stmt) == GIMPLE_PHI - || (usecount == 1 - && (!gimple_assign_single_p (def_stmt) - || is_gimple_min_invariant (value))) + || CONSTANT_CLASS_P (value) || is_gimple_reg (value)) ; else @@ -466,11 +463,6 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var) if (value) { FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) - /* unshare_expr is not needed here. vexpr is either a - SINGLE_RHS, that can be safely shared, some other RHS - that was unshared when we found it had a single debug - use, or a DEBUG_EXPR_DECL, that can be safely - shared. */ SET_USE (use_p, unshare_expr (value)); /* If we didn't replace uses with a debug decl fold the resulting expression. Otherwise we end up with invalid IL. */
[Ada] Remove obsolete configure code in gnattools
It was recently pointed out that we generate symbolic links to ghost files when building the GNAT tools, as the mlib-tgt-specific-*.adb files are gone. Tested on x86-64/Linux, applied on the mainline. I'll backport this onto branches after the GCC 13.1 release is out. 2023-04-25 Eric Botcazou * configure.ac (TOOLS_TARGET_PAIRS): Remove obsolete settings. (EXTRA_GNATTOOLS): Likewise. * configure: Regenerate. -- Eric Botcazou diff --git a/gnattools/configure.ac b/gnattools/configure.ac index 5b6f34ed9f4..38a28b6ee62 100644 --- a/gnattools/configure.ac +++ b/gnattools/configure.ac @@ -53,74 +53,38 @@ AC_PROG_LN_S # Target-specific stuff (defaults) TOOLS_TARGET_PAIRS= -AC_SUBST(TOOLS_TARGET_PAIRS) EXTRA_GNATTOOLS= -AC_SUBST(EXTRA_GNATTOOLS) # Per-target case statement # - case "${target}" in *-*-aix*) -TOOLS_TARGET_PAIRS="\ -mlib-tgt-specific.adb
Re: [PATCH] reload: Handle generating reloads that also clobbers flags
> That "supposed to" is only *one* possible implementation. > The one in CRIS - and I believe the preferred one; one I > should advocate more - is to *always* expose clobbering of > the flags. Yes, both approaches are acceptable IMO and should work. -- Eric Botcazou
Re: [Ada] Fix PR bootstrap/109510
> Tested on Aarch64/Linux by Richard S. (thanks!) and on x86-64/Linux by me, > and applied on the mainline. It turns out that it slightly broke the x86/Linux compiler, which is not yet an acceptable trade-off. Adjusted like this, tested on x86[_64]/Linux, this should not change anything for Aarch64 in particular. PR bootstrap/109510 * gcc-interface/decl.cc (gnat_to_gnu_entity) : Do not reset align to zero in any case. Set TYPE_USER_ALIGN on the type only if it is an aggregate type, or else a type whose default alignment is specifically capped on selected platforms. -- Eric Botcazou diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc index 851a6745f77..20f43de9ea9 100644 --- a/gcc/ada/gcc-interface/decl.cc +++ b/gcc/ada/gcc-interface/decl.cc @@ -4371,10 +4371,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) align = validate_alignment (Alignment (gnat_entity), gnat_entity, TYPE_ALIGN (gnu_type)); - /* Treat confirming clauses on scalar types like the default. */ - if (align == TYPE_ALIGN (gnu_type) && !AGGREGATE_TYPE_P (gnu_type)) - align = 0; - /* Warn on suspiciously large alignments. This should catch errors about the (alignment,byte)/(size,bit) discrepancy. */ if (align > BIGGEST_ALIGNMENT && Has_Alignment_Clause (gnat_entity)) @@ -4657,6 +4653,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* If this is not an unconstrained array type, set some flags. */ if (TREE_CODE (gnu_type) != UNCONSTRAINED_ARRAY_TYPE) { + bool align_clause; + /* Record the property that objects of tagged types are guaranteed to be properly aligned. This is necessary because conversions to the class-wide type are translated into conversions to the root type, @@ -4669,8 +4667,20 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) if (is_by_ref && !VOID_TYPE_P (gnu_type)) TYPE_BY_REFERENCE_P (gnu_type) = 1; - /* Record whether an alignment clause was specified. */ - if (align > 0 && Present (Alignment_Clause (gnat_entity))) + /* Record whether an alignment clause was specified. At this point + scalar types with a non-confirming clause have been wrapped into + a record type, so only scalar types with a confirming clause are + left untouched; we do not set the flag on them except if they are + types whose default alignment is specifically capped in order not + to lose the specified alignment. */ + if ((AGGREGATE_TYPE_P (gnu_type) + && Present (Alignment_Clause (gnat_entity))) + || (double_float_alignment > 0 + && is_double_float_or_array (gnat_entity, _clause) + && align_clause) + || (double_scalar_alignment > 0 + && is_double_scalar_or_array (gnat_entity, _clause) + && align_clause)) TYPE_USER_ALIGN (gnu_type) = 1; /* Record whether a pragma Universal_Aliasing was specified. */
[Ada] Fix PR bootstrap/109510
This is the build failure of the Ada runtime for Aarch64 targets. The Aarch64 back-end now asserts that the main variant of scalar types has TYPE_USER_ALIGN cleared, and that's not the case for scalar types declared with a confirming alignment clause in Ada. Tested on Aarch64/Linux by Richard S. (thanks!) and on x86-64/Linux by me, and applied on the mainline. 2023-04-14 Eric Botcazou PR bootstrap/109510 * gcc-interface/decl.cc (gnat_to_gnu_entity) : Reset align to zero if its value is equal to TYPE_ALIGN and the type is scalar. Set TYPE_USER_ALIGN on the type only if align is positive. -- Eric Botcazoudiff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc index d24adf33601..851a6745f77 100644 --- a/gcc/ada/gcc-interface/decl.cc +++ b/gcc/ada/gcc-interface/decl.cc @@ -4364,13 +4364,17 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* If the alignment has not already been processed and this is not an unconstrained array type, see if an alignment is specified. If not, we pick a default alignment for atomic objects. */ - if (align != 0 || TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE) + if (align > 0 || TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE) ; else if (Known_Alignment (gnat_entity)) { align = validate_alignment (Alignment (gnat_entity), gnat_entity, TYPE_ALIGN (gnu_type)); + /* Treat confirming clauses on scalar types like the default. */ + if (align == TYPE_ALIGN (gnu_type) && !AGGREGATE_TYPE_P (gnu_type)) + align = 0; + /* Warn on suspiciously large alignments. This should catch errors about the (alignment,byte)/(size,bit) discrepancy. */ if (align > BIGGEST_ALIGNMENT && Has_Alignment_Clause (gnat_entity)) @@ -4666,7 +4670,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) TYPE_BY_REFERENCE_P (gnu_type) = 1; /* Record whether an alignment clause was specified. */ - if (Present (Alignment_Clause (gnat_entity))) + if (align > 0 && Present (Alignment_Clause (gnat_entity))) TYPE_USER_ALIGN (gnu_type) = 1; /* Record whether a pragma Universal_Aliasing was specified. */
Re: gcc with the new WIN32 threads fails to compile libstdc++
> I'm assuming the problem also extends to the other __gthr_win32 routines as > well, __gthr_win32_create just happens to be the first symbol it cannot > find. > > Is there a way to fix this issue? How did you configure the compiler and what version of MinGW64 do you use? -- Eric Botcazou