diff options
author | Roger Sayle <roger@eyesopen.com> | 2002-04-23 10:17:37 +0000 |
---|---|---|
committer | Andreas Jaeger <aj@gcc.gnu.org> | 2002-04-23 12:17:37 +0200 |
commit | 1a887f860a2905e95ab853fb1f8adef14515d74e (patch) | |
tree | 5c7e4a7521145a5c59ecb25c52fa10c1cb4acc39 /gcc/builtins.c | |
parent | 77adef8498fb09947e889abbacb1d2bd8ece0929 (diff) | |
download | gcc-1a887f860a2905e95ab853fb1f8adef14515d74e.zip gcc-1a887f860a2905e95ab853fb1f8adef14515d74e.tar.gz gcc-1a887f860a2905e95ab853fb1f8adef14515d74e.tar.bz2 |
builtins.c (builtin_memset_gen_str): New function.
2002-04-23 Roger Sayle <roger@eyesopen.com>
* builtins.c (builtin_memset_gen_str): New function.
(expand_builtin_memset): Optimize the case of constant length, but
unknown value.
testsuite:
* gcc.c-torture/execute/string-opt-17.c: New test case.
* gcc.c-torture/execute/memset-2.c: New test case.
From-SVN: r52662
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index a1ffe0a..84d47dd 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -126,6 +126,8 @@ static rtx expand_builtin_strncpy PARAMS ((tree, rtx, enum machine_mode)); static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode)); +static rtx builtin_memset_gen_str PARAMS ((PTR, HOST_WIDE_INT, + enum machine_mode)); static rtx expand_builtin_memset PARAMS ((tree, rtx, enum machine_mode)); static rtx expand_builtin_bzero PARAMS ((tree)); @@ -2134,6 +2136,34 @@ builtin_memset_read_str (data, offset, mode) return c_readstr (p, mode); } +/* Callback routine for store_by_pieces. Return the RTL of a register + containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned + char value given in the RTL register data. For example, if mode is + 4 bytes wide, return the RTL for 0x01010101*data. */ + +static rtx +builtin_memset_gen_str (data, offset, mode) + PTR data; + HOST_WIDE_INT offset ATTRIBUTE_UNUSED; + enum machine_mode mode; +{ + rtx target, coeff; + size_t size; + char *p; + + size = GET_MODE_SIZE (mode); + if (size==1) + return (rtx)data; + + p = alloca (size); + memset (p, 1, size); + coeff = c_readstr (p, mode); + + target = convert_to_mode (mode, (rtx)data, 1); + target = expand_mult (mode, target, coeff, NULL_RTX, 1); + return force_reg (mode, target); +} + /* Expand expression EXP, which is a call to the memset builtin. Return 0 if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's @@ -2175,7 +2205,34 @@ expand_builtin_memset (exp, target, mode) } if (TREE_CODE (val) != INTEGER_CST) - return 0; + { + rtx val_rtx; + + if (!host_integerp (len, 1)) + return 0; + + if (optimize_size && tree_low_cst (len, 1) > 1) + return 0; + + /* Assume that we can memset by pieces if we can store the + * the coefficients by pieces (in the required modes). + * We can't pass builtin_memset_gen_str as that emits RTL. */ + c = 1; + if (!can_store_by_pieces (tree_low_cst (len, 1), + builtin_memset_read_str, + (PTR) &c, dest_align)) + return 0; + + val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val)); + val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0); + val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node), + val_rtx); + dest_mem = get_memory_rtx (dest); + store_by_pieces (dest_mem, tree_low_cst (len, 1), + builtin_memset_gen_str, + (PTR)val_rtx, dest_align); + return force_operand (XEXP (dest_mem, 0), NULL_RTX); + } if (target_char_cast (val, &c)) return 0; |