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:
parent
d813aaba52
commit
44e10129de
|
@ -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>
|
2009-09-28 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* config/m32r/m32r.c (m32r_is_insn): Return false for debugging
|
* config/m32r/m32r.c (m32r_is_insn): Return false for debugging
|
||||||
|
|
985
gcc/builtins.c
985
gcc/builtins.c
File diff suppressed because it is too large
Load Diff
|
@ -12614,6 +12614,11 @@ fold_binary_loc (location_t loc,
|
||||||
return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
|
return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
|
||||||
fold_convert_loc (loc, type, arg0));
|
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,
|
/* If this is an equality comparison of the address of two non-weak,
|
||||||
unaliased symbols neither of which are extern (since we do not
|
unaliased symbols neither of which are extern (since we do not
|
||||||
have access to attributes for externs), then we know the result. */
|
have access to attributes for externs), then we know the result. */
|
||||||
|
|
|
@ -626,6 +626,11 @@ init_optimization_passes (void)
|
||||||
NEXT_PASS (pass_lower_complex);
|
NEXT_PASS (pass_lower_complex);
|
||||||
NEXT_PASS (pass_sra);
|
NEXT_PASS (pass_sra);
|
||||||
NEXT_PASS (pass_rename_ssa_copies);
|
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);
|
NEXT_PASS (pass_dominator);
|
||||||
/* The only const/copy propagation opportunities left after
|
/* The only const/copy propagation opportunities left after
|
||||||
DOM should be due to degenerate PHI nodes. So rather than
|
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_object_sizes);
|
||||||
NEXT_PASS (pass_ccp);
|
NEXT_PASS (pass_ccp);
|
||||||
NEXT_PASS (pass_copy_prop);
|
NEXT_PASS (pass_copy_prop);
|
||||||
NEXT_PASS (pass_fold_builtins);
|
|
||||||
NEXT_PASS (pass_cse_sincos);
|
NEXT_PASS (pass_cse_sincos);
|
||||||
NEXT_PASS (pass_optimize_bswap);
|
NEXT_PASS (pass_optimize_bswap);
|
||||||
NEXT_PASS (pass_split_crit_edges);
|
NEXT_PASS (pass_split_crit_edges);
|
||||||
|
@ -709,6 +713,7 @@ init_optimization_passes (void)
|
||||||
NEXT_PASS (pass_dse);
|
NEXT_PASS (pass_dse);
|
||||||
NEXT_PASS (pass_forwprop);
|
NEXT_PASS (pass_forwprop);
|
||||||
NEXT_PASS (pass_phiopt);
|
NEXT_PASS (pass_phiopt);
|
||||||
|
NEXT_PASS (pass_fold_builtins);
|
||||||
NEXT_PASS (pass_tail_calls);
|
NEXT_PASS (pass_tail_calls);
|
||||||
NEXT_PASS (pass_rename_ssa_copies);
|
NEXT_PASS (pass_rename_ssa_copies);
|
||||||
NEXT_PASS (pass_uncprop);
|
NEXT_PASS (pass_uncprop);
|
||||||
|
|
|
@ -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>
|
2009-09-27 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
* gcc.c-torture/compile/pr41469.c: Add -fexceptions.
|
* gcc.c-torture/compile/pr41469.c: Add -fexceptions.
|
||||||
|
|
|
@ -31,17 +31,13 @@ main ()
|
||||||
if (__builtin_isinfl (pinfl) != 1)
|
if (__builtin_isinfl (pinfl) != 1)
|
||||||
link_error ();
|
link_error ();
|
||||||
|
|
||||||
if (__builtin_isinf (-pinf) != -1)
|
if (__builtin_isinf_sign (-pinf) != -1)
|
||||||
link_error ();
|
link_error ();
|
||||||
#ifndef __SPU__
|
#ifndef __SPU__
|
||||||
if (__builtin_isinf (-pinff) != -1)
|
if (__builtin_isinf_sign (-pinff) != -1)
|
||||||
link_error ();
|
|
||||||
if (__builtin_isinff (-pinff) != -1)
|
|
||||||
link_error ();
|
link_error ();
|
||||||
#endif
|
#endif
|
||||||
if (__builtin_isinf (-pinfl) != -1)
|
if (__builtin_isinf_sign (-pinfl) != -1)
|
||||||
link_error ();
|
|
||||||
if (__builtin_isinfl (-pinfl) != -1)
|
|
||||||
link_error ();
|
link_error ();
|
||||||
|
|
||||||
if (__builtin_isinf (4.0))
|
if (__builtin_isinf (4.0))
|
||||||
|
|
|
@ -3873,7 +3873,48 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
|
||||||
gimple old_stmt = gsi_stmt (gsi);
|
gimple old_stmt = gsi_stmt (gsi);
|
||||||
tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
|
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
|
/* Re-read the statement from GSI as fold_stmt() may
|
||||||
have changed it. */
|
have changed it. */
|
||||||
|
@ -3882,7 +3923,8 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
|
||||||
|
|
||||||
if (is_gimple_call (old_stmt)
|
if (is_gimple_call (old_stmt)
|
||||||
|| is_gimple_call (new_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))
|
if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
|
||||||
gimple_purge_dead_eh_edges (BASIC_BLOCK (first));
|
gimple_purge_dead_eh_edges (BASIC_BLOCK (first));
|
||||||
|
|
|
@ -1424,8 +1424,8 @@ evaluate_stmt (gimple stmt)
|
||||||
else if (code == GIMPLE_SWITCH)
|
else if (code == GIMPLE_SWITCH)
|
||||||
simplified = gimple_switch_index (stmt);
|
simplified = gimple_switch_index (stmt);
|
||||||
else
|
else
|
||||||
/* These cannot satisfy is_gimple_min_invariant without folding. */
|
/* These cannot satisfy is_gimple_min_invariant without folding. */
|
||||||
gcc_assert (code == GIMPLE_CALL || code == GIMPLE_COND);
|
gcc_assert (code == GIMPLE_CALL || code == GIMPLE_COND);
|
||||||
}
|
}
|
||||||
|
|
||||||
is_constant = simplified && is_gimple_min_invariant (simplified);
|
is_constant = simplified && is_gimple_min_invariant (simplified);
|
||||||
|
@ -2895,6 +2895,7 @@ fold_gimple_cond (gimple stmt)
|
||||||
return false;
|
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.
|
/* 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
|
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);
|
tree result = ccp_fold_builtin (stmt);
|
||||||
|
|
||||||
if (result)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2133,6 +2133,20 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
|
||||||
{
|
{
|
||||||
eliminate_redundant_computations (&si);
|
eliminate_redundant_computations (&si);
|
||||||
stmt = gsi_stmt (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. */
|
/* Record any additional equivalences created by this statement. */
|
||||||
|
|
|
@ -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 stmt = gsi_stmt (i);
|
||||||
gimple old_stmt;
|
gimple old_stmt;
|
||||||
enum gimple_code code = gimple_code (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
|
/* Ignore ASSERT_EXPRs. They are used by VRP to generate
|
||||||
range information for names and they are discarded
|
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
|
if (code == GIMPLE_ASSIGN
|
||||||
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
|
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
|
||||||
{
|
continue;
|
||||||
gsi_prev (&i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No point propagating into a stmt whose result is not used,
|
/* No point propagating into a stmt whose result is not used,
|
||||||
but instead we might be able to remove a trivially dead stmt. */
|
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");
|
fprintf (dump_file, "\n");
|
||||||
}
|
}
|
||||||
prop_stats.num_dce++;
|
prop_stats.num_dce++;
|
||||||
gsi_prev (&i);
|
|
||||||
i2 = gsi_for_stmt (stmt);
|
i2 = gsi_for_stmt (stmt);
|
||||||
gsi_remove (&i2, true);
|
gsi_remove (&i2, true);
|
||||||
release_defs (stmt);
|
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
|
specific information. Do this before propagating
|
||||||
into the stmt to not disturb pass specific information. */
|
into the stmt to not disturb pass specific information. */
|
||||||
if (fold_fn
|
if (fold_fn
|
||||||
&& (*fold_fn)(&i))
|
&& (*fold_fn)(&oldi))
|
||||||
{
|
{
|
||||||
did_replace = true;
|
did_replace = true;
|
||||||
prop_stats.num_stmts_folded++;
|
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 we made a replacement, fold the statement. */
|
||||||
if (did_replace)
|
if (did_replace)
|
||||||
fold_stmt (&i);
|
fold_stmt (&oldi);
|
||||||
|
|
||||||
/* Now cleanup. */
|
/* Now cleanup. */
|
||||||
if (did_replace)
|
if (did_replace)
|
||||||
{
|
{
|
||||||
stmt = gsi_stmt (i);
|
stmt = gsi_stmt (oldi);
|
||||||
|
|
||||||
/* If we cleaned up EH information from the statement,
|
/* If we cleaned up EH information from the statement,
|
||||||
remove EH edges. */
|
remove EH edges. */
|
||||||
|
@ -1105,8 +1105,6 @@ substitute_and_fold (prop_value_t *prop_value, ssa_prop_fold_stmt_fn fold_fn)
|
||||||
else
|
else
|
||||||
fprintf (dump_file, "Not folded\n");
|
fprintf (dump_file, "Not folded\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
gsi_prev (&i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue