Commit 880864cf by Alan Modra Committed by Alan Modra

re PR middle-end/27095 (O2 produces duplicate code)

	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.

From-SVN: r112948
parent 1935e8a8
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> 2006-04-14 Kazu Hirata <kazu@codesourcery.com>
* basic-block.h (REG_BASIC_BLOCK): Use VEC instead of VARRAY. * basic-block.h (REG_BASIC_BLOCK): Use VEC instead of VARRAY.
......
...@@ -3390,12 +3390,14 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, ...@@ -3390,12 +3390,14 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
tree dest = TREE_VALUE (arglist); tree dest = TREE_VALUE (arglist);
tree val = TREE_VALUE (TREE_CHAIN (arglist)); tree val = TREE_VALUE (TREE_CHAIN (arglist));
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
tree fndecl, fn;
enum built_in_function fcode;
char c; char c;
unsigned int dest_align;
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, dest_addr, len_rtx; 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 /* If DEST is not a pointer type, don't do this
operation in-line. */ operation in-line. */
if (dest_align == 0) if (dest_align == 0)
...@@ -3409,15 +3411,21 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, ...@@ -3409,15 +3411,21 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
return expand_expr (dest, target, mode, EXPAND_NORMAL); 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); len_rtx = expand_normal (len);
dest_mem = get_memory_rtx (dest, len); dest_mem = get_memory_rtx (dest, len);
if (TREE_CODE (val) != INTEGER_CST) if (TREE_CODE (val) != INTEGER_CST)
{ {
tree cval;
rtx val_rtx; rtx val_rtx;
val = fold_build1 (CONVERT_EXPR, unsigned_char_type_node, val); cval = fold_build1 (CONVERT_EXPR, unsigned_char_type_node, val);
val_rtx = expand_normal (val); val_rtx = expand_normal (cval);
/* Assume that we can memset by pieces if we can store the /* Assume that we can memset by pieces if we can store the
* the coefficients by pieces (in the required modes). * the coefficients by pieces (in the required modes).
...@@ -3433,9 +3441,9 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, ...@@ -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), store_by_pieces (dest_mem, tree_low_cst (len, 1),
builtin_memset_gen_str, val_rtx, dest_align, 0); builtin_memset_gen_str, val_rtx, dest_align, 0);
} }
else if (!set_storage_via_setmem(dest_mem, len_rtx, val_rtx, else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
dest_align)) dest_align))
return 0; goto do_libcall;
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem); dest_mem = convert_memory_address (ptr_mode, dest_mem);
...@@ -3443,7 +3451,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, ...@@ -3443,7 +3451,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
} }
if (target_char_cast (val, &c)) if (target_char_cast (val, &c))
return 0; goto do_libcall;
if (c) if (c)
{ {
...@@ -3455,7 +3463,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, ...@@ -3455,7 +3463,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
builtin_memset_read_str, &c, dest_align, 0); builtin_memset_read_str, &c, dest_align, 0);
else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c), else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
dest_align)) dest_align))
return 0; goto do_libcall;
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem); dest_mem = convert_memory_address (ptr_mode, dest_mem);
...@@ -3474,6 +3482,19 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, ...@@ -3474,6 +3482,19 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
} }
return dest_addr; 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) ...@@ -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 both arguments have side effects, we cannot optimize. */
if (!len || TREE_SIDE_EFFECTS (len)) if (!len || TREE_SIDE_EFFECTS (len))
return 0; goto do_libcall;
/* Stabilize the arguments in case gen_cmpstrnsi fails. */
arg3_rtx = expand_normal (len); arg3_rtx = expand_normal (len);
/* Make a place to write the result of the instruction. */ /* 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) ...@@ -3752,6 +3772,7 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
/* Expand the library call ourselves using a stabilized argument /* Expand the library call ourselves using a stabilized argument
list to avoid re-evaluating the function's arguments twice. */ list to avoid re-evaluating the function's arguments twice. */
do_libcall:
arglist = build_tree_list (NULL_TREE, arg2); arglist = build_tree_list (NULL_TREE, arg2);
arglist = tree_cons (NULL_TREE, arg1, arglist); arglist = tree_cons (NULL_TREE, arg1, arglist);
fndecl = get_callee_fndecl (exp); fndecl = get_callee_fndecl (exp);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment