builtins.c (interclass_mathfn_icode): New helper.

* builtins.c (interclass_mathfn_icode): New helper.
	(expand_builtin_interclass_mathfn): Use it here, and split folding
	into ...
	(fold_builtin_interclass_mathfn): ... this new folder.
	(build_call_nofold_loc): New static helper.
	(build_call_nofold): New wrapper macro for above.
	(expand_builtin_int_roundingfn): Use it instead of build_call_expr.
	(expand_builtin_pow): Ditto.
	(expand_builtin_memset_args): Ditto.
	(expand_builtin_printf): Ditto.
	(expand_builtin_fprintf): Ditto.
	(expand_builtin_sprintf): Ditto.
	(expand_builtin_memory_chk): Ditto.
	(expand_builtin_mempcpy_args): Ditto and don't call folders.
	(expand_builtin_stpcpy): Ditto.
	(expand_builtin_strcmp): Ditto.
	(expand_builtin_strncmp): Ditto.
	(expand_builtin_strcpy): Remove FNDECL and MODE arguments.
	(expand_builtin_strcpy_args): Don't call folders.
	(expand_builtin_memcmp): Ditto.
	(expand_builtin_strncpy): Ditto, and use target.
	(expand_builtin_memcpy): Ditto.
	(expand_builtin_strstr, expand_builtin_strchr, expand_builtin_strrchr,
	expand_builtin_strpbrk, expand_builtin_memmove,
	expand_builtin_memmove_args, expand_builtin_bcopy,
	expand_builtin_memchr, expand_builtin_strcat, expand_builtin_strncat,
	expand_builtin_strspn, expand_builtin_strcspn,
	expand_builtin_fputs): Remove these.
	(expand_builtin): Don't call the above, change calls to other
	expanders that changed prototype.
	(fold_builtin_stpcpy): New folder split out from expand_builtin_stpcpy.
	(fold_builtin_1 <ISFINITE, ISINF, ISNORMAL>): Call
	fold_builtin_interclass_mathfn.
	(fold_builtin_2 <STPCPY>): Call fold_builtin_stpcpy.
	(fold_builtin_strcat): Add folding split from expand_builtin_strcat.

	* fold-const.c (fold_binary_loc <NE_EXPR>): Add !exp != 0 -> !exp.
	* passes.c (init_optimization_passes): Move pass_fold_builtins
	after last phiopt pass.
	* tree-inline.c (fold_marked_statements): When folding builtins
	iterate over all instruction potentially generated.
	* tree-ssa-ccp.c (gimplify_and_update_call_from_tree): Declare
	earlier.
	(fold_gimple_call): Use it to always fold calls (into potentially
	multiple instructions).
	* tree-ssa-dom.c (optimize_stmt): Resolve __builtin_constant_p
	calls into zero at this time.
	* tree-ssa-propagate.c (substitute_and_fold): Ignore multiple 
	statements generated by builtin folding.

testsuite/
	* gcc.dg/builtins-44.c: Use __builtin_isinf_sign when checking
	for sign of -Inf.

From-SVN: r152236
This commit is contained in:
Michael Matz 2009-09-28 12:54:23 +00:00 committed by Michael Matz
parent d813aaba52
commit 44e10129de
10 changed files with 460 additions and 693 deletions

View File

@ -1,3 +1,55 @@
2009-09-28 Michael Matz <matz@suse.de>
* builtins.c (interclass_mathfn_icode): New helper.
(expand_builtin_interclass_mathfn): Use it here, and split folding
into ...
(fold_builtin_interclass_mathfn): ... this new folder.
(build_call_nofold_loc): New static helper.
(build_call_nofold): New wrapper macro for above.
(expand_builtin_int_roundingfn): Use it instead of build_call_expr.
(expand_builtin_pow): Ditto.
(expand_builtin_memset_args): Ditto.
(expand_builtin_printf): Ditto.
(expand_builtin_fprintf): Ditto.
(expand_builtin_sprintf): Ditto.
(expand_builtin_memory_chk): Ditto.
(expand_builtin_mempcpy_args): Ditto and don't call folders.
(expand_builtin_stpcpy): Ditto.
(expand_builtin_strcmp): Ditto.
(expand_builtin_strncmp): Ditto.
(expand_builtin_strcpy): Remove FNDECL and MODE arguments.
(expand_builtin_strcpy_args): Don't call folders.
(expand_builtin_memcmp): Ditto.
(expand_builtin_strncpy): Ditto, and use target.
(expand_builtin_memcpy): Ditto.
(expand_builtin_strstr, expand_builtin_strchr, expand_builtin_strrchr,
expand_builtin_strpbrk, expand_builtin_memmove,
expand_builtin_memmove_args, expand_builtin_bcopy,
expand_builtin_memchr, expand_builtin_strcat, expand_builtin_strncat,
expand_builtin_strspn, expand_builtin_strcspn,
expand_builtin_fputs): Remove these.
(expand_builtin): Don't call the above, change calls to other
expanders that changed prototype.
(fold_builtin_stpcpy): New folder split out from expand_builtin_stpcpy.
(fold_builtin_1 <ISFINITE, ISINF, ISNORMAL>): Call
fold_builtin_interclass_mathfn.
(fold_builtin_2 <STPCPY>): Call fold_builtin_stpcpy.
(fold_builtin_strcat): Add folding split from expand_builtin_strcat.
* fold-const.c (fold_binary_loc <NE_EXPR>): Add !exp != 0 -> !exp.
* passes.c (init_optimization_passes): Move pass_fold_builtins
after last phiopt pass.
* tree-inline.c (fold_marked_statements): When folding builtins
iterate over all instruction potentially generated.
* tree-ssa-ccp.c (gimplify_and_update_call_from_tree): Declare
earlier.
(fold_gimple_call): Use it to always fold calls (into potentially
multiple instructions).
* tree-ssa-dom.c (optimize_stmt): Resolve __builtin_constant_p
calls into zero at this time.
* tree-ssa-propagate.c (substitute_and_fold): Ignore multiple
statements generated by builtin folding.
2009-09-28 Nick Clifton <nickc@redhat.com>
* config/m32r/m32r.c (m32r_is_insn): Return false for debugging

File diff suppressed because it is too large Load Diff

View File

@ -12614,6 +12614,11 @@ fold_binary_loc (location_t loc,
return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
fold_convert_loc (loc, type, arg0));
/* !exp != 0 becomes !exp */
if (TREE_CODE (arg0) == TRUTH_NOT_EXPR && integer_zerop (arg1)
&& code == NE_EXPR)
return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* If this is an equality comparison of the address of two non-weak,
unaliased symbols neither of which are extern (since we do not
have access to attributes for externs), then we know the result. */

View File

@ -626,6 +626,11 @@ init_optimization_passes (void)
NEXT_PASS (pass_lower_complex);
NEXT_PASS (pass_sra);
NEXT_PASS (pass_rename_ssa_copies);
/* The dom pass will also resolve all __builtin_constant_p calls
that are still there to 0. This has to be done after some
propagations have already run, but before some more dead code
is removed, and this place fits nicely. Remember this when
trying to move or duplicate pass_dominator somewhere earlier. */
NEXT_PASS (pass_dominator);
/* The only const/copy propagation opportunities left after
DOM should be due to degenerate PHI nodes. So rather than
@ -641,7 +646,6 @@ init_optimization_passes (void)
NEXT_PASS (pass_object_sizes);
NEXT_PASS (pass_ccp);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_fold_builtins);
NEXT_PASS (pass_cse_sincos);
NEXT_PASS (pass_optimize_bswap);
NEXT_PASS (pass_split_crit_edges);
@ -709,6 +713,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_dse);
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_phiopt);
NEXT_PASS (pass_fold_builtins);
NEXT_PASS (pass_tail_calls);
NEXT_PASS (pass_rename_ssa_copies);
NEXT_PASS (pass_uncprop);

View File

@ -1,3 +1,8 @@
2009-09-28 Michael Matz <matz@suse.de>
* gcc.dg/builtins-44.c: Use __builtin_isinf_sign when checking
for sign of -Inf.
2009-09-27 Richard Henderson <rth@redhat.com>
* gcc.c-torture/compile/pr41469.c: Add -fexceptions.

View File

@ -31,17 +31,13 @@ main ()
if (__builtin_isinfl (pinfl) != 1)
link_error ();
if (__builtin_isinf (-pinf) != -1)
if (__builtin_isinf_sign (-pinf) != -1)
link_error ();
#ifndef __SPU__
if (__builtin_isinf (-pinff) != -1)
link_error ();
if (__builtin_isinff (-pinff) != -1)
if (__builtin_isinf_sign (-pinff) != -1)
link_error ();
#endif
if (__builtin_isinf (-pinfl) != -1)
link_error ();
if (__builtin_isinfl (-pinfl) != -1)
if (__builtin_isinf_sign (-pinfl) != -1)
link_error ();
if (__builtin_isinf (4.0))

View File

@ -3873,7 +3873,48 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
gimple old_stmt = gsi_stmt (gsi);
tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
if (fold_stmt (&gsi))
if (old_decl && DECL_BUILT_IN (old_decl))
{
/* Folding builtins can create multiple instructions,
we need to look at all of them. */
gimple_stmt_iterator i2 = gsi;
gsi_prev (&i2);
if (fold_stmt (&gsi))
{
gimple new_stmt;
if (gsi_end_p (i2))
i2 = gsi_start_bb (BASIC_BLOCK (first));
else
gsi_next (&i2);
while (1)
{
new_stmt = gsi_stmt (i2);
update_stmt (new_stmt);
cgraph_update_edges_for_call_stmt (old_stmt, old_decl,
new_stmt);
if (new_stmt == gsi_stmt (gsi))
{
/* It is okay to check only for the very last
of these statements. If it is a throwing
statement nothing will change. If it isn't
this can remove EH edges. If that weren't
correct then because some intermediate stmts
throw, but not the last one. That would mean
we'd have to split the block, which we can't
here and we'd loose anyway. And as builtins
probably never throw, this all
is mood anyway. */
if (maybe_clean_or_replace_eh_stmt (old_stmt,
new_stmt))
gimple_purge_dead_eh_edges (BASIC_BLOCK (first));
break;
}
gsi_next (&i2);
}
}
}
else if (fold_stmt (&gsi))
{
/* Re-read the statement from GSI as fold_stmt() may
have changed it. */
@ -3882,7 +3923,8 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
if (is_gimple_call (old_stmt)
|| is_gimple_call (new_stmt))
cgraph_update_edges_for_call_stmt (old_stmt, old_decl, new_stmt);
cgraph_update_edges_for_call_stmt (old_stmt, old_decl,
new_stmt);
if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
gimple_purge_dead_eh_edges (BASIC_BLOCK (first));

View File

@ -1424,8 +1424,8 @@ evaluate_stmt (gimple stmt)
else if (code == GIMPLE_SWITCH)
simplified = gimple_switch_index (stmt);
else
/* These cannot satisfy is_gimple_min_invariant without folding. */
gcc_assert (code == GIMPLE_CALL || code == GIMPLE_COND);
/* These cannot satisfy is_gimple_min_invariant without folding. */
gcc_assert (code == GIMPLE_CALL || code == GIMPLE_COND);
}
is_constant = simplified && is_gimple_min_invariant (simplified);
@ -2895,6 +2895,7 @@ fold_gimple_cond (gimple stmt)
return false;
}
static void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
/* Attempt to fold a call statement referenced by the statement iterator GSI.
The statement may be replaced by another statement, e.g., if the call
@ -2915,7 +2916,11 @@ fold_gimple_call (gimple_stmt_iterator *gsi)
tree result = ccp_fold_builtin (stmt);
if (result)
return update_call_from_tree (gsi, result);
{
if (!update_call_from_tree (gsi, result))
gimplify_and_update_call_from_tree (gsi, result);
return true;
}
}
else
{

View File

@ -2133,6 +2133,20 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
{
eliminate_redundant_computations (&si);
stmt = gsi_stmt (si);
if (gimple_code (stmt) == GIMPLE_CALL)
{
/* Resolve __builtin_constant_p. If it hasn't been
folded to integer_one_node by now, it's fairly
certain that the value simply isn't constant. */
tree callee = gimple_call_fndecl (stmt);
if (callee
&& DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (callee) == BUILT_IN_CONSTANT_P)
{
propagate_tree_value_into_stmt (&si, integer_zero_node);
stmt = gsi_stmt (si);
}
}
}
/* Record any additional equivalences created by this statement. */

View File

@ -1001,6 +1001,10 @@ substitute_and_fold (prop_value_t *prop_value, ssa_prop_fold_stmt_fn fold_fn)
gimple stmt = gsi_stmt (i);
gimple old_stmt;
enum gimple_code code = gimple_code (stmt);
gimple_stmt_iterator oldi;
oldi = i;
gsi_prev (&i);
/* Ignore ASSERT_EXPRs. They are used by VRP to generate
range information for names and they are discarded
@ -1008,10 +1012,7 @@ substitute_and_fold (prop_value_t *prop_value, ssa_prop_fold_stmt_fn fold_fn)
if (code == GIMPLE_ASSIGN
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
{
gsi_prev (&i);
continue;
}
continue;
/* No point propagating into a stmt whose result is not used,
but instead we might be able to remove a trivially dead stmt. */
@ -1030,7 +1031,6 @@ substitute_and_fold (prop_value_t *prop_value, ssa_prop_fold_stmt_fn fold_fn)
fprintf (dump_file, "\n");
}
prop_stats.num_dce++;
gsi_prev (&i);
i2 = gsi_for_stmt (stmt);
gsi_remove (&i2, true);
release_defs (stmt);
@ -1052,7 +1052,7 @@ substitute_and_fold (prop_value_t *prop_value, ssa_prop_fold_stmt_fn fold_fn)
specific information. Do this before propagating
into the stmt to not disturb pass specific information. */
if (fold_fn
&& (*fold_fn)(&i))
&& (*fold_fn)(&oldi))
{
did_replace = true;
prop_stats.num_stmts_folded++;
@ -1066,12 +1066,12 @@ substitute_and_fold (prop_value_t *prop_value, ssa_prop_fold_stmt_fn fold_fn)
/* If we made a replacement, fold the statement. */
if (did_replace)
fold_stmt (&i);
fold_stmt (&oldi);
/* Now cleanup. */
if (did_replace)
{
stmt = gsi_stmt (i);
stmt = gsi_stmt (oldi);
/* If we cleaned up EH information from the statement,
remove EH edges. */
@ -1105,8 +1105,6 @@ substitute_and_fold (prop_value_t *prop_value, ssa_prop_fold_stmt_fn fold_fn)
else
fprintf (dump_file, "Not folded\n");
}
gsi_prev (&i);
}
}