summaryrefslogtreecommitdiff
path: root/gcc/tree-inline.c
diff options
context:
space:
mode:
authormatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>2009-09-28 12:54:23 +0000
committermatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>2009-09-28 12:54:23 +0000
commita65c4d644bc63c7e9ed0df60898aac5aff8cc60c (patch)
treed0d5ddfb1d852abf4f125c9e24309f475790c349 /gcc/tree-inline.c
parentf5417e320113d343ff34f0e82f9130d779d2a065 (diff)
downloadgcc-a65c4d644bc63c7e9ed0df60898aac5aff8cc60c.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152236 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r--gcc/tree-inline.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index feb749985c2..6e1ea39aa92 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -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));