Projects
Mega:23.03
gcc
_service:tar_scm:0038-DFE-Add-Dead-Field-Elimin...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch of Package gcc
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
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