aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-sra.c
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2010-01-14 19:00:34 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2010-01-14 19:00:34 +0100
commit2f3cdcf50295a3888012b66a52b709a7f21d2f25 (patch)
treee67d8e3c3b5b8bd2f68e5f4e63f4b36f8e354636 /gcc/tree-sra.c
parent7767706d58eecfccd3805fd9e59fdb5e3b557611 (diff)
downloadgcc-2f3cdcf50295a3888012b66a52b709a7f21d2f25.zip
gcc-2f3cdcf50295a3888012b66a52b709a7f21d2f25.tar.gz
gcc-2f3cdcf50295a3888012b66a52b709a7f21d2f25.tar.bz2
re PR tree-optimization/42706 (ICE in gimple_op, at gimple.h:1634, (IPA SRA))
2010-01-14 Martin Jambor <mjambor@suse.cz> PR tree-optimization/42706 * tree-sra.c (encountered_recursive_call): New variable. (encountered_unchangable_recursive_call): Likewise. (sra_initialize): Initialize both new variables. (callsite_has_enough_arguments_p): New function. (scan_function): Call decl and flags check only for IPA-SRA, check whether there is a recursive call and whether it has enough arguments. (all_callers_have_enough_arguments_p): New function. (convert_callers): Look for recursive calls only when encountered_recursive_call is set. (ipa_early_sra): Bail out either if !all_callers_have_enough_arguments_p or encountered_unchangable_recursive_call. * testsuite/gcc.dg/ipa/pr42706.c: New testcase. From-SVN: r155911
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r--gcc/tree-sra.c71
1 files changed, 66 insertions, 5 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 4797667..dd62cc5 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -258,6 +258,13 @@ static int func_param_count;
__builtin_apply_args. */
static bool encountered_apply_args;
+/* Set by scan_function when it finds a recursive call. */
+static bool encountered_recursive_call;
+
+/* Set by scan_function when it finds a recursive call with less actual
+ arguments than formal parameters.. */
+static bool encountered_unchangable_recursive_call;
+
/* This is a table in which for each basic block and parameter there is a
distance (offset + size) in that parameter which is dereferenced and
accessed in that BB. */
@@ -545,6 +552,8 @@ sra_initialize (void)
base_access_vec = pointer_map_create ();
memset (&sra_stats, 0, sizeof (sra_stats));
encountered_apply_args = false;
+ encountered_recursive_call = false;
+ encountered_unchangable_recursive_call = false;
}
/* Hook fed to pointer_map_traverse, deallocate stored vectors. */
@@ -944,6 +953,14 @@ asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
return false;
}
+/* Return true iff callsite CALL has at least as many actual arguments as there
+ are formal parameters of the function currently processed by IPA-SRA. */
+
+static inline bool
+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
@@ -1014,15 +1031,24 @@ scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *),
any |= scan_expr (argp, &gsi, false, data);
}
- if (analysis_stage)
+ if (analysis_stage && sra_mode == SRA_MODE_EARLY_IPA)
{
tree dest = gimple_call_fndecl (stmt);
int flags = gimple_call_flags (stmt);
- if (dest
- && DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
- encountered_apply_args = true;
+ if (dest)
+ {
+ if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
+ encountered_apply_args = true;
+ if (cgraph_get_node (dest)
+ == cgraph_get_node (current_function_decl))
+ {
+ encountered_recursive_call = true;
+ if (!callsite_has_enough_arguments_p (stmt))
+ encountered_unchangable_recursive_call = true;
+ }
+ }
if (final_bbs
&& (flags & (ECF_CONST | ECF_PURE)) == 0)
@@ -3780,6 +3806,21 @@ sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
}
}
+/* Return true iff all callers have at least as many actual arguments as there
+ are formal parameters in the current function. */
+
+static bool
+all_callers_have_enough_arguments_p (struct cgraph_node *node)
+{
+ struct cgraph_edge *cs;
+ for (cs = node->callers; cs; cs = cs->next_caller)
+ if (!callsite_has_enough_arguments_p (cs->call_stmt))
+ return false;
+
+ return true;
+}
+
+
/* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
static void
@@ -3815,6 +3856,10 @@ convert_callers (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
BITMAP_FREE (recomputed_callers);
current_function_decl = old_cur_fndecl;
+
+ if (!encountered_recursive_call)
+ return;
+
FOR_EACH_BB (this_block)
{
gimple_stmt_iterator gsi;
@@ -3927,6 +3972,14 @@ ipa_early_sra (void)
goto simple_out;
}
+ if (!all_callers_have_enough_arguments_p (node))
+ {
+ if (dump_file)
+ fprintf (dump_file, "There are callers with insufficient number of "
+ "arguments.\n");
+ goto simple_out;
+ }
+
bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
func_param_count
* last_basic_block_for_function (cfun));
@@ -3941,6 +3994,14 @@ ipa_early_sra (void)
goto out;
}
+ if (encountered_unchangable_recursive_call)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Function calls itself with insufficient "
+ "number of arguments.\n");
+ goto out;
+ }
+
adjustments = analyze_all_param_acesses ();
if (!adjustments)
goto out;