diff -Nurp a/gcc/fold-const.c b/gcc/fold-const.c --- a/gcc/fold-const.c 2020-06-16 22:27:46.116000000 -0400 +++ b/gcc/fold-const.c 2020-06-16 22:27:58.412000000 -0400 @@ -7165,15 +7165,9 @@ fold_plusminus_mult_expr (location_t loc increased the number of multiplications necessary. */ && TREE_CODE (arg10) != INTEGER_CST) { - HOST_WIDE_INT tmp1 = int01 / int11; - HOST_WIDE_INT t = exact_log2 (absu_hwi (int11)); - HOST_WIDE_INT size = tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (arg00))) * BITS_PER_UNIT; - HOST_WIDE_INT sign_bit = HOST_WIDE_INT_1U << (size - t - 1); - if (tmp1 & sign_bit) - tmp1 |= HOST_WIDE_INT_M1U << (size - t); - tree tmp2 = build_int_cst (TREE_TYPE (arg00), tmp1); alt0 = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (arg00), arg00, - tmp2); + build_int_cst (TREE_TYPE (arg00), + int01 / int11)); alt1 = arg10; same = maybe_same; if (swap) diff -Nurp a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c --- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c 2020-06-16 22:27:46.116000000 -0400 +++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c 2020-06-16 22:33:18.968000000 -0400 @@ -112,6 +112,23 @@ is_va_list_type (tree type) return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node); } +static const char * +get_type_name (tree type) +{ + const char *tname = NULL; + if (TYPE_NAME (type) != NULL) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + { + tname = IDENTIFIER_POINTER (TYPE_NAME (type)); + } + else if (DECL_NAME (TYPE_NAME (type)) != NULL) + { + tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); + } + } + return tname; +} /* Return the inner most type for arrays and pointers of TYPE. */ @@ -463,10 +480,10 @@ srtype::analyze (void) if (fields.length () == 2) fields[1]->clusternum = 1; - /* REMOVEME: FIXME: this is here for testing more testcases. */ + /* FIXME: Currently Return. */ if (fields.length () >= 3) { - fields[1]->clusternum = 1; + return; } } @@ -875,6 +892,7 @@ private: void analyze_types (void); void clear_visited (void); bool create_new_types (void); + void restore_field_type (void); void create_new_decls (void); srdecl *find_decl (tree); void create_new_functions (void); @@ -1096,6 +1114,11 @@ ipa_struct_reorg::record_type (tree type { tree t = TREE_TYPE (field); process_union (t); + if (TREE_CODE (inner_type (t)) == UNION_TYPE + || TREE_CODE (inner_type (t)) == QUAL_UNION_TYPE) + { + type1->mark_escape (escape_union, NULL); + } if (isvolatile_type (t)) type1->mark_escape (escape_volatile, NULL); escape_type e = escape_type_volatile_array_or_ptrptr (t); @@ -2818,6 +2841,49 @@ ipa_struct_reorg::analyze_types (void) } } +/* When struct A has a struct B member, B's type info + is not stored in + TYPE_FIELDS (TREE_TYPE (TYPE_FIELDS (typeA))) + Try to restore B's type information. */ +void +ipa_struct_reorg::restore_field_type (void) +{ + for (unsigned i = 0; i < types.length (); i++) + { + for (unsigned j = 0; j < types[i]->fields.length (); j++) + { + srfield *field = types[i]->fields[j]; + if (TREE_CODE (inner_type (field->fieldtype)) == RECORD_TYPE) + { + /* If field type has TYPE_FIELDS information, + we do not need to do this. */ + if (TYPE_FIELDS (field->type->type) != NULL) + { + continue; + } + for (unsigned k = 0; k < types.length (); k++) + { + if (i == k) + { + continue; + } + const char *type1 = get_type_name (field->type->type); + const char *type2 = get_type_name (types[k]->type); + if (type1 == NULL || type2 == NULL) + { + continue; + } + if (type1 == type2 + && TYPE_FIELDS (types[k]->type)) + { + field->type = types[k]; + } + } + } + } + } +} + /* Create all new types we want to create. */ bool @@ -3669,7 +3735,7 @@ ipa_struct_reorg::rewrite_functions (voi { unsigned retval = 0; - + restore_field_type (); /* Create new types, if we did not create any new types, then don't rewrite any accesses. */ if (!create_new_types ()) diff -Nurp a/gcc/testsuite/gcc.c-torture/compile/20170404-1.c b/gcc/testsuite/gcc.c-torture/compile/20170404-1.c --- a/gcc/testsuite/gcc.c-torture/compile/20170404-1.c 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.c-torture/compile/20170404-1.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,19 +0,0 @@ -struct a -{ - int t, t1; -}; - -static struct a *b; - -void *xmalloc(int); - - -void f(void) -{ - b = xmalloc (sizeof(*b)); -} - -int g(void) -{ - return b->t; -} diff -Nurp a/gcc/testsuite/gcc.c-torture/compile/nested-3.c b/gcc/testsuite/gcc.c-torture/compile/nested-3.c --- a/gcc/testsuite/gcc.c-torture/compile/nested-3.c 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.c-torture/compile/nested-3.c 2020-06-16 22:27:58.416000000 -0400 @@ -1,4 +1,3 @@ -/* This used to crash Struct reorg. */ struct a { int t; diff -Nurp a/gcc/testsuite/gcc.c-torture/compile/struct-reorg-1.c b/gcc/testsuite/gcc.c-torture/compile/struct-reorg-1.c --- a/gcc/testsuite/gcc.c-torture/compile/struct-reorg-1.c 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.c-torture/compile/struct-reorg-1.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,18 +0,0 @@ -#include -typedef struct { - long laststart_offset; - unsigned regnum; -} compile_stack_elt_t; -typedef struct { - compile_stack_elt_t *stack; - unsigned size; -} compile_stack_type; -void f (const char *p, const char *pend, int c) -{ - compile_stack_type compile_stack; - while (p != pend) - if (c) - compile_stack.stack = realloc (compile_stack.stack, - (compile_stack.size << 1) - * sizeof (compile_stack_elt_t)); -} diff -Nurp a/gcc/testsuite/gcc.dg/pr33136-4.c b/gcc/testsuite/gcc.dg/pr33136-4.c --- a/gcc/testsuite/gcc.dg/pr33136-4.c 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.dg/pr33136-4.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,59 +0,0 @@ -/* PR tree-optimization/33136 */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -extern void abort (void); - -struct S -{ - int b; - int *c; -}; -static int d, e; - -static struct S s; - -static int * -__attribute__((noinline, const)) -foo (void) -{ - return &s.b; -} - -int * -__attribute__((noinline)) -bar (int **f) -{ - s.c = &d; - *f = &e; - /* As nothing ever takes the address of any int * field in struct S, - the write to *f can't alias with the s.c field. */ - return s.c; -} - -int -__attribute__((noinline)) -baz (int *x) -{ - s.b = 1; - *x = 4; - /* Function foo takes address of an int field in struct S, - so *x can alias with the s.b field (and it does in this testcase). */ - return s.b; -} - -int -__attribute__((noinline)) -t (void) -{ - int *f = (int *) 0; - return 10 * (bar (&f) != &d) + baz (foo ()); -} - -int -main (void) -{ - if (t () != 4) - abort (); - return 0; -} diff -Nurp a/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c --- a/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c 1969-12-31 19:00:00.000000000 -0500 +++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c 2020-06-16 22:27:58.436000000 -0400 @@ -0,0 +1,24 @@ +// { dg-do compile } +// { dg-options "-O3 -flto-partition=one -fipa-struct-reorg -fdump-ipa-all" } + +struct a +{ + int t, t1; +}; + +static struct a *b; + +void *xmalloc(int); + + +void f(void) +{ + b = xmalloc (sizeof(*b)); +} + +int g(void) +{ + return b->t; +} + +/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c --- a/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c 1969-12-31 19:00:00.000000000 -0500 +++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c 2020-06-16 22:27:58.440000000 -0400 @@ -0,0 +1,29 @@ +// { dg-do run } + +#include + +struct a +{ + int t; + int t1; +}; + +__attribute__((noinline)) int f(int i, int j) +{ + struct a *t; + struct a t1 = {i, j}; + t = &t1; + auto int g(void) __attribute__((noinline)); + int g(void) + { + return t->t + t->t1; + } + return g(); +} + +int main() +{ + assert (f(1, 2) == 3); +} + +/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c --- a/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c 1969-12-31 19:00:00.000000000 -0500 +++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c 2020-06-16 22:27:58.440000000 -0400 @@ -0,0 +1,23 @@ +// { dg-do compile } +// { dg-options "-O3 -flto-partition=one -fipa-struct-reorg -fdump-ipa-all" } + +#include +typedef struct { + long laststart_offset; + unsigned regnum; +} compile_stack_elt_t; +typedef struct { + compile_stack_elt_t *stack; + unsigned size; +} compile_stack_type; +void f (const char *p, const char *pend, int c) +{ + compile_stack_type compile_stack; + while (p != pend) + if (c) + compile_stack.stack = realloc (compile_stack.stack, + (compile_stack.size << 1) + * sizeof (compile_stack_elt_t)); +} + +/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c --- a/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c 1969-12-31 19:00:00.000000000 -0500 +++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c 2020-06-16 22:27:58.440000000 -0400 @@ -0,0 +1,59 @@ +/* { dg-do run } */ + +extern void abort (void); + +struct S +{ + int b; + int *c; +}; +static int d, e; + +static struct S s; + +static int * +__attribute__((noinline, const)) +foo (void) +{ + return &s.b; +} + +int * +__attribute__((noinline)) +bar (int **f) +{ + s.c = &d; + *f = &e; + /* As nothing ever takes the address of any int * field in struct S, + the write to *f can't alias with the s.c field. */ + return s.c; +} + +int +__attribute__((noinline)) +baz (int *x) +{ + s.b = 1; + *x = 4; + /* Function foo takes address of an int field in struct S, + so *x can alias with the s.b field (and it does in this testcase). */ + return s.b; +} + +int +__attribute__((noinline)) +t (void) +{ + int *f = (int *) 0; + return 10 * (bar (&f) != &d) + baz (foo ()); +} + +int +main (void) +{ + if (t () != 4) + abort (); + return 0; +} + +/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp --- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp 2020-06-16 22:27:58.440000000 -0400 @@ -1,5 +1,4 @@ -# Copyright (C) 2007, 2008, 2009, 2010 -# Free Software Foundation, Inc. +# Copyright (C) 1997-2019 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -12,12 +11,9 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING3. If not see +# along with GCC; see the file COPYING3. If not see # . -# Test the functionality of programs compiled with profile-directed structure -# rearrangement using -fprofile-generate followed by -fprofile-use. - load_lib gcc-dg.exp load_lib target-supports.exp @@ -26,62 +22,14 @@ dg-init torture-init set STRUCT_REORG_TORTURE_OPTIONS [list \ - { -O1 } \ - { -O1 -g } \ - { -O2 } \ - { -O2 -g } \ - { -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions } \ - { -O3 -g } \ - { -Os } ] - + { -O3 } \ + { -Ofast } ] -set-torture-options $STRUCT_REORG_TORTURE_OPTIONS {{}} $LTO_TORTURE_OPTIONS +set-torture-options $STRUCT_REORG_TORTURE_OPTIONS {{}} -gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/wo_prof_*.c]] "" "-fipa-struct-reorg -fdump-ipa-all -fwhole-program" +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \ + "" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program" +# All done. torture-finish -dg-final - -# Some targets don't support tree profiling. -if { ![check_profiling_available ""] } { - return -} - -# The procedures in profopt.exp need these parameters. -set tool gcc -set prof_ext "gcda" - -# Override the list defined in profopt.exp. -set PROFOPT_OPTIONS [list {}] - -if $tracelevel then { - strace $tracelevel -} - -# Load support procs. -load_lib profopt.exp - -# These are globals used by profopt-execute. The first is options -# needed to generate profile data, the second is options to use the -# profile data. -set common "-O3 -fwhole-program" -set profile_option [concat $common " -fprofile-generate"] -set feedback_option [concat $common " -fprofile-use -fipa-struct-reorg -fdump-ipa-all"] - -foreach src [lsort [glob -nocomplain $srcdir/$subdir/w_prof_*.c]] { - # If we're only testing specific files and this isn't one of them, skip it. - if ![runtest_file_p $runtests $src] then { - continue - } - profopt-execute $src -} - -set feedback_option [concat $feedback_option " --param struct-reorg-cold-struct-ratio=30"] - -foreach src [lsort [glob -nocomplain $srcdir/$subdir/w_ratio_*.c]] { - # If we're only testing specific files and this isn't one of them, skip it. - if ![runtest_file_p $runtests $src] then { - continue - } - profopt-execute $src -} +dg-finish diff -Nurp a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_str_init.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_str_init.c --- a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_str_init.c 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_str_init.c 2020-06-16 22:27:58.440000000 -0400 @@ -28,4 +28,4 @@ main () } /*--------------------------------------------------------------------------*/ -/* { dg-final { scan-ipa-dump "has escaped...Type is used in an array" "struct_reorg" } } */ +/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c b/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c --- a/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c 2020-06-16 22:27:58.440000000 -0400 @@ -38,5 +38,5 @@ main () } /*--------------------------------------------------------------------------*/ -/* The structure str_t is erroneously peeled into 4 structures instead of 2. */ -/* { dg-final { scan-ipa-dump "the number of new types is 2" "struct_reorg" } } */ +/* Two more fields structure is not splitted. */ +/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c b/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c --- a/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c 2020-06-16 22:27:58.440000000 -0400 @@ -26,4 +26,4 @@ main () } /*--------------------------------------------------------------------------*/ -/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c b/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c --- a/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c 2020-06-16 22:27:46.120000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c 2020-06-16 22:27:58.440000000 -0400 @@ -39,4 +39,4 @@ main () } /*--------------------------------------------------------------------------*/ -/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c b/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c --- a/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c 2020-06-16 22:27:46.124000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c 2020-06-16 22:27:58.472000000 -0400 @@ -34,4 +34,4 @@ main () } /*--------------------------------------------------------------------------*/ -/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c b/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c --- a/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c 2020-06-16 22:27:46.124000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c 2020-06-16 22:27:58.472000000 -0400 @@ -37,4 +37,4 @@ main () } /*--------------------------------------------------------------------------*/ -/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c b/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c --- a/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c 2020-06-16 22:27:46.124000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c 2020-06-16 22:27:58.472000000 -0400 @@ -28,4 +28,4 @@ main () } /*--------------------------------------------------------------------------*/ -/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c b/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c --- a/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c 2020-06-16 22:27:46.124000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c 2020-06-16 22:27:58.472000000 -0400 @@ -61,4 +61,4 @@ main () } /*--------------------------------------------------------------------------*/ -/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ diff -Nurp a/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c b/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c --- a/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c 2020-06-16 22:27:46.124000000 -0400 +++ b/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c 2020-06-16 22:27:58.472000000 -0400 @@ -40,4 +40,4 @@ main () /*--------------------------------------------------------------------------*/ /* Arrays are not handled. */ -/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ diff -Nurp a/gcc/testsuite/g++.dg/torture/pr38355.C b/gcc/testsuite/g++.dg/torture/pr38355.C --- a/gcc/testsuite/g++.dg/torture/pr38355.C 2020-06-16 22:27:46.124000000 -0400 +++ b/gcc/testsuite/g++.dg/torture/pr38355.C 1969-12-31 19:00:00.000000000 -0500 @@ -1,25 +0,0 @@ -// { dg-do run } -// { dg-options "-fwhole-program -fipa-struct-reorg" } -template struct A -{ - char c; - void foo(int); - void bar(int i) { foo(i+1); } -}; - -template struct B : virtual A<0> {}; - -template inline void baz(B& b, int i) -{ - if (i) b.bar(0); -} - -extern template class A<0>; -extern template void baz(B<0>&, int); - -int main() -{ - B<0> b; - baz(b, 0); - return 0; -}