Projects
Mega:24.03:SP1:Everything
gcc
_service:tar_scm:0017-StructReorg-Some-bugfix-f...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0017-StructReorg-Some-bugfix-for-structure-reorganization.patch of Package gcc
From 2b4db34d3b21ff8597373e9e67858b3b60cc7dae Mon Sep 17 00:00:00 2001 From: eastb233 <xiezhiheng@huawei.com> Date: Fri, 21 Jul 2023 11:20:51 +0800 Subject: [PATCH 17/22] [StructReorg] Some bugfix for structure reorganization Some bugfix for structure reorganization, 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 --- gcc/ipa-free-lang-data.cc | 11 ++ gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 101 +++++++++++-------- gcc/symbol-summary.h | 13 ++- gcc/testsuite/gcc.dg/struct/struct_reorg-5.c | 31 ++++++ gcc/testsuite/gcc.dg/struct/struct_reorg-6.c | 54 ++++++++++ gcc/testsuite/gcc.dg/struct/struct_reorg-7.c | 38 +++++++ gcc/testsuite/gcc.dg/struct/struct_reorg-8.c | 25 +++++ gcc/testsuite/gcc.dg/struct/struct_reorg-9.c | 54 ++++++++++ 8 files changed, 283 insertions(+), 44 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-5.c create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-6.c create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-7.c create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-8.c create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-9.c diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc index a74215685..5450be9fe 100644 --- a/gcc/ipa-free-lang-data.cc +++ b/gcc/ipa-free-lang-data.cc @@ -102,6 +102,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 @@ -340,6 +346,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. */ diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc index c8b975a92..9f790b28b 100644 --- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc @@ -105,6 +105,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-param-manipulation.h" #include "gimplify-me.h" #include "cfgloop.h" +#include "langhooks.h" namespace { @@ -196,6 +197,39 @@ gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type, GSI_SAME_STMT); } +/* Check whether in C language or LTO with only C language. */ + +static 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, @@ -1018,7 +1052,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); @@ -2107,7 +2140,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)) @@ -2116,7 +2154,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 @@ -2796,8 +2839,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; } @@ -3731,42 +3780,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 @@ -4647,7 +4660,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 ()) @@ -4866,7 +4878,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 c54d3084c..3fe64047c 100644 --- a/gcc/symbol-summary.h +++ b/gcc/symbol-summary.h @@ -103,6 +103,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 () @@ -115,7 +121,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 000000000..273baa9a3 --- /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 000000000..455f9b501 --- /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 000000000..afc0bd86c --- /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 000000000..9bcfaf368 --- /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 000000000..052f4e3bd --- /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; +} -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2