diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/builtins.c | 45 |
2 files changed, 40 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9baf93d..c0ccec9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2006-04-14 Alan Modra <amodra@bigpond.net.au> + + PR middle-end/27095 + * builtins.c: (expand_builtin_memset): Stabilize args before expansion + and emit libcall here in case the builtin fails. + (expand_builtin_strcmp): Always emit the libcall here on failure. + 2006-04-14 Kazu Hirata <kazu@codesourcery.com> * basic-block.h (REG_BASIC_BLOCK): Use VEC instead of VARRAY. diff --git a/gcc/builtins.c b/gcc/builtins.c index f504e31..c4d7ec2 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3390,12 +3390,14 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, tree dest = TREE_VALUE (arglist); tree val = TREE_VALUE (TREE_CHAIN (arglist)); tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + tree fndecl, fn; + enum built_in_function fcode; char c; - - unsigned int dest_align - = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); + unsigned int dest_align; rtx dest_mem, dest_addr, len_rtx; + dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); + /* If DEST is not a pointer type, don't do this operation in-line. */ if (dest_align == 0) @@ -3409,15 +3411,21 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, return expand_expr (dest, target, mode, EXPAND_NORMAL); } + /* Stabilize the arguments in case we fail. */ + dest = builtin_save_expr (dest); + val = builtin_save_expr (val); + len = builtin_save_expr (len); + len_rtx = expand_normal (len); dest_mem = get_memory_rtx (dest, len); if (TREE_CODE (val) != INTEGER_CST) { + tree cval; rtx val_rtx; - val = fold_build1 (CONVERT_EXPR, unsigned_char_type_node, val); - val_rtx = expand_normal (val); + cval = fold_build1 (CONVERT_EXPR, unsigned_char_type_node, val); + val_rtx = expand_normal (cval); /* Assume that we can memset by pieces if we can store the * the coefficients by pieces (in the required modes). @@ -3433,9 +3441,9 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, store_by_pieces (dest_mem, tree_low_cst (len, 1), builtin_memset_gen_str, val_rtx, dest_align, 0); } - else if (!set_storage_via_setmem(dest_mem, len_rtx, val_rtx, - dest_align)) - return 0; + else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx, + dest_align)) + goto do_libcall; dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); dest_mem = convert_memory_address (ptr_mode, dest_mem); @@ -3443,7 +3451,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, } if (target_char_cast (val, &c)) - return 0; + goto do_libcall; if (c) { @@ -3455,7 +3463,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, builtin_memset_read_str, &c, dest_align, 0); else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c), dest_align)) - return 0; + goto do_libcall; dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); dest_mem = convert_memory_address (ptr_mode, dest_mem); @@ -3474,6 +3482,19 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, } return dest_addr; + + do_libcall: + fndecl = get_callee_fndecl (orig_exp); + fcode = DECL_FUNCTION_CODE (fndecl); + gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO); + arglist = build_tree_list (NULL_TREE, len); + if (fcode == BUILT_IN_MEMSET) + arglist = tree_cons (NULL_TREE, val, arglist); + arglist = tree_cons (NULL_TREE, dest, arglist); + fn = build_function_call_expr (fndecl, arglist); + if (TREE_CODE (fn) == CALL_EXPR) + CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp); + return expand_call (fn, target, target == const0_rtx); } } @@ -3719,9 +3740,8 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) /* If both arguments have side effects, we cannot optimize. */ if (!len || TREE_SIDE_EFFECTS (len)) - return 0; + goto do_libcall; - /* Stabilize the arguments in case gen_cmpstrnsi fails. */ arg3_rtx = expand_normal (len); /* Make a place to write the result of the instruction. */ @@ -3752,6 +3772,7 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) /* Expand the library call ourselves using a stabilized argument list to avoid re-evaluating the function's arguments twice. */ + do_libcall: arglist = build_tree_list (NULL_TREE, arg2); arglist = tree_cons (NULL_TREE, arg1, arglist); fndecl = get_callee_fndecl (exp); |