summaryrefslogtreecommitdiff
path: root/0016-StructReorg-Bugfix-in-certain-scenarios.patch
diff options
context:
space:
mode:
Diffstat (limited to '0016-StructReorg-Bugfix-in-certain-scenarios.patch')
-rw-r--r--0016-StructReorg-Bugfix-in-certain-scenarios.patch486
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
+