aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2011-11-02 08:46:08 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2011-11-02 08:46:08 +0000
commite021c122e50fdf3bc80e630e148b836c358a4dc5 (patch)
tree4bbfb4884a0e1cb82abe97bd185f21769f02380b /gcc
parent5743331e9d1e1168cab132e2021cfef4d91c3c0f (diff)
downloadgcc-e021c122e50fdf3bc80e630e148b836c358a4dc5.zip
gcc-e021c122e50fdf3bc80e630e148b836c358a4dc5.tar.gz
gcc-e021c122e50fdf3bc80e630e148b836c358a4dc5.tar.bz2
re PR middle-end/50890 (ICE in fold_convert_loc, at fold-const.c:1894)
2010-11-02 Richard Guenther <rguenther@suse.de> 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/gimple-fold.c100
-rw-r--r--gcc/gimple.h1
-rw-r--r--gcc/ipa-inline.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50890.c17
6 files changed, 93 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fc8704d8..87e0240 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2010-11-02 Richard Guenther <rguenther@suse.de>
+
+ 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 <iant@google.com>
* godump.c (struct macro_hash_value): Define.
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index aa67d24..53bfb96 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;
+ /* 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 false;
+ 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 75e19a7..666c44c 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 662c6b3..31c88e50 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 bdbdb8e..bf7c366 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-11-02 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50890
+ * gcc.dg/torture/pr50890.c: New testcase.
+
2011-11-01 Paolo Carlini <paolo.carlini@oracle.com>
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 0000000..17240d4
--- /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);
+}
+