From e021c122e50fdf3bc80e630e148b836c358a4dc5 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Wed, 2 Nov 2011 08:46:08 +0000 Subject: [PATCH] re PR middle-end/50890 (ICE in fold_convert_loc, at fold-const.c:1894) 2010-11-02 Richard Guenther PR tree-optimization/50890 * gimple.h (gimple_fold_call): Remove. * gimple-fold.c (fold_stmt_1): Move all call related code to ... (gimple_fold_call): ... here. Make static. Update the cannot-inline flag on direct calls. * ipa-inline.c (early_inliner): Copy the cannot-inline flag from the statements to the edges. * gcc.dg/torture/pr50890.c: New testcase. From-SVN: r180763 --- gcc/ChangeLog | 10 +++ gcc/gimple-fold.c | 102 +++++++++++++++---------- gcc/gimple.h | 1 - gcc/ipa-inline.c | 2 + gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/torture/pr50890.c | 17 +++++ 6 files changed, 94 insertions(+), 43 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr50890.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fc8704d8502..87e02408db2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2010-11-02 Richard Guenther + + PR tree-optimization/50890 + * gimple.h (gimple_fold_call): Remove. + * gimple-fold.c (fold_stmt_1): Move all call related code to ... + (gimple_fold_call): ... here. Make static. Update the + cannot-inline flag on direct calls. + * ipa-inline.c (early_inliner): Copy the cannot-inline flag + from the statements to the edges. + 2011-11-01 Ian Lance Taylor * godump.c (struct macro_hash_value): Define. diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index aa67d248c53..53bfb9641f8 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1057,53 +1057,82 @@ gimple_extract_devirt_binfo_from_cst (tree cst) simplifies to a constant value. Return true if any changes were made. It is assumed that the operands have been previously folded. */ -bool +static bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) { gimple stmt = gsi_stmt (*gsi); tree callee; + bool changed = false; + unsigned i; - /* Check for builtins that CCP can handle using information not - available in the generic fold routines. */ - callee = gimple_call_fndecl (stmt); - if (!inplace && callee && DECL_BUILT_IN (callee)) - { - tree result = gimple_fold_builtin (stmt); - - if (result) - { - if (!update_call_from_tree (gsi, result)) - gimplify_and_update_call_from_tree (gsi, result); - return true; - } - } + /* Fold *& in call arguments. */ + for (i = 0; i < gimple_call_num_args (stmt); ++i) + if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i))) + { + tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false); + if (tmp) + { + gimple_call_set_arg (stmt, i, tmp); + changed = true; + } + } /* Check for virtual calls that became direct calls. */ callee = gimple_call_fn (stmt); if (callee && TREE_CODE (callee) == OBJ_TYPE_REF) { - tree binfo, fndecl, obj; - HOST_WIDE_INT token; - if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE) { gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee)); - return true; + changed = true; + } + else + { + tree obj = OBJ_TYPE_REF_OBJECT (callee); + tree binfo = gimple_extract_devirt_binfo_from_cst (obj); + if (binfo) + { + HOST_WIDE_INT token + = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee)); + tree fndecl = gimple_get_virt_method_for_binfo (token, binfo); + if (fndecl) + { + gimple_call_set_fndecl (stmt, fndecl); + changed = true; + } + } } - - obj = OBJ_TYPE_REF_OBJECT (callee); - binfo = gimple_extract_devirt_binfo_from_cst (obj); - if (!binfo) - return false; - token = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee)); - fndecl = gimple_get_virt_method_for_binfo (token, binfo); - if (!fndecl) - return false; - gimple_call_set_fndecl (stmt, fndecl); - return true; } - return false; + /* Check whether propagating into the function address made the + call direct, and thus possibly non-inlineable. + ??? This asks for a more conservative setting of the non-inlinable + flag, namely true for all indirect calls. But that would require + that we can re-compute the flag conservatively, thus it isn't + ever initialized from something else than return/argument type + checks . */ + callee = gimple_call_fndecl (stmt); + if (callee + && !gimple_check_call_matching_types (stmt, callee)) + gimple_call_set_cannot_inline (stmt, true); + + if (inplace) + return changed; + + /* Check for builtins that CCP can handle using information not + available in the generic fold routines. */ + if (callee && DECL_BUILT_IN (callee)) + { + tree result = gimple_fold_builtin (stmt); + if (result) + { + if (!update_call_from_tree (gsi, result)) + gimplify_and_update_call_from_tree (gsi, result); + changed = true; + } + } + + return changed; } /* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument @@ -1162,17 +1191,6 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) break; case GIMPLE_CALL: - /* Fold *& in call arguments. */ - for (i = 0; i < gimple_call_num_args (stmt); ++i) - if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i))) - { - tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false); - if (tmp) - { - gimple_call_set_arg (stmt, i, tmp); - changed = true; - } - } changed |= gimple_fold_call (gsi, inplace); break; diff --git a/gcc/gimple.h b/gcc/gimple.h index 75e19a72b87..666c44c8591 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -909,7 +909,6 @@ unsigned get_gimple_rhs_num_ops (enum tree_code); #define gimple_alloc(c, n) gimple_alloc_stat (c, n MEM_STAT_INFO) gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL); const char *gimple_decl_printable_name (tree, int); -bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace); tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree); void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree); tree gimple_extract_devirt_binfo_from_cst (tree); diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 662c6b3cb5d..31c88e501e7 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -1949,6 +1949,8 @@ early_inliner (void) = estimate_num_insns (edge->call_stmt, &eni_size_weights); es->call_stmt_time = estimate_num_insns (edge->call_stmt, &eni_time_weights); + edge->call_stmt_cannot_inline_p + = gimple_call_cannot_inline_p (edge->call_stmt); } timevar_pop (TV_INTEGRATION); iterations++; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bdbdb8e7b19..bf7c36611e9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-11-02 Richard Guenther + + PR tree-optimization/50890 + * gcc.dg/torture/pr50890.c: New testcase. + 2011-11-01 Paolo Carlini PR c++/44277 diff --git a/gcc/testsuite/gcc.dg/torture/pr50890.c b/gcc/testsuite/gcc.dg/torture/pr50890.c new file mode 100644 index 00000000000..17240d4fb82 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr50890.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ + +static float make_insn_raw (void) +{ + return 0; +} + +static int emit_pattern_after_noloc (int (make_raw) ()) +{ + return make_raw (); +} + +void emit_insn_after_noloc (void) +{ + emit_pattern_after_noloc ((void *) make_insn_raw); +} +