1 Star 0 Fork 117

yhl123123/gcc

forked from src-openEuler/gcc 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch 23.81 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
From edd4200e2b3e94d5c124900657b91c22dfe9c557 Mon Sep 17 00:00:00 2001
From: Mingchuan Wu <wumingchuan1992@foxmail.com>
Date: Wed, 15 Jun 2022 16:00:25 +0800
Subject: [PATCH 04/12] [DFE] Add Dead Field Elimination in Struct-Reorg.
We can transform gimple to eliminate fields that are never read
and remove their redundant stmts.
Also we adapted the partial escape_cast_another_ptr for struct relayout.
Add flag -fipa-struct-reorg=3 to enable dead field elimination.
---
gcc/common.opt | 4 +-
gcc/ipa-struct-reorg/ipa-struct-reorg.c | 209 ++++++++++++++++--
gcc/ipa-struct-reorg/ipa-struct-reorg.h | 9 +-
gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c | 86 +++++++
.../gcc.dg/struct/dfe_ele_minus_verify.c | 60 +++++
.../gcc.dg/struct/dfe_mem_ref_offset.c | 58 +++++
.../struct/dfe_mul_layer_ptr_record_bug.c | 30 +++
gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c | 71 ++++++
.../gcc.dg/struct/dfe_ptr_negate_expr.c | 55 +++++
gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c | 55 +++++
gcc/testsuite/gcc.dg/struct/struct-reorg.exp | 21 +-
11 files changed, 639 insertions(+), 19 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c
diff --git a/gcc/common.opt b/gcc/common.opt
index 7fc075d35..b5ea3c7a1 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1884,8 +1884,8 @@ Common Report Var(flag_ipa_struct_reorg) Init(0) Optimization
Perform structure layout optimizations.
fipa-struct-reorg=
-Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 2)
--fipa-struct-reorg=[0,1,2] adding none, struct-reorg, reorder-fields optimizations.
+Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 3)
+-fipa-struct-reorg=[0,1,2,3] adding none, struct-reorg, reorder-fields, dfe optimizations.
fipa-extend-auto-profile
Common Report Var(flag_ipa_extend_auto_profile)
diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
index 9214ee74a..2fa560239 100644
--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "gimple-pretty-print.h"
#include "gimple-iterator.h"
+#include "gimple-walk.h"
#include "cfg.h"
#include "ssa.h"
#include "tree-dfa.h"
@@ -238,11 +239,44 @@ enum srmode
STRUCT_LAYOUT_OPTIMIZE
};
+/* Enum the struct layout optimize level,
+ which should be the same as the option -fstruct-reorg=. */
+
+enum struct_layout_opt_level
+{
+ NONE = 0,
+ STRUCT_REORG,
+ STRUCT_REORDER_FIELDS,
+ DEAD_FIELD_ELIMINATION
+};
+
static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
bool isptrptr (tree type);
srmode current_mode;
+hash_map<tree, tree> replace_type_map;
+
+/* Return true if one of these types is created by struct-reorg. */
+
+static bool
+is_replace_type (tree type1, tree type2)
+{
+ if (replace_type_map.is_empty ())
+ return false;
+ if (type1 == NULL_TREE || type2 == NULL_TREE)
+ return false;
+ tree *type_value = replace_type_map.get (type1);
+ if (type_value)
+ if (types_compatible_p (*type_value, type2))
+ return true;
+ type_value = replace_type_map.get (type2);
+ if (type_value)
+ if (types_compatible_p (*type_value, type1))
+ return true;
+ return false;
+}
+
} // anon namespace
namespace struct_reorg {
@@ -318,12 +352,13 @@ srfunction::simple_dump (FILE *file)
/* Constructor of FIELD. */
srfield::srfield (tree field, srtype *base)
- : offset(int_byte_position (field)),
+ : offset (int_byte_position (field)),
fieldtype (TREE_TYPE (field)),
fielddecl (field),
- base(base),
- type(NULL),
- clusternum(0)
+ base (base),
+ type (NULL),
+ clusternum (0),
+ field_access (EMPTY_FIELD)
{
for(int i = 0;i < max_split; i++)
newfield[i] = NULL_TREE;
@@ -362,6 +397,25 @@ srtype::srtype (tree type)
}
}
+/* Check it if all fields in the RECORD_TYPE are referenced. */
+
+bool
+srtype::has_dead_field (void)
+{
+ bool may_dfe = false;
+ srfield *this_field;
+ unsigned i;
+ FOR_EACH_VEC_ELT (fields, i, this_field)
+ {
+ if (!(this_field->field_access & READ_FIELD))
+ {
+ may_dfe = true;
+ break;
+ }
+ }
+ return may_dfe;
+}
+
/* Mark the type as escaping type E at statement STMT. */
void
@@ -833,6 +887,10 @@ srtype::create_new_type (void)
for (unsigned i = 0; i < fields.length (); i++)
{
srfield *f = fields[i];
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION
+ && !(f->field_access & READ_FIELD))
+ continue;
f->create_new_fields (newtype, newfields, newlast);
}
@@ -854,6 +912,16 @@ srtype::create_new_type (void)
warn_padded = save_warn_padded;
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && replace_type_map.get (this->newtype[0]) == NULL)
+ replace_type_map.put (this->newtype[0], this->type);
+ if (dump_file)
+ {
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION
+ && has_dead_field ())
+ fprintf (dump_file, "Dead field elimination.\n");
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Created %d types:\n", maxclusters);
@@ -1128,12 +1196,12 @@ csrtype::init_type_info (void)
/* Close enough to pad to improve performance.
33~63 should pad to 64 but 33~48 (first half) are too far away, and
- 65~127 should pad to 128 but 65~96 (first half) are too far away. */
+ 65~127 should pad to 128 but 65~80 (first half) are too far away. */
if (old_size > 48 && old_size < 64)
{
new_size = 64;
}
- if (old_size > 96 && old_size < 128)
+ if (old_size > 80 && old_size < 128)
{
new_size = 128;
}
@@ -1272,6 +1340,7 @@ public:
bool has_rewritten_type (srfunction*);
void maybe_mark_or_record_other_side (tree side, tree other, gimple *stmt);
unsigned execute_struct_relayout (void);
+ bool remove_dead_field_stmt (tree lhs);
};
struct ipa_struct_relayout
@@ -3206,6 +3275,90 @@ ipa_struct_reorg::find_vars (gimple *stmt)
}
}
+/* Update field_access in srfield. */
+
+static void
+update_field_access (tree record, tree field, unsigned access, void *data)
+{
+ srtype *this_srtype = ((ipa_struct_reorg *)data)->find_type (record);
+ if (this_srtype == NULL)
+ return;
+ srfield *this_srfield = this_srtype->find_field (int_byte_position (field));
+ if (this_srfield == NULL)
+ return;
+
+ this_srfield->field_access |= access;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "record field access %d:", access);
+ print_generic_expr (dump_file, record);
+ fprintf (dump_file, " field:");
+ print_generic_expr (dump_file, field);
+ fprintf (dump_file, "\n");
+ }
+ return;
+}
+
+/* A callback for walk_stmt_load_store_ops to visit store. */
+
+static bool
+find_field_p_store (gimple *, tree node, tree op, void *data)
+{
+ if (TREE_CODE (op) != COMPONENT_REF)
+ return false;
+ tree node_type = TREE_TYPE (node);
+ if (!handled_type (node_type))
+ return false;
+
+ update_field_access (node_type, TREE_OPERAND (op, 1), WRITE_FIELD, data);
+
+ return false;
+}
+
+/* A callback for walk_stmt_load_store_ops to visit load. */
+
+static bool
+find_field_p_load (gimple *, tree node, tree op, void *data)
+{
+ if (TREE_CODE (op) != COMPONENT_REF)
+ return false;
+ tree node_type = TREE_TYPE (node);
+ if (!handled_type (node_type))
+ return false;
+
+ update_field_access (node_type, TREE_OPERAND (op, 1), READ_FIELD, data);
+
+ return false;
+}
+
+/* Determine whether the stmt should be deleted. */
+
+bool
+ipa_struct_reorg::remove_dead_field_stmt (tree lhs)
+{
+ tree base = NULL_TREE;
+ bool indirect = false;
+ srtype *t = NULL;
+ srfield *f = NULL;
+ bool realpart = false;
+ bool imagpart = false;
+ bool address = false;
+ bool escape_from_base = false;
+ if (!get_type_field (lhs, base, indirect, t, f, realpart, imagpart,
+ address, escape_from_base))
+ return false;
+ if (t ==NULL)
+ return false;
+ if (t->newtype[0] == t->type)
+ return false;
+ if (f == NULL)
+ return false;
+ if (f->newfield[0] == NULL
+ && (f->field_access & WRITE_FIELD))
+ return true;
+ return false;
+}
+
/* Maybe record access of statement for further analaysis. */
void
@@ -3227,6 +3380,13 @@ ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt)
default:
break;
}
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION)
+ {
+ /* Look for loads and stores. */
+ walk_stmt_load_store_ops (stmt, this, find_field_p_load,
+ find_field_p_store);
+ }
}
/* Calculate the multiplier. */
@@ -3543,8 +3703,11 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
}
else if (type != d->type)
{
- type->mark_escape (escape_cast_another_ptr, stmt);
- d->type->mark_escape (escape_cast_another_ptr, stmt);
+ if (!is_replace_type (d->type->type, type->type))
+ {
+ type->mark_escape (escape_cast_another_ptr, stmt);
+ d->type->mark_escape (escape_cast_another_ptr, stmt);
+ }
}
/* x_1 = y.x_nodes; void *x;
Directly mark the structure pointer type assigned
@@ -4131,8 +4294,9 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
}
/* If we have a non void* or a decl (which is hard to track),
then mark the type as escaping. */
- if (!VOID_POINTER_P (TREE_TYPE (newdecl))
- || DECL_P (newdecl))
+ if (replace_type_map.get (type->type) == NULL
+ && (!VOID_POINTER_P (TREE_TYPE (newdecl))
+ || DECL_P (newdecl)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -4142,7 +4306,7 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
print_generic_expr (dump_file, TREE_TYPE (newdecl));
fprintf (dump_file, "\n");
}
- type->mark_escape (escape_cast_another_ptr, stmt);
+ type->mark_escape (escape_cast_another_ptr, stmt);
return;
}
/* At this point there should only be unkown void* ssa names. */
@@ -4465,11 +4629,13 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
return;
}
+ if (!is_replace_type (t1->type, type->type))
+ {
+ if (t1)
+ t1->mark_escape (escape_cast_another_ptr, stmt);
- if (t1)
- t1->mark_escape (escape_cast_another_ptr, stmt);
-
- type->mark_escape (escape_cast_another_ptr, stmt);
+ type->mark_escape (escape_cast_another_ptr, stmt);
+ }
}
@@ -5722,6 +5888,19 @@ bool
ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
{
bool remove = false;
+
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION
+ && remove_dead_field_stmt (gimple_assign_lhs (stmt)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\n rewriting statement (remove): \n");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+ return true;
+ }
+
if (gimple_clobber_p (stmt))
{
tree lhs = gimple_assign_lhs (stmt);
diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
index 54b0dc655..936c0fa6f 100644
--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
@@ -142,6 +142,7 @@ public:
bool create_new_type (void);
void analyze (void);
+ bool has_dead_field (void);
void mark_escape (escape_type, gimple *stmt);
bool has_escaped (void)
{
@@ -163,6 +164,12 @@ public:
}
};
+/* Bitflags used for determining if a field
+ is never accessed, read or written. */
+const unsigned EMPTY_FIELD = 0x0u;
+const unsigned READ_FIELD = 0x01u;
+const unsigned WRITE_FIELD = 0x02u;
+
struct srfield
{
unsigned HOST_WIDE_INT offset;
@@ -174,7 +181,7 @@ struct srfield
unsigned clusternum;
tree newfield[max_split];
-
+ unsigned field_access; /* FIELD_DECL -> bitflag (use for dfe). */
// Constructors
srfield (tree field, srtype *base);
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c
new file mode 100644
index 000000000..4261d2352
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c
@@ -0,0 +1,86 @@
+/* { dg-do compile } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node node_t;
+typedef struct node *node_p;
+
+typedef struct arc arc_t;
+typedef struct arc *arc_p;
+
+typedef struct network
+{
+ arc_p arcs;
+ arc_p sorted_arcs;
+ int x;
+ node_p nodes;
+ node_p stop_nodes;
+} network_t;
+
+struct node
+{
+ int64_t potential;
+ int orientation;
+ node_p child;
+ node_p pred;
+ node_p sibling;
+ node_p sibling_prev;
+ arc_p basic_arc;
+ arc_p firstout;
+ arc_p firstin;
+ arc_p arc_tmp;
+ int64_t flow;
+ int64_t depth;
+ int number;
+ int time;
+};
+
+struct arc
+{
+ int id;
+ int64_t cost;
+ node_p tail;
+ node_p head;
+ short ident;
+ arc_p nextout;
+ arc_p nextin;
+ int64_t flow;
+ int64_t org_cost;
+ network_t* net_add;
+};
+
+
+const int MAX = 100;
+
+/* let it escape_array, "Type is used in an array [not handled yet]". */
+network_t* net[2];
+arc_p stop_arcs = NULL;
+
+int
+main ()
+{
+ net[0] = (network_t*) calloc (1, sizeof(network_t));
+ net[0]->arcs = (arc_p) calloc (MAX, sizeof (arc_t));
+ stop_arcs = (arc_p) calloc (MAX, sizeof (arc_t));
+
+ net[0]->arcs->id = 100;
+
+ for (unsigned i = 0; i < 3; i++)
+ {
+ net[0]->arcs->id = net[0]->arcs->id + 2;
+ stop_arcs->cost = net[0]->arcs->id / 2;
+ stop_arcs->net_add = net[0];
+ printf("stop_arcs->cost = %ld\n", stop_arcs->cost);
+ net[0]->arcs++;
+ stop_arcs++;
+ }
+
+ if( net[1] != 0 && stop_arcs != 0)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c
new file mode 100644
index 000000000..42d38c63a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c
@@ -0,0 +1,60 @@
+// verify newarc[cmp-1].flow
+/* { dg-do compile } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node node_t;
+typedef struct node *node_p;
+
+typedef struct arc arc_t;
+typedef struct arc *arc_p;
+
+struct node
+{
+ int64_t potential;
+ int orientation;
+ node_p child;
+ node_p pred;
+ node_p sibling;
+ node_p sibling_prev;
+ arc_p basic_arc;
+ arc_p firstout;
+ arc_p firstin;
+ arc_p arc_tmp;
+ int64_t flow;
+ int64_t depth;
+ int number;
+ int time;
+};
+
+struct arc
+{
+ int id;
+ int64_t cost;
+ node_p tail;
+ node_p head;
+ short ident;
+ arc_p nextout;
+ arc_p nextin;
+ int64_t flow;
+ int64_t org_cost;
+};
+
+const int MAX = 100;
+arc_p ap = NULL;
+
+int
+main ()
+{
+ ap = (arc_p) calloc(MAX, sizeof(arc_t));
+ printf("%d\n", ap[0].id);
+ for (int i = 1; i < MAX; i++)
+ {
+ ap[i-1].id = 500;
+ }
+ printf("%d\n", ap[0].id);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c b/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c
new file mode 100644
index 000000000..53583fe82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c
@@ -0,0 +1,58 @@
+/* Supports the MEM_REF offset.
+ _1 = MEM[(struct arc *)ap_4 + 72B].flow;
+ Old rewrite:_1 = ap.reorder.0_8->flow;
+ New rewrite:_1 = MEM[(struct arc.reorder.0 *)ap.reorder.0_8 + 64B].flow. */
+/* { dg-do compile } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node node_t;
+typedef struct node *node_p;
+
+typedef struct arc arc_t;
+typedef struct arc *arc_p;
+
+struct node
+{
+ int64_t potential;
+ int orientation;
+ node_p child;
+ node_p pred;
+ node_p sibling;
+ node_p sibling_prev;
+ arc_p basic_arc;
+ arc_p firstout;
+ arc_p firstin;
+ arc_p arc_tmp;
+ int64_t flow;
+ int64_t depth;
+ int number;
+ int time;
+};
+
+struct arc
+{
+ int id;
+ int64_t cost;
+ node_p tail;
+ node_p head;
+ short ident;
+ arc_p nextout;
+ arc_p nextin;
+ int64_t flow;
+ int64_t org_cost;
+};
+
+int
+main ()
+{
+ const int MAX = 100;
+ /* A similar scenario can be reproduced only by using local variables. */
+ arc_p ap = NULL;
+ ap = (arc_p) calloc(MAX, sizeof(arc_t));
+ printf("%d\n", ap[1].flow);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c b/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c
new file mode 100644
index 000000000..fd675ec2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct T_HASH_ENTRY
+{
+ unsigned int hash;
+ unsigned int klen;
+ char *key;
+} iHashEntry;
+
+typedef struct T_HASH
+{
+ unsigned int size;
+ unsigned int fill;
+ unsigned int keys;
+
+ iHashEntry **array;
+} uHash;
+
+uHash *retval;
+
+int
+main() {
+ retval->array = (iHashEntry **)calloc(sizeof(iHashEntry *), retval->size);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c
new file mode 100644
index 000000000..600e7908b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c
@@ -0,0 +1,71 @@
+// support POINTER_DIFF_EXPR & NOP_EXPR to avoid
+// escape_unhandled_rewrite, "Type escapes via a unhandled rewrite stmt"
+/* { dg-do compile } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node node_t;
+typedef struct node *node_p;
+
+typedef struct arc arc_t;
+typedef struct arc *arc_p;
+
+typedef struct network
+{
+ arc_p arcs;
+ arc_p sorted_arcs;
+ int x;
+ node_p nodes;
+ node_p stop_nodes;
+} network_t;
+
+struct node
+{
+ int64_t potential;
+ int orientation;
+ node_p child;
+ node_p pred;
+ node_p sibling;
+ node_p sibling_prev;
+ arc_p basic_arc;
+ arc_p firstout;
+ arc_p firstin;
+ arc_p arc_tmp;
+ int64_t flow;
+ int64_t depth;
+ int number;
+ int time;
+};
+
+struct arc
+{
+ int id;
+ int64_t cost;
+ node_p tail;
+ node_p head;
+ short ident;
+ arc_p nextout;
+ arc_p nextin;
+ int64_t flow;
+ int64_t org_cost;
+};
+
+int
+main ()
+{
+ arc_t *old_arcs;
+ node_t *node;
+ node_t *stop;
+ size_t off;
+ network_t* net;
+
+ for( ; node->number < stop->number; node++ )
+ {
+ off = node->basic_arc - old_arcs;
+ node->basic_arc = (arc_t *)(net->arcs + off);
+ }
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 3 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c
new file mode 100644
index 000000000..f411364a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c
@@ -0,0 +1,55 @@
+// support NEGATE_EXPR rewriting
+/* { dg-do compile } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node node_t;
+typedef struct node *node_p;
+
+typedef struct arc arc_t;
+typedef struct arc *arc_p;
+
+struct node
+{
+ int64_t potential;
+ int orientation;
+ node_p child;
+ node_p pred;
+ node_p sibling;
+ node_p sibling_prev;
+ arc_p basic_arc;
+ arc_p firstout;
+ arc_p firstin;
+ arc_p arc_tmp;
+ int64_t flow;
+ int64_t depth;
+ int number;
+ int time;
+};
+
+struct arc
+{
+ int id;
+ int64_t cost;
+ node_p tail;
+ node_p head;
+ short ident;
+ arc_p nextout;
+ arc_p nextin;
+ int64_t flow;
+ int64_t org_cost;
+};
+
+int
+main ()
+{
+ int64_t susp = 0;
+ const int MAX = 100;
+ arc_p ap = (arc_p) calloc(MAX, sizeof(arc_t));
+ ap -= susp;
+ printf("%d\n", ap[1].flow);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c
new file mode 100644
index 000000000..a4e723763
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c
@@ -0,0 +1,55 @@
+// release escape_ptr_ptr, "Type is used in a pointer to a pointer [not handled yet]";
+/* { dg-do compile } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node node_t;
+typedef struct node *node_p;
+
+typedef struct arc arc_t;
+typedef struct arc *arc_p;
+
+struct node
+{
+ int64_t potential;
+ int orientation;
+ node_p child;
+ node_p pred;
+ node_p sibling;
+ node_p sibling_prev;
+ arc_p basic_arc;
+ arc_p firstout;
+ arc_p firstin;
+ arc_p arc_tmp;
+ int64_t flow;
+ int64_t depth;
+ int number;
+ int time;
+};
+
+struct arc
+{
+ int id;
+ int64_t cost;
+ node_p tail;
+ node_p head;
+ short ident;
+ arc_p nextout;
+ arc_p nextin;
+ int64_t flow;
+ int64_t org_cost;
+};
+
+const int MAX = 100;
+arc_t **ap = NULL;
+
+int
+main ()
+{
+ ap = (arc_t**) malloc(MAX * sizeof(arc_t*));
+ (*ap)[0].id = 300;
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
index 67b3ac2d5..ac5585813 100644
--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
@@ -64,8 +64,27 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout
"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
# -fipa-struct-reorg=2
-gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/wo_prof_*.c]] \
"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_ratio_*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_prof_*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/struct_reorg*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/sr_*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+
+# -fipa-struct-reorg=3
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \
+ "" "-fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program"
+
# All done.
torture-finish
dg-finish
--
2.27.0.windows.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/yhl123123/gcc.git
git@gitee.com:yhl123123/gcc.git
yhl123123
gcc
gcc
master

搜索帮助

D67c1975 1850385 1daf7b77 1850385