加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0022-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch 42.31 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753
From 9d03b0a7741915e3a0172d60b9c21bf5abbda89e Mon Sep 17 00:00:00 2001
From: Mingchuan Wu <wumingchuan1992@foxmail.com>
Date: Mon, 28 Aug 2023 18:11:02 +0800
Subject: [PATCH 22/22] [DFE] Add Dead Field Elimination in Struct-Reorg.
We can transform gimple to eliminate fields that are never read
and replace the dead fields in stmt by creating a new ssa.
---
gcc/common.opt | 4 +
gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 240 +++++++++++++++++-
gcc/ipa-struct-reorg/ipa-struct-reorg.h | 8 +
gcc/opts.cc | 17 ++
gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c | 86 +++++++
.../gcc.dg/struct/dfe_ele_minus_verify.c | 60 +++++
.../gcc.dg/struct/dfe_extr_board_init.c | 77 ++++++
gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c | 84 ++++++
gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c | 56 ++++
gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c | 162 ++++++++++++
gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c | 126 +++++++++
.../gcc.dg/struct/dfe_extr_mv_udc_core.c | 82 ++++++
.../gcc.dg/struct/dfe_extr_tcp_usrreq.c | 58 +++++
.../gcc.dg/struct/dfe_extr_ui_main.c | 61 +++++
.../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 | 4 +
.../struct/wo_prof_escape_replace_type.c | 49 ++++
21 files changed, 1436 insertions(+), 7 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_extr_board_init.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.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
create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c
diff --git a/gcc/common.opt b/gcc/common.opt
index 14633c821..8bb735551 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1988,6 +1988,10 @@ fipa-struct-reorg
Common 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, 3)
+-fipa-struct-reorg=[0,1,2,3] adding none, struct-reorg, reorder-fields, dfe optimizations.
+
fipa-vrp
Common Var(flag_ipa_vrp) Optimization
Perform IPA Value Range Propagation.
diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
index 3e5f9538b..eac5fac7e 100644
--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
@@ -87,6 +87,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"
@@ -268,10 +269,43 @@ enum srmode
STRUCT_REORDER_FIELDS
};
+/* 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_SLO,
+ DEAD_FIELD_ELIMINATION
+};
+
static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
static bool isptrptr (tree type);
+void get_base (tree &base, tree expr);
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
@@ -353,7 +387,8 @@ srfield::srfield (tree field, srtype *base)
fielddecl (field),
base (base),
type (NULL),
- clusternum (0)
+ clusternum (0),
+ field_access (EMPTY_FIELD)
{
for (int i = 0; i < max_split; i++)
newfield[i] = NULL_TREE;
@@ -392,6 +427,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
@@ -595,7 +649,17 @@ srtype::analyze (void)
into 2 different structures. In future we intend to add profile
info and/or static heuristics to differentiate splitting process. */
if (fields.length () == 2)
- fields[1]->clusternum = 1;
+ {
+ /* Currently, when the replacement structure type exists,
+ we only split the replacement structure. */
+ for (hash_map<tree, tree>::iterator it = replace_type_map.begin ();
+ it != replace_type_map.end (); ++it)
+ {
+ if (types_compatible_p ((*it).second, this->type))
+ return;
+ }
+ fields[1]->clusternum = 1;
+ }
/* Otherwise we do nothing. */
if (fields.length () >= 3)
@@ -838,6 +902,10 @@ srtype::create_new_type (void)
for (unsigned i = 0; i < fields.length (); i++)
{
srfield *f = fields[i];
+ if (current_mode == STRUCT_REORDER_FIELDS
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION
+ && !(f->field_access & READ_FIELD))
+ continue;
f->create_new_fields (newtype, newfields, newlast);
}
@@ -856,6 +924,16 @@ srtype::create_new_type (void)
warn_padded = save_warn_padded;
+ if (current_mode == STRUCT_REORDER_FIELDS
+ && replace_type_map.get (this->newtype[0]) == NULL)
+ replace_type_map.put (this->newtype[0], this->type);
+ if (dump_file)
+ {
+ if (current_mode == STRUCT_REORDER_FIELDS
+ && 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);
@@ -1269,6 +1347,7 @@ public:
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
@@ -3057,6 +3136,119 @@ ipa_struct_reorg::find_vars (gimple *stmt)
}
}
+static HOST_WIDE_INT
+get_offset (tree op, HOST_WIDE_INT offset)
+{
+ switch (TREE_CODE (op))
+ {
+ case COMPONENT_REF:
+ {
+ return int_byte_position (TREE_OPERAND (op, 1));
+ }
+ case MEM_REF:
+ {
+ return tree_to_uhwi (TREE_OPERAND (op, 1));
+ }
+ default:
+ return offset;
+ }
+ return offset;
+}
+
+/* Record field access. */
+static void
+record_field_access (tree type, HOST_WIDE_INT offset,
+ unsigned access, void *data)
+{
+ srtype *this_srtype = ((ipa_struct_reorg *)data)->find_type (type);
+ if (this_srtype == NULL)
+ return;
+ srfield *this_srfield = this_srtype->find_field (offset);
+ 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, type);
+ fprintf (dump_file, " field:");
+ print_generic_expr (dump_file, this_srfield->fielddecl);
+ fprintf (dump_file, "\n");
+ }
+ return;
+
+}
+
+/* Update field_access in srfield. */
+
+static void
+update_field_access (tree node, tree op, unsigned access, void *data)
+{
+ HOST_WIDE_INT offset = 0;
+ offset = get_offset (op, offset);
+ tree node_type = inner_type (TREE_TYPE (node));
+ record_field_access (node_type, offset, access, data);
+ tree base = node;
+ get_base (base, node);
+ tree base_type = inner_type (TREE_TYPE (base));
+ if (!types_compatible_p (base_type, node_type))
+ {
+ record_field_access (base_type, get_offset (node, offset),
+ access, data);
+ }
+ return;
+}
+
+/* A callback for walk_stmt_load_store_ops to visit store. */
+
+static bool
+find_field_p_store (gimple *stmt ATTRIBUTE_UNUSED,
+ tree node, tree op, void *data)
+{
+ update_field_access (node, op, WRITE_FIELD, data);
+
+ return false;
+}
+
+/* A callback for walk_stmt_load_store_ops to visit load. */
+
+static bool
+find_field_p_load (gimple *stmt ATTRIBUTE_UNUSED,
+ tree node, tree op, void *data)
+{
+ update_field_access (node, op, 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)
+ return true;
+ return false;
+}
+
/* Maybe record access of statement for further analaysis. */
void
@@ -3078,6 +3270,13 @@ ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt)
default:
break;
}
+ if (current_mode == STRUCT_REORDER_FIELDS
+ && 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. */
@@ -3368,8 +3567,11 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other,
}
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
@@ -3949,8 +4151,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))
{
@@ -4216,7 +4419,9 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt,
}
srtype *t1 = find_type (inner_type (t));
- if (t1 == type)
+ /* In the other side check, escape mark is added
+ when the replacement struct type exists. */
+ if (t1 == type || is_replace_type (inner_type (t), type->type))
{
/* In Complete Struct Relayout, if lhs type is the same
as rhs type, we could return without any harm. */
@@ -5513,6 +5718,27 @@ bool
ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
{
bool remove = false;
+
+ if (current_mode == STRUCT_REORDER_FIELDS
+ && 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);
+ }
+ /* Replace the dead field in stmt by creating a dummy ssa. */
+ tree dummy_ssa = make_ssa_name (TREE_TYPE (gimple_assign_lhs (stmt)));
+ gimple_assign_set_lhs (stmt, dummy_ssa);
+ update_stmt (stmt);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "To: \n");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+ }
+
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 6f85adeb4..719f7b308 100644
--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
@@ -143,6 +143,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)
{
@@ -164,6 +165,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;
@@ -175,6 +182,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/opts.cc b/gcc/opts.cc
index c3cc2c169..b868d189e 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -2957,6 +2957,23 @@ common_handle_option (struct gcc_options *opts,
SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_correction, value);
break;
+ case OPT_fipa_struct_reorg_:
+ /* No break here - do -fipa-struct-reorg processing. */
+ /* FALLTHRU. */
+ case OPT_fipa_struct_reorg:
+ opts->x_flag_ipa_struct_reorg = value;
+ if (value && !opts->x_struct_layout_optimize_level)
+ {
+ /* Using the -fipa-struct-reorg option is equivalent to using
+ -fipa-struct-reorg=1. */
+ opts->x_struct_layout_optimize_level = 1;
+ }
+ break;
+
+ case OPT_fipa_reorder_fields:
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_struct_reorg, value);
+ break;
+
case OPT_fprofile_generate_:
opts->x_profile_data_prefix = xstrdup (arg);
value = true;
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..0c9e384c4
--- /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 "reorder_fields" } } */
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..717fcc386
--- /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 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c
new file mode 100644
index 000000000..7723c240b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c
@@ -0,0 +1,77 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_5__ TYPE_2__;
+typedef struct TYPE_4__ TYPE_1__;
+
+struct TYPE_4__
+{
+ int Pin;
+ int Pull;
+ int Mode;
+ int Speed;
+};
+
+struct TYPE_5__
+{
+ int MEMRMP;
+};
+typedef TYPE_1__ GPIO_InitTypeDef;
+
+int BT_RST_PIN;
+int BT_RST_PORT;
+int CONN_POS10_PIN;
+int CONN_POS10_PORT;
+int GPIO_HIGH (int, int);
+int GPIO_MODE_INPUT;
+int GPIO_MODE_OUTPUT_PP;
+int GPIO_NOPULL;
+int GPIO_PULLUP;
+int GPIO_SPEED_FREQ_LOW;
+int HAL_GPIO_Init (int, TYPE_1__ *);
+scalar_t__ IS_GPIO_RESET (int, int);
+TYPE_2__ *SYSCFG;
+int __HAL_RCC_GPIOB_CLK_ENABLE ();
+int __HAL_RCC_GPIOC_CLK_ENABLE ();
+
+__attribute__((used)) static void
+LBF_DFU_If_Needed (void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ __HAL_RCC_GPIOC_CLK_ENABLE ();
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStruct.Pin = BT_RST_PIN;
+ HAL_GPIO_Init (BT_RST_PORT, &GPIO_InitStruct);
+
+ GPIO_HIGH (BT_RST_PORT, BT_RST_PIN);
+ __HAL_RCC_GPIOB_CLK_ENABLE ();
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Pin = CONN_POS10_PIN;
+ HAL_GPIO_Init (CONN_POS10_PORT, &GPIO_InitStruct);
+
+ if (IS_GPIO_RESET (CONN_POS10_PORT, CONN_POS10_PIN))
+ {
+ SYSCFG->MEMRMP = 0x00000001;
+ asm (
+ "LDR R0, =0x000000\n\t"
+ "LDR SP, [R0, #0]\n\t"
+ );
+ asm (
+ "LDR R0, [R0, #0]\n\t"
+ "BX R0\n\t"
+ );
+ }
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c
new file mode 100644
index 000000000..a1feac966
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c
@@ -0,0 +1,84 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_2__ TYPE_1__;
+
+struct net_device
+{
+ struct claw_privbk* ml_priv;
+};
+struct clawctl
+{
+ int linkid;
+};
+struct claw_privbk
+{
+ int system_validate_comp;
+ TYPE_1__* p_env;
+ int ctl_bk;
+};
+typedef int __u8;
+struct TYPE_2__
+{
+ scalar_t__ packing;
+ int api_type;
+};
+
+int CLAW_DBF_TEXT (int, int, char*);
+int CONNECTION_REQUEST;
+int HOST_APPL_NAME;
+scalar_t__ PACKING_ASK;
+scalar_t__ PACK_SEND;
+int WS_APPL_NAME_IP_NAME;
+int WS_APPL_NAME_PACKED;
+int claw_send_control (struct net_device*, int, int, int, int, int, int);
+int setup;
+
+__attribute__((noinline)) int
+claw_send_control (struct net_device* net, int a, int b, int c, int d, int e,
+ int f)
+{
+ return net->ml_priv->system_validate_comp + a + b + c + d + f;
+}
+
+__attribute__((used)) static int
+claw_snd_conn_req (struct net_device *dev, __u8 link)
+{
+ int rc;
+ struct claw_privbk *privptr = dev->ml_priv;
+ struct clawctl *p_ctl;
+ CLAW_DBF_TEXT (2, setup, "snd_conn");
+ rc = 1;
+ p_ctl = (struct clawctl *)&privptr->ctl_bk;
+ p_ctl->linkid = link;
+ if (privptr->system_validate_comp == 0x00)
+ {
+ return rc;
+ }
+ if (privptr->p_env->packing == PACKING_ASK)
+ {
+ rc = claw_send_control (dev, CONNECTION_REQUEST, 0, 0, 0,
+ WS_APPL_NAME_PACKED, WS_APPL_NAME_PACKED);
+ }
+ if (privptr->p_env->packing == PACK_SEND)
+ {
+ rc = claw_send_control (dev, CONNECTION_REQUEST, 0, 0, 0,
+ WS_APPL_NAME_IP_NAME, WS_APPL_NAME_IP_NAME);
+ }
+ if (privptr->p_env->packing == 0)
+ {
+ rc = claw_send_control (dev, CONNECTION_REQUEST, 0, 0, 0,
+ HOST_APPL_NAME, privptr->p_env->api_type);
+ }
+ return rc;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c
new file mode 100644
index 000000000..fd1e936ca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c
@@ -0,0 +1,56 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_4__ TYPE_2__;
+typedef struct TYPE_3__ TYPE_1__;
+
+typedef int uint8_t;
+typedef int uint16_t;
+
+struct TYPE_4__
+{
+ size_t cpu_id;
+};
+
+struct TYPE_3__
+{
+ int cpuc_dtrace_flags;
+};
+
+TYPE_2__ *CPU;
+volatile int CPU_DTRACE_FAULT;
+TYPE_1__ *cpu_core;
+scalar_t__ dtrace_load8 (uintptr_t);
+
+__attribute__((used)) static int
+dtrace_bcmp (const void *s1, const void *s2, size_t len)
+{
+ volatile uint16_t *flags;
+ flags = (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
+ if (s1 == s2)
+ return (0);
+ if (s1 == NULL || s2 == NULL)
+ return (1);
+ if (s1 != s2 && len != 0)
+ {
+ const uint8_t *ps1 = s1;
+ const uint8_t *ps2 = s2;
+ do
+ {
+ if (dtrace_load8 ((uintptr_t)ps1++) != *ps2++)
+ return (1);
+ }
+ while (--len != 0 && !(*flags & CPU_DTRACE_FAULT));
+ }
+ return (0);
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c
new file mode 100644
index 000000000..b13d785a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c
@@ -0,0 +1,162 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+struct mrb_context
+{
+ size_t stack;
+ size_t stbase;
+ size_t stend;
+ size_t eidx;
+ int *ci;
+ int *cibase;
+ int status;
+};
+
+struct RObject
+{
+ int dummy;
+};
+
+struct RHash
+{
+ int dummy;
+};
+
+struct RFiber
+{
+ struct mrb_context *cxt;
+};
+
+struct RClass
+{
+ int dummy;
+};
+
+struct RBasic
+{
+ int tt;
+};
+
+struct RArray
+{
+ int dummy;
+};
+
+typedef int mrb_state;
+typedef int mrb_gc;
+typedef int mrb_callinfo;
+size_t ARY_LEN (struct RArray *);
+size_t MRB_ENV_STACK_LEN (struct RBasic *);
+int MRB_FIBER_TERMINATED;
+
+#define MRB_TT_ARRAY 140
+#define MRB_TT_CLASS 139
+#define MRB_TT_DATA 138
+#define MRB_TT_ENV 137
+#define MRB_TT_EXCEPTION 136
+#define MRB_TT_FIBER 135
+#define MRB_TT_HASH 134
+#define MRB_TT_ICLASS 133
+#define MRB_TT_MODULE 132
+#define MRB_TT_OBJECT 131
+#define MRB_TT_PROC 130
+#define MRB_TT_RANGE 129
+#define MRB_TT_SCLASS 128
+
+size_t ci_nregs (int *);
+int gc_mark_children (int *, int *, struct RBasic *);
+size_t mrb_gc_mark_hash_size (int *, struct RHash *);
+size_t mrb_gc_mark_iv_size (int *, struct RObject *);
+size_t mrb_gc_mark_mt_size (int *, struct RClass *);
+
+__attribute__((used)) static size_t
+gc_gray_mark (mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
+{
+ size_t children = 0;
+ gc_mark_children (mrb, gc, obj);
+ switch (obj->tt)
+ {
+ case MRB_TT_ICLASS:
+ children++;
+ break;
+
+ case MRB_TT_CLASS:
+ case MRB_TT_SCLASS:
+ case MRB_TT_MODULE:
+ {
+ struct RClass *c = (struct RClass *)obj;
+ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj);
+ children += mrb_gc_mark_mt_size (mrb, c);
+ children ++;
+ }
+ break;
+
+ case MRB_TT_OBJECT:
+ case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
+ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj);
+ break;
+
+ case MRB_TT_ENV:
+ children += MRB_ENV_STACK_LEN (obj);
+ break;
+
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber *)obj)->cxt;
+ size_t i;
+ mrb_callinfo *ci;
+ if (!c || c->status == MRB_FIBER_TERMINATED)
+ break;
+
+ i = c->stack - c->stbase;
+ if (c->ci)
+ {
+ i += ci_nregs (c->ci);
+ }
+ if (c->stbase + i > c->stend)
+ i = c->stend - c->stbase;
+
+ children += i;
+ children += c->eidx;
+ if (c->cibase)
+ {
+ for (i = 0, ci = c->cibase; ci <= c->ci; i++, ci++)
+ ;
+ }
+ children += i;
+ }
+ break;
+
+ case MRB_TT_ARRAY:
+ {
+ struct RArray *a = (struct RArray *)obj;
+ children += ARY_LEN (a);
+ }
+ break;
+
+ case MRB_TT_HASH:
+ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj);
+ children += mrb_gc_mark_hash_size (mrb, (struct RHash *)obj);
+ break;
+
+ case MRB_TT_PROC:
+ case MRB_TT_RANGE:
+ children += 2;
+ break;
+ default:
+ break;
+ }
+
+ return children;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c
new file mode 100644
index 000000000..bc28a658a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c
@@ -0,0 +1,126 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_6__ TYPE_3__;
+typedef struct TYPE_5__ TYPE_2__;
+typedef struct TYPE_4__ TYPE_1__;
+
+struct io_accel2_cmd
+{
+ int dummy;
+};
+
+struct hpsa_tmf_struct
+{
+ int it_nexus;
+};
+
+struct hpsa_scsi_dev_t
+{
+ int nphysical_disks;
+ int ioaccel_handle;
+ struct hpsa_scsi_dev_t **phys_disk;
+};
+
+struct ctlr_info
+{
+ TYPE_3__ *pdev;
+ struct io_accel2_cmd *ioaccel2_cmd_pool;
+};
+struct TYPE_4__
+{
+ int LunAddrBytes;
+};
+
+struct TYPE_5__
+{
+ TYPE_1__ LUN;
+};
+
+struct CommandList
+{
+ size_t cmdindex;
+ int cmd_type;
+ struct hpsa_scsi_dev_t *phys_disk;
+ TYPE_2__ Header;
+};
+
+struct TYPE_6__
+{
+ int dev;
+};
+
+int BUG ();
+#define CMD_IOACCEL1 132
+#define CMD_IOACCEL2 131
+#define CMD_IOCTL_PEND 130
+#define CMD_SCSI 129
+#define IOACCEL2_TMF 128
+int dev_err (int *, char *, int);
+scalar_t__ hpsa_is_cmd_idle (struct CommandList *);
+int le32_to_cpu (int);
+int test_memcmp (unsigned char *, int *, int);
+
+__attribute__((used)) static bool
+hpsa_cmd_dev_match (struct ctlr_info *h, struct CommandList *c,
+ struct hpsa_scsi_dev_t *dev, unsigned char *scsi3addr)
+{
+ int i;
+ bool match = false;
+ struct io_accel2_cmd * c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
+ struct hpsa_tmf_struct *ac = (struct hpsa_tmf_struct *)c2;
+
+ if (hpsa_is_cmd_idle (c))
+ return false;
+
+ switch (c->cmd_type)
+ {
+ case CMD_SCSI:
+ case CMD_IOCTL_PEND:
+ match = !test_memcmp (scsi3addr, &c->Header.LUN.LunAddrBytes,
+ sizeof (c->Header.LUN.LunAddrBytes));
+ break;
+
+ case CMD_IOACCEL1:
+ case CMD_IOACCEL2:
+ if (c->phys_disk == dev)
+ {
+ match = true;
+ }
+ else
+ {
+ for (i = 0; i < dev->nphysical_disks && !match; i++)
+ {
+ match = dev->phys_disk[i] == c->phys_disk;
+ }
+ }
+ break;
+
+ case IOACCEL2_TMF:
+ for (i = 0; i < dev->nphysical_disks && !match; i++)
+ {
+ match = dev->phys_disk[i]->ioaccel_handle ==
+ le32_to_cpu (ac->it_nexus);
+ }
+ break;
+
+ case 0:
+ match = false;
+ break;
+ default:
+ dev_err (&h->pdev->dev, "unexpected cmd_type: %d\n", c->cmd_type);
+ BUG ();
+ }
+
+ return match;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c
new file mode 100644
index 000000000..0a585ac3d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c
@@ -0,0 +1,82 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_4__ TYPE_2__;
+typedef struct TYPE_3__ TYPE_1__;
+typedef int u32;
+
+struct mv_udc
+{
+ TYPE_2__ *op_regs;
+ TYPE_1__ *ep_dqh;
+ struct mv_ep *eps;
+};
+
+struct mv_ep
+{
+ TYPE_1__ *dqh;
+ struct mv_udc *udc;
+};
+
+struct TYPE_4__
+{
+ int *epctrlx;
+};
+
+struct TYPE_3__
+{
+ int max_packet_length;
+ int next_dtd_ptr;
+};
+
+int EP0_MAX_PKT_SIZE;
+int EPCTRL_RX_ENABLE;
+int EPCTRL_RX_EP_TYPE_SHIFT;
+int EPCTRL_TX_ENABLE;
+int EPCTRL_TX_EP_TYPE_SHIFT;
+int EP_QUEUE_HEAD_IOS;
+int EP_QUEUE_HEAD_MAX_PKT_LEN_POS;
+int EP_QUEUE_HEAD_NEXT_TERMINATE;
+int USB_ENDPOINT_XFER_CONTROL;
+int readl (int *);
+int writel (int, int *);
+
+__attribute__((used)) static void
+ep0_reset (struct mv_udc *udc)
+{
+ struct mv_ep *ep;
+ u32 epctrlx;
+ int i = 0;
+ for (i = 0; i < 2; i++)
+ {
+ ep = &udc->eps[i];
+ ep->udc = udc;
+ ep->dqh = &udc->ep_dqh[i];
+ ep->dqh->max_packet_length =
+ (EP0_MAX_PKT_SIZE << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+ | EP_QUEUE_HEAD_IOS;
+ ep->dqh->next_dtd_ptr = EP_QUEUE_HEAD_NEXT_TERMINATE;
+ epctrlx = readl (&udc->op_regs->epctrlx[0]);
+ if (i)
+ {
+ epctrlx |= EPCTRL_TX_ENABLE
+ | (USB_ENDPOINT_XFER_CONTROL << EPCTRL_TX_EP_TYPE_SHIFT);
+ }
+ else
+ {
+ epctrlx |= EPCTRL_RX_ENABLE
+ | (USB_ENDPOINT_XFER_CONTROL << EPCTRL_RX_EP_TYPE_SHIFT);
+ }
+ writel (epctrlx, &udc->op_regs->epctrlx[0]);
+ }
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c
new file mode 100644
index 000000000..bddd862fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c
@@ -0,0 +1,58 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+struct tcpcb
+{
+ int t_state;
+};
+
+struct socket
+{
+ int dummy;
+};
+
+struct proc
+{
+ int dummy;
+};
+
+struct inpcb
+{
+ scalar_t__ inp_lport;
+};
+
+int COMMON_END (int);
+int COMMON_START ();
+int PRU_LISTEN;
+int TCPS_LISTEN;
+int in_pcbbind (struct inpcb *, int *, struct proc *);
+struct inpcb* sotoinpcb (struct socket *);
+
+__attribute__((used)) static void
+tcp_usr_listen (struct socket *so, struct proc *p)
+{
+ int error = 0;
+ struct inpcb *inp = sotoinpcb (so);
+ struct tcpcb *tp;
+
+ COMMON_START ();
+ if (inp->inp_lport == 0)
+ {
+ error = in_pcbbind (inp, NULL, p);
+ }
+ if (error == 0)
+ {
+ tp->t_state = TCPS_LISTEN;
+ }
+ COMMON_END (PRU_LISTEN);
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c
new file mode 100644
index 000000000..1a06f5eec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c
@@ -0,0 +1,61 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_4__ TYPE_2__;
+typedef struct TYPE_3__ TYPE_1__;
+
+struct TYPE_4__
+{
+ size_t modCount;
+ TYPE_1__ *modList;
+};
+
+struct TYPE_3__
+{
+ void *modDescr;
+ void *modName;
+};
+
+size_t MAX_MODS;
+void *String_Alloc (char *);
+int test_strlen (char *);
+int trap_FD_GetFileList (char *, char *, char *, int);
+TYPE_2__ uiInfo;
+
+__attribute__((used)) static void
+UI_LoadMods ()
+{
+ int numdirs;
+ char dirlist[2048];
+ char *dirptr;
+ char *descptr;
+ int i;
+ int dirlen;
+
+ uiInfo.modCount = 0;
+ numdirs = trap_FD_GetFileList ("$modelist", "", dirlist, sizeof (dirlist));
+ dirptr = dirlist;
+ for (i = 0; i < numdirs; i++)
+ {
+ dirlen = test_strlen (dirptr) + 1;
+ descptr = dirptr + dirlen;
+ uiInfo.modList[uiInfo.modCount].modName = String_Alloc (dirptr);
+ uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc (descptr);
+ dirptr += dirlen + test_strlen (descptr) + 1;
+ uiInfo.modCount++;
+ if (uiInfo.modCount >= MAX_MODS)
+ {
+ break;
+ }
+ }
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */
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..94eb88d5c
--- /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 "reorder_fields" } } */
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..bbf9420d0
--- /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 "reorder_fields" } } */
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..f706db968
--- /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 "reorder_fields" } } */
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..963295cb4
--- /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 "reorder_fields" } } */
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..aa10506a1
--- /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 "reorder_fields" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
index 5a476e8f9..6ccb753b5 100644
--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
@@ -43,6 +43,10 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \
gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf_*.c]] \
"" "-fipa-reorder-fields -fdump-ipa-all -flto-partition=one -fwhole-program"
+# -fipa-struct-reorg=3
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \
+ "" "-fipa-reorder-fields -fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program"
+
# All done.
torture-finish
dg-finish
diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c
new file mode 100644
index 000000000..fa8c66b9e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+
+#include <stdlib.h>
+
+struct AngleDef
+{
+ double K;
+ double th0;
+};
+typedef struct AngleDef angldef;
+
+struct bndangdihe
+{
+ int nbond;
+ int nangl;
+ int ndihe;
+};
+typedef struct bndangdihe bah;
+
+struct ambprmtop
+{
+ double *AnglK;
+ double *AnglEq;
+ bah nBAH;
+ angldef *AParam;
+ char source[512];
+ char eprulesource[512];
+};
+typedef struct ambprmtop prmtop;
+
+static void OrderBondParameters (prmtop *tp)
+{
+ int i;
+ tp->AParam = (angldef *)malloc (tp->nBAH.nangl * sizeof (angldef));
+ for (i = 0; i < tp->nBAH.nangl; i++)
+ {
+ tp->AParam[i].K = tp->AnglK[i];
+ tp->AParam[i].th0 = tp->AnglEq[i];
+ }
+}
+
+void main ()
+{
+ prmtop *tp = (prmtop *)malloc (100 * sizeof (prmtop));
+ OrderBondParameters (tp);
+}
+
+/*---------------------------------------------------------------------------------------------*/
+/* { dg-final { scan-ipa-dump "No structures to transform" "struct_reorg" } } */
--
2.33.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化