This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, pretty-ipa]
- From: Martin Jambor <mjambor at suse dot cz>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Jan Hubicka <hubicka at ucw dot cz>
- Date: Thu, 2 Apr 2009 12:20:24 +0200
- Subject: [PATCH, pretty-ipa]
Hi,
the patch below updates DECL_VALUE_EXPR and BLOCK_NONLOCALIZED_VARS so
that dwarf2out can then still express the value of the aggregates
scalarized by intra-SRA. Basically, it stores there constructors
describing how to access individual leaf (i.e. non-aggregate) fields
(and array elements) there. create_debug_constructor uses callbacks
so that the function can be reused for IPA-SRA as well (I will post
this as a followup patch). Honza works on the dwarf2out bits.
It has bootstrapped and is currently being regression-tested on
x86_64-linux. OK for pretty-ipa if it passes?
Thanks,
Martin
2009-04-02 Martin Jambor <mjambor@suse.cz>
* ipa-sra.c: Include flags.h
(create_debug_constructor): New function.
(access_tree_debug_search): New function.
(intra_remap_nonlocalized_vars): New function.
(intra_store_all_debug_information): New function.
(perform_new_intra_sra): Call intra_store_all_debug_information.
Index: isra/gcc/ipa-sra.c
===================================================================
--- isra.orig/gcc/ipa-sra.c
+++ isra/gcc/ipa-sra.c
@@ -140,6 +140,8 @@ along with GCC; see the file COPYING3.
#include "params.h"
#include "target.h"
#include "ipa-utils.h"
+#include "flags.h"
+
/* Enumeration of all aggregate reductions we can do. */
enum sra_mode {SRA_MODE_EARLY_IPA,
@@ -2686,6 +2688,114 @@ convert_callers (struct cgraph_node *nod
return;
}
+/* Returns a constructor for aggregate of TYPE type which is a part of DECL at
+ offset OFFSET and accessible through EXPR. SEARCH is a callback function
+ which locates values given their offset and size. If EXPR is NULL, the
+ parts of the aggregate which have not been located by SEARCH have been
+ optimized out. Returns error_mark_node if something goes wrong and this
+ cannot be achieved, for example when array index bounds cannot be
+ edetermined. DATA is passed to SEARCH and not interpreted in any way. */
+
+static tree
+create_debug_constructor (tree type, tree decl, tree expr,
+ HOST_WIDE_INT offset,
+ tree (*search) (tree, HOST_WIDE_INT, HOST_WIDE_INT,
+ void *), void *data)
+{
+ tree fld, el, domain, index, max, tree_size;
+ HOST_WIDE_INT size;
+ VEC(constructor_elt,gc) *vals = VEC_alloc (constructor_elt, gc, 8);
+
+ gcc_assert (AGGREGATE_TYPE_P (type));
+
+ switch (TREE_CODE (type))
+ {
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ case RECORD_TYPE:
+ for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+ {
+ HOST_WIDE_INT pos;
+ tree fld_type, ref;
+ constructor_elt *elt;
+ tree value;
+
+ if (TREE_CODE (fld) != FIELD_DECL)
+ continue;
+ pos = int_bit_position (fld);
+ elt = VEC_safe_push (constructor_elt, gc, vals, NULL);
+ elt->index = fld;
+ if (expr)
+ ref = build3 (COMPONENT_REF, TREE_TYPE (fld), expr, fld,
+ NULL_TREE);
+ else
+ ref = NULL;
+ fld_type = TREE_TYPE (fld);
+ tree_size = TYPE_SIZE (TREE_TYPE (fld));
+ gcc_assert (tree_size && host_integerp (tree_size, 1));
+ size = tree_low_cst (tree_size, 1);
+
+ value = search (decl, offset + pos, size, data);
+ if (!value)
+ {
+ if (AGGREGATE_TYPE_P (fld_type))
+ value = create_debug_constructor (fld_type, decl, ref,
+ offset + pos, search, data);
+ else
+ value = ref;
+ }
+ elt->value = value;
+ }
+
+ break;
+ case ARRAY_TYPE:
+ domain = TYPE_DOMAIN (type);
+
+ if (!domain || !TYPE_MIN_VALUE (domain) || !TYPE_MAX_VALUE (domain))
+ return error_mark_node;
+
+ el = TREE_TYPE (type);
+ tree_size = TYPE_SIZE (el);
+ gcc_assert (tree_size && host_integerp (tree_size, 1));
+ size = tree_low_cst (tree_size, 1);
+ index = TYPE_MIN_VALUE (domain);
+ max = TYPE_MAX_VALUE (domain);
+ while (!tree_int_cst_lt (max, index))
+ {
+ constructor_elt *elt;
+ tree ref, value;
+
+ if (expr)
+ ref = build4 (ARRAY_REF, TREE_TYPE (type), expr, index,
+ NULL_TREE, NULL_TREE);
+ else
+ ref = NULL;
+
+ elt = VEC_safe_push (constructor_elt, gc, vals, NULL);
+ elt->index = index;
+
+ value = search (decl, offset, size, data);
+ if (!value)
+ {
+ if (AGGREGATE_TYPE_P (el))
+ value = create_debug_constructor (el, decl, ref, offset,
+ search, data);
+ else
+ value = ref;
+ }
+ elt->value = value;
+ offset += size;
+ index = int_const_binop (PLUS_EXPR, index, integer_one_node, 0);
+ }
+
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ return build_constructor (type, vals);
+}
+
/* Perform all the modification required in IPA-SRA for NODE to have parameters
as given in NOTES. */
@@ -3890,6 +4000,79 @@ initialize_parameter_reductions (void)
}
+/* Callback used by build_debug_constructor to locate a replacement in access
+ tree. */
+
+static tree
+access_tree_debug_search (tree decl, HOST_WIDE_INT offset,
+ HOST_WIDE_INT size, void *data ATTRIBUTE_UNUSED)
+{
+ struct access *access = get_var_base_offset_size_access (decl, offset, size);
+ if (access && access->to_be_replaced)
+ {
+ /* We read replacement_decl here directly because after the
+ function has been modified it really ought to exist. */
+ gcc_assert (access->replacement_decl);
+ return access->replacement_decl;
+ }
+ else
+ return NULL;
+}
+
+/* If any of values of NONLOCALIZED_VARS holds an aggregate that was split into
+ components by intra-SRA, replace it with an appropriate constructor. */
+
+static void
+intra_remap_nonlocalized_vars (tree block)
+{
+ int i, n;
+ tree t;
+
+ n = BLOCK_NUM_NONLOCALIZED_VARS (block);
+ for (i = 0; i < n; i++)
+ {
+ tree var = BLOCK_NONLOCALIZED_VAR_VALUE (block, i);
+
+ if (var && DECL_P (var)
+ && bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
+ {
+ BLOCK_NONLOCALIZED_VAR_VALUE (block, i)
+ = create_debug_constructor (TREE_TYPE (var), var, var, 0,
+ access_tree_debug_search, NULL);
+ }
+ }
+
+ for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
+ intra_remap_nonlocalized_vars (t);
+}
+
+/* Store information describing how aggregates were reduced by intra-SRA to be
+ used later when generating debug info, if the debug info level requires it
+ it. */
+
+static void
+intra_store_all_debug_information (void)
+{
+ tree var;
+ referenced_var_iterator rvi;
+
+ if (debug_info_level <= DINFO_LEVEL_TERSE)
+ return;
+
+ FOR_EACH_REFERENCED_VAR (var, rvi)
+ {
+ if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
+ {
+ tree cst;
+
+ cst = create_debug_constructor (TREE_TYPE (var), var, var, 0,
+ access_tree_debug_search, NULL);
+ SET_DECL_VALUE_EXPR (var, cst);
+ }
+ }
+
+ intra_remap_nonlocalized_vars (DECL_INITIAL (current_function_decl));
+}
/* The "main" function of intraprocedural SRA passes. Runs the analysis and if
it reveals there are components of some aggregates to be scalarized, it runs
@@ -3913,6 +4096,7 @@ perform_new_intra_sra (void)
scan_function (sra_intra_modify_expr, sra_intra_modify_assign, NULL,
false, NULL);
initialize_parameter_reductions ();
+ intra_store_all_debug_information();
if (sra_mode == SRA_MODE_EARLY_INTRA)
ret = TODO_update_ssa;
Index: isra/gcc/Makefile.in
===================================================================
--- isra.orig/gcc/Makefile.in
+++ isra/gcc/Makefile.in
@@ -2614,7 +2614,7 @@ ipa-inline.o : ipa-inline.c gt-ipa-inlin
ipa-sra.o : ipa-sra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GIMPLE_H) $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) $(TREE_FLOW_H) \
$(DIAGNOSTIC_H) $(TREE_DUMP_H) $(IPA_PROP_H) $(TIMEVAR_H) $(TARGET_H) \
- tree-pass.h $(PARAMS_H)
+ tree-pass.h $(PARAMS_H) $(FLAGS_H)
ipa-utils.o : ipa-utils.c $(IPA_UTILS_H) $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \