aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2010-05-04 19:34:01 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2010-05-04 19:34:01 +0200
commit6cbd3b6a699912ff879d13c0fb5ab3f4b244943f (patch)
treefbf0e8c6815f54c2f72fc7d9a758ef50fc3da37e
parented24bfdf685375d4f82f7da01c3233e8f0898b88 (diff)
downloadgcc-6cbd3b6a699912ff879d13c0fb5ab3f4b244943f.zip
gcc-6cbd3b6a699912ff879d13c0fb5ab3f4b244943f.tar.gz
gcc-6cbd3b6a699912ff879d13c0fb5ab3f4b244943f.tar.bz2
tree-sra.c (build_access_from_expr_1): The first parameter type changed to simple tree.
2010-05-04 Martin Jambor <mjambor@suse.cz> * tree-sra.c (build_access_from_expr_1): The first parameter type changed to simple tree. (build_access_from_expr): Likewise, gsi parameter was eliminated. (scan_assign_result): Renamed to assignment_mod_result, enum elements renamed as well. (build_accesses_from_assign): Removed all parameters except for a simple gimple statement. Now returns a simple bool. (scan_function): All non-analysis parts moved to separate functions sra_modify_function_body and ipa_sra_modify_function_body. Removed all parameters and updated both callers. (sra_modify_expr): Removed parameter data. (sra_modify_function_body): New function. (perform_intra_sra): Call sra_modify_function_body to modify the function body. (replace_removed_params_ssa_names): Parameter data changed into adjustments vector. (sra_ipa_modify_expr): Likewise. Also removed unused parameter gsi and changed the parameter dont_convert to convert with the opposite meaning. (sra_ipa_modify_assign): Parameter data changed into adjustments vector, return value changed to bool. (ipa_sra_modify_function_body): New function. (sra_ipa_reset_debug_stmts): Updated a comment. (modify_function): Use ipa_sra_modify_function_body to modify function body. From-SVN: r159038
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/tree-sra.c468
2 files changed, 303 insertions, 193 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a93e111..41139cb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,31 @@
+2010-05-04 Martin Jambor <mjambor@suse.cz>
+
+ * tree-sra.c (build_access_from_expr_1): The first parameter type
+ changed to simple tree.
+ (build_access_from_expr): Likewise, gsi parameter was eliminated.
+ (scan_assign_result): Renamed to assignment_mod_result, enum elements
+ renamed as well.
+ (build_accesses_from_assign): Removed all parameters except for a
+ simple gimple statement. Now returns a simple bool.
+ (scan_function): All non-analysis parts moved to separate functions
+ sra_modify_function_body and ipa_sra_modify_function_body. Removed all
+ parameters and updated both callers.
+ (sra_modify_expr): Removed parameter data.
+ (sra_modify_function_body): New function.
+ (perform_intra_sra): Call sra_modify_function_body to modify the
+ function body.
+ (replace_removed_params_ssa_names): Parameter data changed into
+ adjustments vector.
+ (sra_ipa_modify_expr): Likewise. Also removed unused parameter gsi and
+ changed the parameter dont_convert to convert with the opposite
+ meaning.
+ (sra_ipa_modify_assign): Parameter data changed into adjustments
+ vector, return value changed to bool.
+ (ipa_sra_modify_function_body): New function.
+ (sra_ipa_reset_debug_stmts): Updated a comment.
+ (modify_function): Use ipa_sra_modify_function_body to modify function
+ body.
+
2010-05-04 H.J. Lu <hongjiu.lu@intel.com>
PR middle-end/43671
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 1bfb5c2..166338f 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -903,10 +903,9 @@ disqualify_base_of_expr (tree t, const char *reason)
created. */
static struct access *
-build_access_from_expr_1 (tree *expr_ptr, gimple stmt, bool write)
+build_access_from_expr_1 (tree expr, gimple stmt, bool write)
{
struct access *ret = NULL;
- tree expr = *expr_ptr;
bool partial_ref;
if (TREE_CODE (expr) == BIT_FIELD_REF
@@ -958,18 +957,17 @@ build_access_from_expr_1 (tree *expr_ptr, gimple stmt, bool write)
return ret;
}
-/* Callback of scan_function. Scan expression EXPR and create access
- structures for all accesses to candidates for scalarization. Return true if
- any access has been inserted. */
+/* Scan expression EXPR and create access structures for all accesses to
+ candidates for scalarization. Return true if any access has been inserted.
+ STMT must be the statement from which the expression is taken, WRITE must be
+ true if the expression is a store and false otherwise. */
static bool
-build_access_from_expr (tree *expr_ptr,
- gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, bool write,
- void *data ATTRIBUTE_UNUSED)
+build_access_from_expr (tree expr, gimple stmt, bool write)
{
struct access *access;
- access = build_access_from_expr_1 (expr_ptr, gsi_stmt (*gsi), write);
+ access = build_access_from_expr_1 (expr, stmt, write);
if (access)
{
/* This means the aggregate is accesses as a whole in a way other than an
@@ -1001,39 +999,28 @@ disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
return false;
}
-
-/* Result code for scan_assign callback for scan_function. */
-enum scan_assign_result { SRA_SA_NONE, /* nothing done for the stmt */
- SRA_SA_PROCESSED, /* stmt analyzed/changed */
- SRA_SA_REMOVED }; /* stmt redundant and eliminated */
-
-
-/* Callback of scan_function. Scan expressions occuring in the statement
- pointed to by STMT_EXPR, create access structures for all accesses to
- candidates for scalarization and remove those candidates which occur in
+/* Scan expressions occuring in STMT, create access structures for all accesses
+ to candidates for scalarization and remove those candidates which occur in
statements or expressions that prevent them from being split apart. Return
true if any access has been inserted. */
-static enum scan_assign_result
-build_accesses_from_assign (gimple *stmt_ptr,
- gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
- void *data ATTRIBUTE_UNUSED)
+static bool
+build_accesses_from_assign (gimple stmt)
{
- gimple stmt = *stmt_ptr;
- tree *lhs_ptr, *rhs_ptr;
+ tree lhs, rhs;
struct access *lacc, *racc;
if (!gimple_assign_single_p (stmt))
- return SRA_SA_NONE;
+ return false;
- lhs_ptr = gimple_assign_lhs_ptr (stmt);
- rhs_ptr = gimple_assign_rhs1_ptr (stmt);
+ lhs = gimple_assign_lhs (stmt);
+ rhs = gimple_assign_rhs1 (stmt);
- if (disqualify_ops_if_throwing_stmt (stmt, *lhs_ptr, *rhs_ptr))
- return SRA_SA_NONE;
+ if (disqualify_ops_if_throwing_stmt (stmt, lhs, rhs))
+ return false;
- racc = build_access_from_expr_1 (rhs_ptr, stmt, false);
- lacc = build_access_from_expr_1 (lhs_ptr, stmt, true);
+ racc = build_access_from_expr_1 (rhs, stmt, false);
+ lacc = build_access_from_expr_1 (lhs, stmt, true);
if (racc)
{
@@ -1047,7 +1034,7 @@ build_accesses_from_assign (gimple *stmt_ptr,
&& (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
&& !lacc->grp_unscalarizable_region
&& !racc->grp_unscalarizable_region
- && AGGREGATE_TYPE_P (TREE_TYPE (*lhs_ptr))
+ && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
/* FIXME: Turn the following line into an assert after PR 40058 is
fixed. */
&& lacc->size == racc->size
@@ -1064,7 +1051,7 @@ build_accesses_from_assign (gimple *stmt_ptr,
add_link_to_rhs (racc, link);
}
- return (lacc || racc) ? SRA_SA_PROCESSED : SRA_SA_NONE;
+ return lacc || racc;
}
/* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
@@ -1091,76 +1078,46 @@ callsite_has_enough_arguments_p (gimple call)
return gimple_call_num_args (call) >= (unsigned) func_param_count;
}
-/* Scan function and look for interesting statements. Return true if any has
- been found or processed, as indicated by callbacks. SCAN_EXPR is a callback
- called on all expressions within statements except assign statements and
- those deemed entirely unsuitable for some reason (all operands in such
- statements and expression are removed from candidate_bitmap). SCAN_ASSIGN
- is a callback called on all assign statements, HANDLE_SSA_DEFS is a callback
- called on assign statements and those call statements which have a lhs, it
- can be NULL. ANALYSIS_STAGE is true when running in the analysis stage of a
- pass and thus no statement is being modified. DATA is a pointer passed to
- all callbacks. If any single callback returns true, this function also
- returns true, otherwise it returns false. */
+/* Scan function and look for interesting expressions and create access
+ structures for them. Return true iff any access is created. */
static bool
-scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *),
- enum scan_assign_result (*scan_assign) (gimple *,
- gimple_stmt_iterator *,
- void *),
- bool (*handle_ssa_defs)(gimple, void *),
- bool analysis_stage, void *data)
+scan_function (void)
{
- gimple_stmt_iterator gsi;
basic_block bb;
- unsigned i;
- tree *t;
bool ret = false;
FOR_EACH_BB (bb)
{
- bool bb_changed = false;
-
- if (handle_ssa_defs)
- for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- ret |= handle_ssa_defs (gsi_stmt (gsi), data);
-
- gsi = gsi_start_bb (bb);
- while (!gsi_end_p (gsi))
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
- enum scan_assign_result assign_result;
- bool any = false, deleted = false;
+ tree t;
+ unsigned i;
- if (analysis_stage && final_bbs && stmt_can_throw_external (stmt))
+ if (final_bbs && stmt_can_throw_external (stmt))
bitmap_set_bit (final_bbs, bb->index);
switch (gimple_code (stmt))
{
case GIMPLE_RETURN:
- t = gimple_return_retval_ptr (stmt);
- if (*t != NULL_TREE)
- any |= scan_expr (t, &gsi, false, data);
- if (analysis_stage && final_bbs)
+ t = gimple_return_retval (stmt);
+ if (t != NULL_TREE)
+ ret |= build_access_from_expr (t, stmt, false);
+ if (final_bbs)
bitmap_set_bit (final_bbs, bb->index);
break;
case GIMPLE_ASSIGN:
- assign_result = scan_assign (&stmt, &gsi, data);
- any |= assign_result == SRA_SA_PROCESSED;
- deleted = assign_result == SRA_SA_REMOVED;
- if (handle_ssa_defs && assign_result != SRA_SA_REMOVED)
- any |= handle_ssa_defs (stmt, data);
+ ret |= build_accesses_from_assign (stmt);
break;
case GIMPLE_CALL:
- /* Operands must be processed before the lhs. */
for (i = 0; i < gimple_call_num_args (stmt); i++)
- {
- tree *argp = gimple_call_arg_ptr (stmt, i);
- any |= scan_expr (argp, &gsi, false, data);
- }
+ ret |= build_access_from_expr (gimple_call_arg (stmt, i),
+ stmt, false);
- if (analysis_stage && sra_mode == SRA_MODE_EARLY_IPA)
+ if (sra_mode == SRA_MODE_EARLY_IPA)
{
tree dest = gimple_call_fndecl (stmt);
int flags = gimple_call_flags (stmt);
@@ -1184,65 +1141,33 @@ scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *),
bitmap_set_bit (final_bbs, bb->index);
}
- if (gimple_call_lhs (stmt))
- {
- tree *lhs_ptr = gimple_call_lhs_ptr (stmt);
- if (!analysis_stage
- || !disqualify_ops_if_throwing_stmt (stmt,
- *lhs_ptr, NULL))
- {
- any |= scan_expr (lhs_ptr, &gsi, true, data);
- if (handle_ssa_defs)
- any |= handle_ssa_defs (stmt, data);
- }
- }
+ t = gimple_call_lhs (stmt);
+ if (t && !disqualify_ops_if_throwing_stmt (stmt, t, NULL))
+ ret |= build_access_from_expr (t, stmt, true);
break;
case GIMPLE_ASM:
- if (analysis_stage)
- {
- walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
- asm_visit_addr);
- if (final_bbs)
- bitmap_set_bit (final_bbs, bb->index);
- }
+ walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
+ asm_visit_addr);
+ if (final_bbs)
+ bitmap_set_bit (final_bbs, bb->index);
+
for (i = 0; i < gimple_asm_ninputs (stmt); i++)
{
- tree *op = &TREE_VALUE (gimple_asm_input_op (stmt, i));
- any |= scan_expr (op, &gsi, false, data);
+ t = TREE_VALUE (gimple_asm_input_op (stmt, i));
+ ret |= build_access_from_expr (t, stmt, false);
}
for (i = 0; i < gimple_asm_noutputs (stmt); i++)
{
- tree *op = &TREE_VALUE (gimple_asm_output_op (stmt, i));
- any |= scan_expr (op, &gsi, true, data);
+ t = TREE_VALUE (gimple_asm_output_op (stmt, i));
+ ret |= build_access_from_expr (t, stmt, true);
}
break;
default:
break;
}
-
- if (any)
- {
- ret = true;
-
- if (!analysis_stage)
- {
- bb_changed = true;
- update_stmt (stmt);
- maybe_clean_eh_stmt (stmt);
- }
- }
- if (deleted)
- bb_changed = true;
- else
- {
- gsi_next (&gsi);
- ret = true;
- }
}
- if (!analysis_stage && bb_changed && sra_mode == SRA_MODE_EARLY_IPA)
- gimple_purge_dead_eh_edges (bb);
}
return ret;
@@ -2300,15 +2225,14 @@ get_access_for_expr (tree expr)
return get_var_base_offset_size_access (base, offset, max_size);
}
-/* Callback for scan_function. Replace the expression EXPR with a scalar
- replacement if there is one and generate other statements to do type
- conversion or subtree copying if necessary. GSI is used to place newly
- created statements, WRITE is true if the expression is being written to (it
- is on a LHS of a statement or output in an assembly statement). */
+/* Replace the expression EXPR with a scalar replacement if there is one and
+ generate other statements to do type conversion or subtree copying if
+ necessary. GSI is used to place newly created statements, WRITE is true if
+ the expression is being written to (it is on a LHS of a statement or output
+ in an assembly statement). */
static bool
-sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write,
- void *data ATTRIBUTE_UNUSED)
+sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
{
struct access *access;
tree type, bfr;
@@ -2510,11 +2434,17 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
while (lacc);
}
+/* Result code for SRA assignment modification. */
+enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
+ SRA_AM_MODIFIED, /* stmt changed but not
+ removed */
+ SRA_AM_REMOVED }; /* stmt eliminated */
+
/* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
to the assignment and GSI is the statement iterator pointing at it. Returns
the same values as sra_modify_assign. */
-static enum scan_assign_result
+static enum assignment_mod_result
sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
{
tree lhs = gimple_assign_lhs (*stmt);
@@ -2522,7 +2452,7 @@ sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
acc = get_access_for_expr (lhs);
if (!acc)
- return SRA_SA_NONE;
+ return SRA_AM_NONE;
if (VEC_length (constructor_elt,
CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
@@ -2532,7 +2462,7 @@ sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
if (access_has_children_p (acc))
generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
true, true);
- return SRA_SA_PROCESSED;
+ return SRA_AM_MODIFIED;
}
if (acc->grp_covered)
@@ -2540,12 +2470,12 @@ sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
init_subtree_with_zero (acc, gsi, false);
unlink_stmt_vdef (*stmt);
gsi_remove (gsi, true);
- return SRA_SA_REMOVED;
+ return SRA_AM_REMOVED;
}
else
{
init_subtree_with_zero (acc, gsi, true);
- return SRA_SA_PROCESSED;
+ return SRA_AM_MODIFIED;
}
}
@@ -2578,16 +2508,14 @@ replace_uses_with_default_def_ssa_name (tree ssa)
replace_uses_by (ssa, repl);
}
-/* Callback of scan_function to process assign statements. It examines both
- sides of the statement, replaces them with a scalare replacement if there is
- one and generating copying of replacements if scalarized aggregates have been
- used in the assignment. STMT is a pointer to the assign statement, GSI is
- used to hold generated statements for type conversions and subtree
+/* Examine both sides of the assignment statement pointed to by STMT, replace
+ them with a scalare replacement if there is one and generate copying of
+ replacements if scalarized aggregates have been used in the assignment. GSI
+ is used to hold generated statements for type conversions and subtree
copying. */
-static enum scan_assign_result
-sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
- void *data ATTRIBUTE_UNUSED)
+static enum assignment_mod_result
+sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
{
struct access *lacc, *racc;
tree lhs, rhs;
@@ -2597,7 +2525,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
gimple_stmt_iterator orig_gsi = *gsi;
if (!gimple_assign_single_p (*stmt))
- return SRA_SA_NONE;
+ return SRA_AM_NONE;
lhs = gimple_assign_lhs (*stmt);
rhs = gimple_assign_rhs1 (*stmt);
@@ -2609,16 +2537,16 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
|| TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
{
modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
- gsi, false, data);
+ gsi, false);
modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
- gsi, true, data);
- return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
+ gsi, true);
+ return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
}
lacc = get_access_for_expr (lhs);
racc = get_access_for_expr (rhs);
if (!lacc && !racc)
- return SRA_SA_NONE;
+ return SRA_AM_NONE;
if (lacc && lacc->grp_to_be_replaced)
{
@@ -2747,7 +2675,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
unlink_stmt_vdef (*stmt);
gsi_remove (&orig_gsi, true);
sra_stats.deleted++;
- return SRA_SA_REMOVED;
+ return SRA_AM_REMOVED;
}
}
else
@@ -2767,7 +2695,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
unlink_stmt_vdef (*stmt);
gsi_remove (gsi, true);
sra_stats.deleted++;
- return SRA_SA_REMOVED;
+ return SRA_AM_REMOVED;
}
else if (racc->first_child)
generate_subtree_copies (racc->first_child, lhs,
@@ -2790,7 +2718,83 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
gcc_assert (*stmt == gsi_stmt (orig_gsi));
}
- return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
+ return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
+}
+
+/* Traverse the function body and all modifications as decided in
+ analyze_all_variable_accesses. */
+
+static void
+sra_modify_function_body (void)
+{
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ while (!gsi_end_p (gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ enum assignment_mod_result assign_result;
+ bool modified = false, deleted = false;
+ tree *t;
+ unsigned i;
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_RETURN:
+ t = gimple_return_retval_ptr (stmt);
+ if (*t != NULL_TREE)
+ modified |= sra_modify_expr (t, &gsi, false);
+ break;
+
+ case GIMPLE_ASSIGN:
+ assign_result = sra_modify_assign (&stmt, &gsi);
+ modified |= assign_result == SRA_AM_MODIFIED;
+ deleted = assign_result == SRA_AM_REMOVED;
+ break;
+
+ case GIMPLE_CALL:
+ /* Operands must be processed before the lhs. */
+ for (i = 0; i < gimple_call_num_args (stmt); i++)
+ {
+ t = gimple_call_arg_ptr (stmt, i);
+ modified |= sra_modify_expr (t, &gsi, false);
+ }
+
+ if (gimple_call_lhs (stmt))
+ {
+ t = gimple_call_lhs_ptr (stmt);
+ modified |= sra_modify_expr (t, &gsi, true);
+ }
+ break;
+
+ case GIMPLE_ASM:
+ for (i = 0; i < gimple_asm_ninputs (stmt); i++)
+ {
+ t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
+ modified |= sra_modify_expr (t, &gsi, false);
+ }
+ for (i = 0; i < gimple_asm_noutputs (stmt); i++)
+ {
+ t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
+ modified |= sra_modify_expr (t, &gsi, true);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (modified)
+ {
+ update_stmt (stmt);
+ maybe_clean_eh_stmt (stmt);
+ }
+ if (!deleted)
+ gsi_next (&gsi);
+ }
+ }
}
/* Generate statements initializing scalar replacements of parts of function
@@ -2844,14 +2848,13 @@ perform_intra_sra (void)
if (!find_var_candidates ())
goto out;
- if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL,
- true, NULL))
+ if (!scan_function ())
goto out;
if (!analyze_all_variable_accesses ())
goto out;
- scan_function (sra_modify_expr, sra_modify_assign, NULL, false, NULL);
+ sra_modify_function_body ();
initialize_parameter_reductions ();
statistics_counter_event (cfun, "Scalar replacements created",
@@ -3786,20 +3789,18 @@ get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
return NULL;
}
-/* Callback for scan_function. If the statement STMT defines an SSA_NAME of a
- parameter which is to be removed because its value is not used, replace the
- SSA_NAME with a one relating to a created VAR_DECL and replace all of its
- uses too and return true (update_stmt is then issued for the statement by
- the caller). DATA is a pointer to an adjustments vector. */
+/* If the statement STMT defines an SSA_NAME of a parameter which is to be
+ removed because its value is not used, replace the SSA_NAME with a one
+ relating to a created VAR_DECL together all of its uses and return true.
+ ADJUSTMENTS is a pointer to an adjustments vector. */
static bool
-replace_removed_params_ssa_names (gimple stmt, void *data)
+replace_removed_params_ssa_names (gimple stmt,
+ ipa_parm_adjustment_vec adjustments)
{
- VEC (ipa_parm_adjustment_t, heap) *adjustments;
struct ipa_parm_adjustment *adj;
tree lhs, decl, repl, name;
- adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data;
if (gimple_code (stmt) == GIMPLE_PHI)
lhs = gimple_phi_result (stmt);
else if (is_gimple_assign (stmt))
@@ -3842,27 +3843,22 @@ replace_removed_params_ssa_names (gimple stmt, void *data)
return true;
}
-/* Callback for scan_function and helper to sra_ipa_modify_assign. If the
- expression *EXPR should be replaced by a reduction of a parameter, do so.
- DATA is a pointer to a vector of adjustments. DONT_CONVERT specifies
- whether the function should care about type incompatibility the current and
- new expressions. If it is true, the function will leave incompatibility
- issues to the caller.
-
- When called directly by scan_function, DONT_CONVERT is true when the EXPR is
- a write (LHS) expression. */
+/* If the expression *EXPR should be replaced by a reduction of a parameter, do
+ so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
+ specifies whether the function should care about type incompatibility the
+ current and new expressions. If it is false, the function will leave
+ incompatibility issues to the caller. Return true iff the expression
+ was modified. */
static bool
-sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
- bool dont_convert, void *data)
+sra_ipa_modify_expr (tree *expr, bool convert,
+ ipa_parm_adjustment_vec adjustments)
{
- ipa_parm_adjustment_vec adjustments;
int i, len;
struct ipa_parm_adjustment *adj, *cand = NULL;
HOST_WIDE_INT offset, size, max_size;
tree base, src;
- adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data;
len = VEC_length (ipa_parm_adjustment_t, adjustments);
if (TREE_CODE (*expr) == BIT_FIELD_REF
@@ -3870,7 +3866,7 @@ sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
|| TREE_CODE (*expr) == REALPART_EXPR)
{
expr = &TREE_OPERAND (*expr, 0);
- dont_convert = false;
+ convert = true;
}
base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
@@ -3919,8 +3915,7 @@ sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
fprintf (dump_file, "\n");
}
- if (!dont_convert
- && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
+ if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
{
tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
*expr = vce;
@@ -3930,24 +3925,28 @@ sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
return true;
}
-/* Callback for scan_function to process assign statements. Performs
- essentially the same function like sra_ipa_modify_expr. */
+/* If the statement pointed to by STMT_PTR contains any expressions that need
+ to replaced with a different one as noted by ADJUSTMENTS, do so. Handle any
+ potential type incompatibilities (GSI is used to accommodate conversion
+ statements and must point to the statement). Return true iff the statement
+ was modified. */
-static enum scan_assign_result
-sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, void *data)
+static bool
+sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
+ ipa_parm_adjustment_vec adjustments)
{
gimple stmt = *stmt_ptr;
tree *lhs_p, *rhs_p;
bool any;
if (!gimple_assign_single_p (stmt))
- return SRA_SA_NONE;
+ return false;
rhs_p = gimple_assign_rhs1_ptr (stmt);
lhs_p = gimple_assign_lhs_ptr (stmt);
- any = sra_ipa_modify_expr (rhs_p, gsi, true, data);
- any |= sra_ipa_modify_expr (lhs_p, gsi, true, data);
+ any = sra_ipa_modify_expr (rhs_p, false, adjustments);
+ any |= sra_ipa_modify_expr (lhs_p, false, adjustments);
if (any)
{
tree new_rhs = NULL_TREE;
@@ -3983,10 +3982,94 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, void *data)
gimple_assign_set_rhs_from_tree (gsi, tmp);
}
- return SRA_SA_PROCESSED;
+ return true;
}
- return SRA_SA_NONE;
+ return false;
+}
+
+/* Traverse the function body and all modifications as described in
+ ADJUSTMENTS. */
+
+static void
+ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
+{
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ gimple_stmt_iterator gsi;
+ bool bb_changed = false;
+
+ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
+
+ gsi = gsi_start_bb (bb);
+ while (!gsi_end_p (gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ bool modified = false;
+ tree *t;
+ unsigned i;
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_RETURN:
+ t = gimple_return_retval_ptr (stmt);
+ if (*t != NULL_TREE)
+ modified |= sra_ipa_modify_expr (t, true, adjustments);
+ break;
+
+ case GIMPLE_ASSIGN:
+ modified |= sra_ipa_modify_assign (&stmt, &gsi, adjustments);
+ modified |= replace_removed_params_ssa_names (stmt, adjustments);
+ break;
+
+ case GIMPLE_CALL:
+ /* Operands must be processed before the lhs. */
+ for (i = 0; i < gimple_call_num_args (stmt); i++)
+ {
+ t = gimple_call_arg_ptr (stmt, i);
+ modified |= sra_ipa_modify_expr (t, true, adjustments);
+ }
+
+ if (gimple_call_lhs (stmt))
+ {
+ t = gimple_call_lhs_ptr (stmt);
+ modified |= sra_ipa_modify_expr (t, false, adjustments);
+ modified |= replace_removed_params_ssa_names (stmt,
+ adjustments);
+ }
+ break;
+
+ case GIMPLE_ASM:
+ for (i = 0; i < gimple_asm_ninputs (stmt); i++)
+ {
+ t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
+ modified |= sra_ipa_modify_expr (t, true, adjustments);
+ }
+ for (i = 0; i < gimple_asm_noutputs (stmt); i++)
+ {
+ t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
+ modified |= sra_ipa_modify_expr (t, false, adjustments);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (modified)
+ {
+ bb_changed = true;
+ update_stmt (stmt);
+ maybe_clean_eh_stmt (stmt);
+ }
+ gsi_next (&gsi);
+ }
+ if (bb_changed)
+ gimple_purge_dead_eh_edges (bb);
+ }
}
/* Call gimple_debug_bind_reset_value on all debug statements describing
@@ -4013,7 +4096,8 @@ sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
continue;
FOR_EACH_IMM_USE_STMT (stmt, ui, name)
{
- /* All other users must have been removed by scan_function. */
+ /* All other users must have been removed by
+ ipa_sra_modify_function_body. */
gcc_assert (is_gimple_debug (stmt));
gimple_debug_bind_reset_value (stmt);
update_stmt (stmt);
@@ -4131,8 +4215,7 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
as following functions will use what it computed. */
create_abstract_origin (current_function_decl);
ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
- scan_function (sra_ipa_modify_expr, sra_ipa_modify_assign,
- replace_removed_params_ssa_names, false, adjustments);
+ ipa_sra_modify_function_body (adjustments);
sra_ipa_reset_debug_stmts (adjustments);
convert_callers (node, adjustments);
cgraph_make_node_local (node);
@@ -4224,8 +4307,7 @@ ipa_early_sra (void)
* last_basic_block_for_function (cfun));
final_bbs = BITMAP_ALLOC (NULL);
- scan_function (build_access_from_expr, build_accesses_from_assign,
- NULL, true, NULL);
+ scan_function ();
if (encountered_apply_args)
{
if (dump_file)