This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PR27095, builtin_expand_memset multiple arg expansion
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 13 Apr 2006 23:50:00 +0930
- Subject: PR27095, builtin_expand_memset multiple arg expansion
:ADDPATCH middle-end:
Some time ago, Roger fixed a similar problem with expand_builtin_strcmp
to this one with expand_builtin_memset. I've followed Roger's lead in
stopping multiple expansion of args by wrapping the args in a save_expr
and, if the builtin expansion fails for some reason, expanding the
libcall using the wrapped args. As far as I can see, other builtin
string functions don't need similar fixes, but while I was checking them
I noticed that a bug had crept into expand_builtin_strcmp.
Bootstrapped and regression tested powerpc64-linux. OK mainline and
4.1?
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.
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c (revision 112911)
+++ gcc/builtins.c (working copy)
@@ -3390,12 +3390,14 @@ expand_builtin_memset (tree arglist, rtx
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
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
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
}
if (target_char_cast (val, &c))
- return 0;
+ goto do_libcall;
if (c)
{
@@ -3455,7 +3463,7 @@ expand_builtin_memset (tree arglist, rtx
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
}
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 tar
/* 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 tar
/* 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);
--
Alan Modra
IBM OzLabs - Linux Technology Centre