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
This commit is contained in:
parent
5743331e9d
commit
e021c122e5
6 changed files with 94 additions and 43 deletions
|
@ -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.
|
||||
|
|
|
@ -1057,24 +1057,23 @@ 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))
|
||||
/* Fold *& in call arguments. */
|
||||
for (i = 0; i < gimple_call_num_args (stmt); ++i)
|
||||
if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
|
||||
{
|
||||
tree result = gimple_fold_builtin (stmt);
|
||||
|
||||
if (result)
|
||||
tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
|
||||
if (tmp)
|
||||
{
|
||||
if (!update_call_from_tree (gsi, result))
|
||||
gimplify_and_update_call_from_tree (gsi, result);
|
||||
return true;
|
||||
gimple_call_set_arg (stmt, i, tmp);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1082,28 +1081,58 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
|
|||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
return true;
|
||||
changed = 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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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
|
||||
|
|
17
gcc/testsuite/gcc.dg/torture/pr50890.c
Normal file
17
gcc/testsuite/gcc.dg/torture/pr50890.c
Normal file
|
@ -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);
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue