Commit e021c122 by Richard Guenther Committed by Richard Biener

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
parent 5743331e
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> 2011-11-01 Ian Lance Taylor <iant@google.com>
* godump.c (struct macro_hash_value): Define. * godump.c (struct macro_hash_value): Define.
...@@ -1057,53 +1057,82 @@ gimple_extract_devirt_binfo_from_cst (tree cst) ...@@ -1057,53 +1057,82 @@ gimple_extract_devirt_binfo_from_cst (tree cst)
simplifies to a constant value. Return true if any changes were made. simplifies to a constant value. Return true if any changes were made.
It is assumed that the operands have been previously folded. */ It is assumed that the operands have been previously folded. */
bool static bool
gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
{ {
gimple stmt = gsi_stmt (*gsi); gimple stmt = gsi_stmt (*gsi);
tree callee; tree callee;
bool changed = false;
unsigned i;
/* Check for builtins that CCP can handle using information not /* Fold *& in call arguments. */
available in the generic fold routines. */ for (i = 0; i < gimple_call_num_args (stmt); ++i)
callee = gimple_call_fndecl (stmt); if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
if (!inplace && callee && DECL_BUILT_IN (callee)) {
{ tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
tree result = gimple_fold_builtin (stmt); if (tmp)
{
if (result) gimple_call_set_arg (stmt, i, tmp);
{ changed = true;
if (!update_call_from_tree (gsi, result)) }
gimplify_and_update_call_from_tree (gsi, result); }
return true;
}
}
/* Check for virtual calls that became direct calls. */ /* Check for virtual calls that became direct calls. */
callee = gimple_call_fn (stmt); callee = gimple_call_fn (stmt);
if (callee && TREE_CODE (callee) == OBJ_TYPE_REF) 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) if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
{ {
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee)); 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); /* Check whether propagating into the function address made the
binfo = gimple_extract_devirt_binfo_from_cst (obj); call direct, and thus possibly non-inlineable.
if (!binfo) ??? This asks for a more conservative setting of the non-inlinable
return false; flag, namely true for all indirect calls. But that would require
token = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee)); that we can re-compute the flag conservatively, thus it isn't
fndecl = gimple_get_virt_method_for_binfo (token, binfo); ever initialized from something else than return/argument type
if (!fndecl) checks . */
return false; callee = gimple_call_fndecl (stmt);
gimple_call_set_fndecl (stmt, fndecl); if (callee
return true; && !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 /* 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) ...@@ -1162,17 +1191,6 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
break; break;
case GIMPLE_CALL: 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); changed |= gimple_fold_call (gsi, inplace);
break; break;
......
...@@ -909,7 +909,6 @@ unsigned get_gimple_rhs_num_ops (enum tree_code); ...@@ -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) #define gimple_alloc(c, n) gimple_alloc_stat (c, n MEM_STAT_INFO)
gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL); gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
const char *gimple_decl_printable_name (tree, int); 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); tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree); void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree);
tree gimple_extract_devirt_binfo_from_cst (tree); tree gimple_extract_devirt_binfo_from_cst (tree);
......
...@@ -1949,6 +1949,8 @@ early_inliner (void) ...@@ -1949,6 +1949,8 @@ early_inliner (void)
= estimate_num_insns (edge->call_stmt, &eni_size_weights); = estimate_num_insns (edge->call_stmt, &eni_size_weights);
es->call_stmt_time es->call_stmt_time
= estimate_num_insns (edge->call_stmt, &eni_time_weights); = 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); timevar_pop (TV_INTEGRATION);
iterations++; iterations++;
......
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> 2011-11-01 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/44277 PR c++/44277
......
/* { 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment