diff options
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ipa/pr42706.c | 27 | ||||
-rw-r--r-- | gcc/tree-sra.c | 71 |
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; |