aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr42706.c27
-rw-r--r--gcc/tree-sra.c71
4 files changed, 115 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 161756d..9c2e7ef 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+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.
+
2010-01-14 Alexander Monakov <amonakov@ispras.ru>
* sel-sched.c: Add 2010 to copyright years.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6940408..cfebc86 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-01-14 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/42706
+ * gcc.dg/ipa/pr42706.c: New testcase.
+
2010-01-14 H.J. Lu <hongjiu.lu@intel.com>
* g++.dg/graphite/pr42681.C (size_t): Use __SIZE_TYPE__.
@@ -5,7 +10,7 @@
2010-01-14 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/42714
- * gcc/testsuite/g++.dg/torture/pr42714.C: New test.
+ * g++.dg/torture/pr42714.C: New test.
2010-01-14 Alexander Monakov <amonakov@ispras.ru>
diff --git a/gcc/testsuite/gcc.dg/ipa/pr42706.c b/gcc/testsuite/gcc.dg/ipa/pr42706.c
new file mode 100644
index 0000000..9c5f43a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr42706.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-early-inlining -fipa-sra" } */
+
+struct S
+{
+ float red;
+ int green;
+ void *blue;
+};
+
+extern int gi;
+static int foo ();
+
+int
+bar (void)
+{
+ foo ();
+ return 0;
+}
+
+static int
+foo (struct S s)
+{
+ gi = s.green;
+ return 0;
+}
+
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;