summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorogolovanevsky <ogolovanevsky@ogolovanevsky-lnx.caveonetworks.com>2014-05-16 17:39:06 -0700
committerogolovanevsky <ogolovanevsky@ogolovanevsky-lnx.caveonetworks.com>2014-05-16 17:39:06 -0700
commit5409db70319c88dbf65a5f545d597b928e1832a8 (patch)
tree39013c3a185923b9602650ec7eb55465b331f693
parent173e24e00006cbd561d0b2733f25343fc5dd0b17 (diff)
downloadgcc-5409db70319c88dbf65a5f545d597b928e1832a8.tar.gz
Initial ipa-struct-reorg pass and struct_reorg_generate_summery function implementation.
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/expr.c17
-rwxr-xr-xgcc/ipa-struct-reorg.c643
-rwxr-xr-xgcc/ipa-struct-reorg.h112
-rw-r--r--gcc/passes.def1
-rw-r--r--gcc/timevar.def1
-rw-r--r--gcc/tree-pass.h1
-rw-r--r--gcc/tree.c15
-rw-r--r--gcc/tree.h4
10 files changed, 781 insertions, 20 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index daaeabd392a..fe056d13f07 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1278,6 +1278,7 @@ OBJS = \
ipa-pure-const.o \
ipa-reference.o \
ipa-ref.o \
+ ipa-struct-reorg.o \
ipa-utils.o \
ipa.o \
ira.o \
@@ -2244,7 +2245,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
$(srcdir)/reload.h $(srcdir)/caller-save.c $(srcdir)/symtab.c \
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
- $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-utils.h \
+ $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-struct-reorg.c $(srcdir)/ipa-utils.h \
$(srcdir)/dbxout.c \
$(srcdir)/dwarf2out.h \
$(srcdir)/dwarf2asm.c \
diff --git a/gcc/common.opt b/gcc/common.opt
index 411361cbbd3..a1034e17c68 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1409,8 +1409,8 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fipa-struct-reorg
-Common Ignore
-Does nothing. Preserved for backward compatibility.
+Common Report Var(flag_ipa_struct_reorg)
+Perform structure layout optimizations.
fira-algorithm=
Common Joined RejectNegative Enum(ira_algorithm) Var(flag_ira_algorithm) Init(IRA_ALGORITHM_CB)
diff --git a/gcc/expr.c b/gcc/expr.c
index ea23f199bda..1262f8481dd 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5869,23 +5869,6 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false);
}
-
-/* Returns the number of FIELD_DECLs in TYPE. */
-
-static int
-fields_length (const_tree type)
-{
- tree t = TYPE_FIELDS (type);
- int count = 0;
-
- for (; t; t = DECL_CHAIN (t))
- if (TREE_CODE (t) == FIELD_DECL)
- ++count;
-
- return count;
-}
-
-
/* Store the value of constructor EXP into the rtx TARGET.
TARGET is either a REG or a MEM; we know it cannot conflict, since
safe_from_p has been called.
diff --git a/gcc/ipa-struct-reorg.c b/gcc/ipa-struct-reorg.c
new file mode 100755
index 00000000000..fc47862a7f3
--- /dev/null
+++ b/gcc/ipa-struct-reorg.c
@@ -0,0 +1,643 @@
+/* Struct-reorg optimizations.
+ Copyright (C) 2007-2014 Free Software Foundation, Inc.
+ Contributed by Olga Golovanevsky <golovanevsky.olga@gmail.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "flags.h"
+#include "tree-pass.h"
+#include "print-tree.h" // for debug_tree
+#include "diagnostic.h"
+#include "ipa-struct-reorg.h"
+#include "tree-pretty-print.h"
+#include "cgraph.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "tree-ssa-alias.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+
+
+/* Vector of structures to be transformed. */
+typedef struct data_structure structure;
+vec<structure, va_heap, vl_ptr> *structures;
+
+/* Forward declarations. */
+static bool is_equal_types (tree type1, tree type2);
+
+/* Given a type TYPE, this function returns the name of the type. */
+
+static const char *
+get_type_name (tree type)
+{
+ if (! TYPE_NAME (type))
+ return NULL;
+
+ if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
+ return IDENTIFIER_POINTER (TYPE_NAME (type));
+ else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (type)))
+ return IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ else
+ return NULL;
+}
+
+/* This function returns true if two fields FIELD1 and FIELD2 are
+ semantically equal, and false otherwise. */
+
+static bool
+compare_fields (tree field1, tree field2)
+{
+ if (DECL_NAME (field1) && DECL_NAME (field2))
+ {
+ const char *name1 = IDENTIFIER_POINTER (DECL_NAME (field1));
+ const char *name2 = IDENTIFIER_POINTER (DECL_NAME (field2));
+
+ gcc_assert (name1 && name2);
+
+ if (strcmp (name1, name2))
+ return false;
+
+ }
+ else if (DECL_NAME (field1) || DECL_NAME (field2))
+ return false;
+
+ if (!is_equal_types (TREE_TYPE (field1), TREE_TYPE (field2)))
+ return false;
+
+ return true;
+}
+
+/* This function is a temporary hack to overcome the types problem.
+ When several compilation units are compiled together
+ with -combine, the TYPE_MAIN_VARIANT of the same type
+ can appear differently in different compilation units.
+ Therefore this function first compares type names.
+ If there are no names, structure bodies are recursively
+ compared. */
+
+static bool
+is_equal_types (tree type1, tree type2)
+{
+ const char * name1,* name2;
+
+ if ((!type1 && type2)
+ ||(!type2 && type1))
+ return false;
+
+ if (!type1 && !type2)
+ return true;
+
+ if (TREE_CODE (type1) != TREE_CODE (type2))
+ return false;
+
+ if (type1 == type2)
+ return true;
+
+ if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
+ return true;
+
+ name1 = get_type_name (type1);
+ name2 = get_type_name (type2);
+
+ if (name1 && name2)
+ return strcmp (name1, name2) == 0;
+
+ switch (TREE_CODE (type1))
+ {
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ {
+ return is_equal_types (TREE_TYPE (type1), TREE_TYPE (type2));
+ }
+ break;
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ case ENUMERAL_TYPE:
+ {
+ tree field1, field2;
+
+ /* Compare fields of structure. */
+ for (field1 = TYPE_FIELDS (type1), field2 = TYPE_FIELDS (type2);
+ field1 && field2;
+ field1 = TREE_CHAIN (field1), field2 = TREE_CHAIN (field2))
+ {
+ if (!compare_fields (field1, field2))
+ return false;
+ }
+ if (field1 || field2)
+ return false;
+ else
+ return true;
+ }
+ break;
+
+ case INTEGER_TYPE:
+ {
+ if (TYPE_UNSIGNED (type1) == TYPE_UNSIGNED (type2)
+ && TYPE_PRECISION (type1) == TYPE_PRECISION (type2))
+ return true;
+ }
+ break;
+
+ case ARRAY_TYPE:
+ {
+ tree d1, d2;
+ tree max1, min1, max2, min2;
+
+ if (!is_equal_types (TREE_TYPE (type1), TREE_TYPE (type2)))
+ return false;
+
+ d1 = TYPE_DOMAIN (type1);
+ d2 = TYPE_DOMAIN (type2);
+
+ if (!d1 || !d2)
+ return false;
+
+ max1 = TYPE_MAX_VALUE (d1);
+ max2 = TYPE_MAX_VALUE (d2);
+ min1 = TYPE_MIN_VALUE (d1);
+ min2 = TYPE_MIN_VALUE (d2);
+
+ if (max1 && max2 && min1 && min2
+ && TREE_CODE (max1) == TREE_CODE (max2)
+ && TREE_CODE (max1) == INTEGER_CST
+ && TREE_CODE (min1) == TREE_CODE (min2)
+ && TREE_CODE (min1) == INTEGER_CST
+ && tree_int_cst_equal (max1, max2)
+ && tree_int_cst_equal (min1, min2))
+ return true;
+ }
+ break;
+
+ default:
+ gcc_unreachable();
+ }
+
+ return false;
+}
+
+/* This function looks for d_str, represented by TYPE, in the structures
+ vector. If found, it returns an index of found structure. Otherwise
+ it returns a length of the structures vector. */
+
+static unsigned
+find_structure (tree type)
+{
+ d_str str;
+ unsigned i;
+
+ type = TYPE_MAIN_VARIANT (type);
+
+ FOR_EACH_VEC_ELT ((*structures), i, str)
+ if (is_equal_types (str->decl, type))
+ return i;
+
+ return structures->length ();
+}
+
+
+/* Given a structure declaration STRUCT_DECL, and number of fields
+ in the structure NUM_FIELDS, this function creates and returns
+ corresponding field_entry's. */
+
+static struct field_entry *
+get_fields (tree struct_decl, int num_fields)
+{
+ struct field_entry *list;
+ tree t = TYPE_FIELDS (struct_decl);
+ int idx = 0;
+
+ list = XNEWVEC (struct field_entry, num_fields);
+
+ for (idx = 0 ; t; t = TREE_CHAIN (t), idx++)
+ if (TREE_CODE (t) == FIELD_DECL)
+ {
+ list[idx].index = idx;
+ list[idx].decl = t;
+ list[idx].acc_sites = 0; //htab_create (32, field_acc_hash, field_acc_eq, NULL);
+ list[idx].count = 0;
+ list[idx].field_mapping = NULL_TREE;
+ }
+
+ return list;
+}
+
+
+/* This function adds a structure TYPE to the vector of structures,
+ if it's not already there. */
+
+static void
+add_structure (tree type)
+{
+ structure node;
+ unsigned i;
+ int num_fields;
+
+ type = TYPE_MAIN_VARIANT (type);
+
+ i = find_structure (type);
+
+ if (i != structures->length ()) {
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nType \"");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, "\" already in structures.");
+ }
+ return;
+ }
+
+ num_fields = fields_length (type);
+ node.decl = type;
+ node.num_fields = num_fields;
+ node.fields = get_fields (type, num_fields);
+ node.struct_clustering = NULL;
+ node.accs = 0; //htab_create (32, acc_hash, acc_eq, NULL);
+ node.new_types = 0; // node.new_types.create (num_fields);
+ node.count = 0;
+
+ structures->safe_push (node);
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nAdding data structure \"");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, "\" to data_struct_list.");
+ }
+}
+
+/* This function returns type of VAR. */
+
+static inline tree
+get_type_of_var (tree var)
+{
+ if (!var)
+ return NULL;
+
+ if (TREE_CODE (var) == PARM_DECL)
+ return DECL_ARG_TYPE (var);
+ else
+ return TREE_TYPE (var);
+}
+
+/* Strip structure TYPE from pointers and arrays. */
+
+static inline tree
+strip_type (tree type)
+{
+ gcc_assert (TYPE_P (type));
+
+ while (POINTER_TYPE_P (type)
+ || TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ return type;
+}
+
+
+/* Check whether the type of VAR is potential candidate for peeling.
+ Returns true if yes, false otherwise. If yes, TYPE_P will contain
+ candidate type. */
+
+static bool
+type_is_candidate (tree type, tree *type_p)
+{
+ *type_p = NULL;
+
+ if (!type)
+ return false;
+
+ if (type)
+ {
+ type = TYPE_MAIN_VARIANT (strip_type (type));
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return false;
+ else
+ {
+ *type_p = type;
+ return true;
+ }
+ }
+ else
+ return false;
+}
+
+/* Check whether the type of VAR is potential candidate for peeling.
+ Returns true if yes, false otherwise. If yes, TYPE_P will contain
+ candidate type. */
+
+static bool
+var_is_candidate (tree var, tree *type_p)
+{
+ tree type;
+
+ *type_p = NULL;
+
+ if (!var)
+ return false;
+
+ type = get_type_of_var (var);
+
+ return type_is_candidate (type, type_p);
+}
+
+/* This function looks for structure types instantiated in the program.
+ The candidate types are added to the structures vector. */
+
+static void
+build_data_structure (void)
+{
+ tree var, type, p;
+ struct varpool_node *current_varpool;
+ struct cgraph_node *c_node;
+ //struct cgraph_node *callee;
+ //struct cgraph_edge *edge;
+
+ /* Check global and static (global and local) variables. */
+ FOR_EACH_VARIABLE (current_varpool)
+ {
+ var = current_varpool->decl;
+
+ if (dump_file) {
+ fprintf (dump_file, "\nConsidering var: ");
+ print_generic_expr (dump_file, var, 0);
+ fprintf (dump_file, "\n");
+ }
+
+ if (var_is_candidate (var, &type)) {
+ if (dump_file) {
+ fprintf (dump_file, " Type ");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, " is candidate. Adding to list of candidates...\n");
+
+ }
+ add_structure (type);
+ } else {
+ if (dump_file) {
+ fprintf (dump_file, " Type ");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, "is not candidate. Skipping...\n");
+ }
+ }
+ }
+
+ /* Now add structures that are types of function parameters and
+ local variables. */
+ FOR_EACH_FUNCTION(c_node)
+ {
+ struct function *fn = DECL_STRUCT_FUNCTION (c_node->decl);
+ unsigned ix;
+
+
+ if (dump_file) {
+ fprintf (dump_file, "\nConsidering c_node: ");
+ dump_cgraph_node (dump_file, c_node);
+ fprintf (dump_file, "\n");
+ }
+
+
+ if (c_node->decl) {
+ if (dump_file) {
+ fprintf (dump_file, "\nFunc:");
+ print_generic_expr (dump_file, c_node->decl, 0);
+ }
+ }
+
+
+ for (p = TYPE_ARG_TYPES (TREE_TYPE(c_node->decl)); p; p = TREE_CHAIN (p))
+ {
+ tree arg_type = TREE_VALUE (p);
+ fprintf (dump_file, "\n\tArg:");
+ print_generic_expr (dump_file, arg_type, 0);
+ //debug_tree (arg_type);
+ if (type_is_candidate (arg_type, &type)) {
+ if (dump_file) {
+ fprintf (dump_file, " Type ");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, " is candidate. Adding to list of candidates...\n");
+ }
+ add_structure (type);
+ } else {
+ if (dump_file) {
+ fprintf (dump_file, " Type ");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, "is not candidate. Skipping...\n");
+ }
+ }
+ }
+
+ if (fn)
+ {
+ /* Check function local variables. */
+ FOR_EACH_LOCAL_DECL (fn, ix, var)
+ {
+ if (dump_file) {
+ fprintf (dump_file, "\nConsidering var: ");
+ print_generic_expr (dump_file, var, 0);
+ fprintf (dump_file, "\n");
+ }
+
+ if (var_is_candidate (var, &type)) {
+ if (dump_file) {
+ fprintf (dump_file, " Type ");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, " is candidate. Adding to list of candidates...\n");
+ }
+ add_structure (type);
+ } else {
+ if (dump_file) {
+ fprintf (dump_file, " Type ");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, "is not candidate. Skipping...\n");
+ }
+ }
+ }
+ }
+ }
+ /* Scan parameters of functions that have no forward declarations. */
+ FOR_EACH_DEFINED_FUNCTION(c_node)
+ {
+ struct function *fn = DECL_STRUCT_FUNCTION (c_node->decl);
+ basic_block bb;
+ gimple_stmt_iterator gsi;
+
+ FOR_EACH_BB_FN (bb, fn)
+ {
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+
+ if (is_gimple_call(stmt))
+ {
+ tree target = gimple_call_fndecl (stmt);
+ tree op;
+ unsigned int i;
+
+ if (dump_file) {
+ fprintf (dump_file, "\nTarget:");
+ print_generic_expr (dump_file, target, 0);
+ }
+
+ p = TYPE_ARG_TYPES (TREE_TYPE(target));
+ if (p) {
+ if (dump_file)
+ fprintf (dump_file, " Continuing...");
+ continue;
+ }
+
+ for (i = 0; i < gimple_num_ops (stmt); i++)
+ {
+ op = gimple_op (stmt, i);
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nOp %d:", i);
+ print_generic_expr (dump_file, op, 0);
+ debug_tree(op);
+ }
+
+ if (var_is_candidate (op, &type)) {
+ if (dump_file) {
+ fprintf (dump_file, " Type ");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, " is candidate. Adding to list of candidates...\n");
+
+ }
+ add_structure (type);
+ } else {
+ if (dump_file) {
+ fprintf (dump_file, " Type ");
+ print_generic_expr (dump_file, type, 0);
+ fprintf (dump_file, "is not candidate. Skipping...\n");
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+}
+
+/* This function collects structures potential
+ for peeling transformation, and inserts
+ them into structures hashtable. */
+
+static void
+collect_structures (void)
+{
+ vec_alloc (structures, 32);
+
+ /* Build data structures hashtable of all data structures
+ in the program. */
+ build_data_structure ();
+}
+
+static unsigned int
+propagate (void)
+{
+ return 0;
+}
+
+/* Deserialize the ipa info for lto. */
+
+static void
+struct_reorg_read_summary (void)
+{
+}
+
+/* Serialize the ipa info for lto. */
+
+static void
+struct_reorg_write_summary (void)
+{
+}
+
+/* Analyze each function in the cgraph. */
+
+static void
+struct_reorg_generate_summary (void)
+{
+
+ collect_structures ();
+
+}
+
+static bool
+gate_struct_reorg (void)
+{
+ return (flag_ipa_struct_reorg
+ /* Don't bother doing anything if the program has errors. */
+ && !seen_error ());
+}
+
+namespace {
+
+const pass_data pass_data_ipa_struct_reorg =
+{
+ IPA_PASS, /* type */
+ "struct-reorg", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_IPA_STRUCT_REORG, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_ipa_struct_reorg : public ipa_opt_pass_d
+{
+public:
+ pass_ipa_struct_reorg (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_struct_reorg, ctxt,
+ struct_reorg_generate_summary, /* generate_summary */
+ struct_reorg_write_summary, /* write_summary */
+ struct_reorg_read_summary, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_struct_reorg (); }
+ unsigned int execute () { return propagate (); }
+
+}; // class pass_ipa_struct_reorg
+
+} // anon namespace
+
+ipa_opt_pass_d *
+make_pass_ipa_struct_reorg (gcc::context *ctxt)
+{
+ return new pass_ipa_struct_reorg (ctxt);
+}
+
diff --git a/gcc/ipa-struct-reorg.h b/gcc/ipa-struct-reorg.h
new file mode 100755
index 00000000000..fd958a27bd7
--- /dev/null
+++ b/gcc/ipa-struct-reorg.h
@@ -0,0 +1,112 @@
+/* Struct-reorg optimizations.
+ Copyright (C) 2007-2014 Free Software Foundation, Inc.
+ Contributed by Olga Golovanevsky <golovanevsky.olga@gmail.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef IPA_STRUCT_REORG_H
+#define IPA_STRUCT_REORG_H
+
+/* This file contains data structures and interfaces required
+ for struct-reorg optimizations. */
+
+/* An access site of the structure field.
+ We consider an access to be of the following form:
+
+ D.2166_21 = i.6_20 * 8;
+ D.2167_22 = (struct str_t *) D.2166_21;
+ D.2168_24 = D.2167_22 + p.5_23;
+ D.2169_25 = D.2168_24->b;
+*/
+
+struct field_access_site
+{
+ /* Statement in which the access site occurs. */
+ gimple stmt; /* D.2169_25 = D.2168_24->b; */
+ tree comp_ref; /* D.2168_24->b */
+ tree field_decl; /* b */
+ tree ref; /* D.2168_24 */
+ tree num; /* i.6_20 */
+ tree offset; /* D2167_22 */
+ tree base; /* p.5_23 */
+ gimple ref_def_stmt; /* D.2168_24 = D.2167_22 + p.5_23; */
+ gimple cast_stmt; /* D.2167_22 = (struct str_t *) D.2166_21;
+ This statement is not always present. */
+};
+
+/* A non-field structure access site. */
+struct access_site
+{
+ /* A statement in which the access site occurs. */
+ gimple stmt;
+ /* A list of structure variables in the access site. */
+ vec<tree, va_heap, vl_ptr> *vars;
+};
+
+/* A field of the structure. */
+struct field_entry
+{
+ /* A field index. */
+ int index;
+ /* Number of times the field is accessed (according to profiling). */
+ gcov_type count;
+ tree decl;
+ /* A type of a new structure this field belongs to. */
+ tree field_mapping;
+ htab_t acc_sites;
+};
+
+/* This structure represents a result of the structure peeling.
+ The original structure is decomposed into substructures, or clusters. */
+struct field_cluster
+{
+ /* A bitmap of field indices. The set bit indicates that the field
+ corresponding to it is a part of this cluster. */
+ sbitmap fields_in_cluster;
+ struct field_cluster *sibling;
+};
+
+/* An information about an individual structure type (RECORD_TYPE) required
+ by struct-reorg optimizations to perform a transformation. */
+struct data_structure
+{
+
+ /* A main variant of the structure type. */
+ tree decl;
+
+ /* Number of fields in the structure. */
+ int num_fields;
+
+ /* A structure access count collected through profiling. */
+ gcov_type count;
+
+ /* An array of the structure fields, indexed by field ID. */
+ struct field_entry *fields;
+
+ /* Non-field accesses of the structure. */
+ htab_t accs;
+
+ /* A data structure representing a reorganization decision. */
+ struct field_cluster *struct_clustering;
+
+ /* New types to replace the original structure type. */
+ vec<tree, va_heap, vl_ptr> *new_types;
+};
+
+typedef struct data_structure *d_str;
+
+#endif /* IPA_STRUCT_REORG_H */
diff --git a/gcc/passes.def b/gcc/passes.def
index ee5feeee648..d58a0fbb972 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -111,6 +111,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_ipa_inline);
NEXT_PASS (pass_ipa_pure_const);
NEXT_PASS (pass_ipa_reference);
+ NEXT_PASS (pass_ipa_struct_reorg);
TERMINATE_PASS_LIST ()
/* Simple IPA passes executed after the regular passes. In WHOPR mode the
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 44a061af7f4..23a83cd2add 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -90,6 +90,7 @@ DEFTIMEVAR (TV_IPA_PROFILE , "ipa profile")
DEFTIMEVAR (TV_IPA_PURE_CONST , "ipa pure const")
DEFTIMEVAR (TV_IPA_PTA , "ipa points-to")
DEFTIMEVAR (TV_IPA_SRA , "ipa SRA")
+DEFTIMEVAR (TV_IPA_STRUCT_REORG , "ipa struct reorg")
DEFTIMEVAR (TV_IPA_FREE_LANG_DATA , "ipa free lang data")
DEFTIMEVAR (TV_IPA_FREE_INLINE_SUMMARY, "ipa free inline summary")
/* Time spent by constructing CFG. */
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index fb942724cb9..f1cca8cea26 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -478,6 +478,7 @@ extern ipa_opt_pass_d *make_pass_ipa_cp (gcc::context *ctxt);
extern ipa_opt_pass_d *make_pass_ipa_devirt (gcc::context *ctxt);
extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt);
extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_struct_reorg (gcc::context *ctxt);
extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt);
extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt);
extern simple_ipa_opt_pass *make_pass_omp_simd_clone (gcc::context *ctxt);
diff --git a/gcc/tree.c b/gcc/tree.c
index efee5e69cf2..fdeb7545b27 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2479,6 +2479,21 @@ list_length (const_tree t)
return len;
}
+/* Returns the number of FIELD_DECLs in TYPE. */
+
+int
+fields_length (const_tree type)
+{
+ tree t = TYPE_FIELDS (type);
+ int count = 0;
+
+ for (; t; t = DECL_CHAIN (t))
+ if (TREE_CODE (t) == FIELD_DECL)
+ ++count;
+
+ return count;
+}
+
/* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or
UNION_TYPE TYPE, or NULL_TREE if none. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 71d68321a55..4aa981efb7b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3843,6 +3843,10 @@ extern tree nreverse (tree);
extern int list_length (const_tree);
+/* Returns the number of FIELD_DECLs in a type. */
+
+extern int fields_length (const_tree);
+
/* Returns the first FIELD_DECL in a type. */
extern tree first_field (const_tree);