diff options
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; |