diff options
Diffstat (limited to '0016-StructReorg-Bugfix-in-certain-scenarios.patch')
-rw-r--r-- | 0016-StructReorg-Bugfix-in-certain-scenarios.patch | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/0016-StructReorg-Bugfix-in-certain-scenarios.patch b/0016-StructReorg-Bugfix-in-certain-scenarios.patch new file mode 100644 index 0000000..f16f352 --- /dev/null +++ b/0016-StructReorg-Bugfix-in-certain-scenarios.patch @@ -0,0 +1,486 @@ +From 2194d59a20be1ab627089d2f0c082b5a0a217f52 Mon Sep 17 00:00:00 2001 +From: xiezhiheng <xiezhiheng@huawei.com> +Date: Tue, 3 Aug 2021 03:49:52 -0400 +Subject: [PATCH 16/22] [StructReorg] Bugfix in certain scenarios + +Some bugfix in certain scenarios, +1. disable type simplify in LTO within optimizations +2. only enable optimizations in C language +3. use new to initialize allocated memory in symbol-summary.h +4. cover escape scenarios not considered + +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c +index 5a19ea0bb40..1cb544ec3b0 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c +@@ -97,6 +97,7 @@ along with GCC; see the file COPYING3. If not see + #include "tree-eh.h" + #include "bitmap.h" + #include "cfgloop.h" ++#include "langhooks.h" + #include "ipa-param-manipulation.h" + #include "tree-ssa-live.h" /* For remove_unused_locals. */ + +@@ -161,6 +162,44 @@ handled_type (tree type) + return false; + } + ++/* Check whether in C language or LTO with only C language. */ ++bool ++lang_c_p (void) ++{ ++ const char *language_string = lang_hooks.name; ++ ++ if (!language_string) ++ { ++ return false; ++ } ++ ++ if (strcmp (language_string, "GNU GIMPLE") == 0) ++ { ++ unsigned i = 0; ++ tree t = NULL; ++ const char *unit_string = NULL; ++ ++ FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, t) ++ { ++ unit_string = TRANSLATION_UNIT_LANGUAGE (t); ++ if (!unit_string ++ || (strncmp (unit_string, "GNU C", 5) != 0) ++ || (!ISDIGIT (unit_string[5]))) ++ { ++ return false; ++ } ++ } ++ return true; ++ } ++ else if (strncmp (language_string, "GNU C", 5) == 0 ++ && ISDIGIT (language_string[5])) ++ { ++ return true; ++ } ++ ++ return false; ++} ++ + enum srmode + { + NORMAL = 0, +@@ -999,7 +1038,6 @@ public: + 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); +@@ -2127,7 +2165,12 @@ ipa_struct_reorg::find_vars (gimple *stmt) + srtype *t = find_type (inner_type (TREE_TYPE (rhs))); + srdecl *d = find_decl (lhs); + if (!d && t) +- current_function->record_decl (t, lhs, -1); ++ { ++ current_function->record_decl (t, lhs, -1); ++ tree var = SSA_NAME_VAR (lhs); ++ if (var && VOID_POINTER_P (TREE_TYPE (var))) ++ current_function->record_decl (t, var, -1); ++ } + } + if (TREE_CODE (rhs) == SSA_NAME + && VOID_POINTER_P (TREE_TYPE (rhs)) +@@ -2136,7 +2179,12 @@ ipa_struct_reorg::find_vars (gimple *stmt) + srtype *t = find_type (inner_type (TREE_TYPE (lhs))); + srdecl *d = find_decl (rhs); + if (!d && t) +- current_function->record_decl (t, rhs, -1); ++ { ++ current_function->record_decl (t, rhs, -1); ++ tree var = SSA_NAME_VAR (rhs); ++ if (var && VOID_POINTER_P (TREE_TYPE (var))) ++ current_function->record_decl (t, var, -1); ++ } + } + } + else +@@ -2816,8 +2864,14 @@ ipa_struct_reorg::maybe_record_call (cgraph_node *node, gcall *stmt) + if (escapes != does_not_escape) + { + for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) +- mark_type_as_escape (TREE_TYPE (gimple_call_arg (stmt, i)), +- escapes); ++ { ++ mark_type_as_escape (TREE_TYPE (gimple_call_arg (stmt, i)), ++ escapes); ++ srdecl *d = current_function->find_decl ( ++ gimple_call_arg (stmt, i)); ++ if (d) ++ d->type->mark_escape (escapes, stmt); ++ } + return; + } + +@@ -3753,49 +3807,6 @@ 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 +@@ -4652,7 +4663,6 @@ ipa_struct_reorg::rewrite_functions (void) + { + 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 ()) +@@ -4887,7 +4897,10 @@ pass_ipa_struct_reorg::gate (function *) + && flag_ipa_struct_reorg + /* Don't bother doing anything if the program has errors. */ + && !seen_error () +- && flag_lto_partition == LTO_PARTITION_ONE); ++ && flag_lto_partition == LTO_PARTITION_ONE ++ /* Only enable struct optimizations in C since other ++ languages' grammar forbid. */ ++ && lang_c_p ()); + } + + } // anon namespace +diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h +index fa1df5c8015..a223b4dadea 100644 +--- a/gcc/symbol-summary.h ++++ b/gcc/symbol-summary.h +@@ -59,6 +59,12 @@ protected: + /* Allocates new data that are stored within map. */ + T* allocate_new () + { ++ /* In structure optimizatons, we call new to ensure that ++ the allocated memory is initialized to 0. */ ++ if (flag_ipa_struct_reorg) ++ return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () ++ : new T (); ++ + /* Call gcc_internal_because we do not want to call finalizer for + a type T. We call dtor explicitly. */ + return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () +@@ -71,7 +77,12 @@ protected: + if (is_ggc ()) + ggc_delete (item); + else +- m_allocator.remove (item); ++ { ++ if (flag_ipa_struct_reorg) ++ delete item; ++ else ++ m_allocator.remove (item); ++ } + } + + /* Unregister all call-graph hooks. */ +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-5.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-5.c +new file mode 100644 +index 00000000000..273baa9a368 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-5.c +@@ -0,0 +1,31 @@ ++/* { dg-do compile } */ ++/* { dg-additional-options "-flto -fno-use-linker-plugin" } */ ++ ++struct D ++{ ++ int n; ++ int c [8]; ++}; ++ ++struct A ++{ ++ int i; ++ char *p; ++}; ++ ++struct B ++{ ++ struct A *a; ++ struct D *d; ++}; ++ ++int dtInsert1 (struct B *b) ++{ ++ struct A a = { 0, 0 }; ++ struct D *d; ++ b->a = &a; ++ d = b->d; ++ &d->c [d->n]; ++ return 0; ++} ++ +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-6.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-6.c +new file mode 100644 +index 00000000000..455f9b501d6 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-6.c +@@ -0,0 +1,54 @@ ++/* { dg-do compile } */ ++/* { dg-additional-options "-flto -fno-use-linker-plugin" } */ ++ ++typedef struct basic_block_def *basic_block; ++typedef struct gimple_seq_node_d *gimple_seq_node; ++typedef struct gimple_seq_d *gimple_seq; ++typedef struct ++{ ++ gimple_seq_node ptr; ++ gimple_seq seq; ++ basic_block bb; ++} gimple_stmt_iterator; ++typedef void *gimple; ++extern void exit(int); ++struct gimple_seq_node_d ++{ ++ gimple stmt; ++ struct gimple_seq_node_d *next; ++}; ++struct gimple_seq_d ++{ ++}; ++static __inline__ gimple_stmt_iterator ++gsi_start (gimple_seq seq) ++{ ++ gimple_stmt_iterator i; ++ i.seq = seq; ++ return i; ++} ++static __inline__ unsigned char ++gsi_end_p (gimple_stmt_iterator i) ++{ ++ return i.ptr == ((void *)0); ++} ++static __inline__ void ++gsi_next (gimple_stmt_iterator *i) ++{ ++ i->ptr = i->ptr->next; ++} ++static __inline__ gimple ++gsi_stmt (gimple_stmt_iterator i) ++{ ++ return i.ptr->stmt; ++} ++void ++c_warn_unused_result (gimple_seq seq) ++{ ++ gimple_stmt_iterator i; ++ for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i)) ++ { ++ gimple g = gsi_stmt (i); ++ if (!g) exit(0); ++ } ++} +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-7.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-7.c +new file mode 100644 +index 00000000000..afc0bd86ca5 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-7.c +@@ -0,0 +1,38 @@ ++/* { dg-do run } */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++ ++struct gki_elem { ++ char *key; ++ int idx; ++}; ++ ++typedef struct { ++ struct gki_elem *table; ++ ++ int primelevel; ++ int nhash; ++ int nkeys; ++} GKI; ++ ++void * ++sre_malloc(size_t size) ++{ ++ void *ptr = malloc (size); ++ return ptr; ++} ++ ++__attribute__((noinline)) int ++GKIStoreKey(GKI *hash) ++{ ++ hash->table = sre_malloc(sizeof(struct gki_elem)); ++} ++ ++int ++main () ++{ ++ GKI *hash = malloc (sizeof(GKI)); ++ GKIStoreKey(hash); ++ return 0; ++} +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-8.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-8.c +new file mode 100644 +index 00000000000..9bcfaf3681b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-8.c +@@ -0,0 +1,25 @@ ++/* { dg-do run } */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++typedef struct { ++ unsigned char blue; ++ unsigned char green; ++} Pixel; ++ ++typedef struct { ++ unsigned short colormaplength; ++ Pixel *colormapdata; ++} TargaImage; ++ ++TargaImage *img; ++ ++int main() { ++ img = (TargaImage *) malloc( sizeof(TargaImage) ); ++ if (img->colormaplength > 0) { ++ img->colormapdata = (Pixel *) malloc(sizeof(Pixel) * img->colormaplength); ++ memset(img->colormapdata, 0, (sizeof(Pixel) * img->colormaplength) ); ++ } ++} +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-9.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-9.c +new file mode 100644 +index 00000000000..052f4e3bdc1 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-9.c +@@ -0,0 +1,54 @@ ++/* { dg-do run } */ ++ ++extern void abort(void); ++ ++struct packed_ushort { ++ unsigned short ucs; ++} __attribute__((packed)); ++ ++struct source { ++ int pos, length; ++}; ++ ++static int flag; ++ ++static void __attribute__((noinline)) fetch(struct source *p) ++{ ++ p->length = 128; ++} ++ ++static struct packed_ushort __attribute__((noinline)) next(struct source *p) ++{ ++ struct packed_ushort rv; ++ ++ if (p->pos >= p->length) { ++ if (flag) { ++ flag = 0; ++ fetch(p); ++ return next(p); ++ } ++ flag = 1; ++ rv.ucs = 0xffff; ++ return rv; ++ } ++ rv.ucs = 0; ++ return rv; ++} ++ ++int main(void) ++{ ++ struct source s; ++ int i; ++ ++ s.pos = 0; ++ s.length = 0; ++ flag = 0; ++ ++ for (i = 0; i < 16; i++) { ++ struct packed_ushort rv = next(&s); ++ if ((i == 0 && rv.ucs != 0xffff) ++ || (i > 0 && rv.ucs != 0)) ++ abort(); ++ } ++ return 0; ++} +diff --git a/gcc/tree.c b/gcc/tree.c +index 3c17694c703..5c1374d6fb1 100644 +--- a/gcc/tree.c ++++ b/gcc/tree.c +@@ -5216,6 +5216,12 @@ fld_worklist_push (tree t, class free_lang_data_d *fld) + static tree + fld_simplified_type_name (tree type) + { ++ /* Simplify type will cause that struct A and struct A within ++ struct B are different type pointers, so skip it in structure ++ optimizations. */ ++ if (flag_ipa_struct_reorg) ++ return TYPE_NAME (type); ++ + if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL) + return TYPE_NAME (type); + /* Drop TYPE_DECLs in TYPE_NAME in favor of the identifier in the +@@ -5454,6 +5460,11 @@ fld_simplified_type (tree t, class free_lang_data_d *fld) + { + if (!t) + return t; ++ /* Simplify type will cause that struct A and struct A within ++ struct B are different type pointers, so skip it in structure ++ optimizations. */ ++ if (flag_ipa_struct_reorg) ++ return t; + if (POINTER_TYPE_P (t)) + return fld_incomplete_type_of (t, fld); + /* FIXME: This triggers verification error, see PR88140. */ +-- +2.21.0.windows.1 + |