aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2002-04-23 10:17:37 +0000
committerAndreas Jaeger <aj@gcc.gnu.org>2002-04-23 12:17:37 +0200
commit1a887f860a2905e95ab853fb1f8adef14515d74e (patch)
tree5c7e4a7521145a5c59ecb25c52fa10c1cb4acc39 /gcc/builtins.c
parent77adef8498fb09947e889abbacb1d2bd8ece0929 (diff)
downloadgcc-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.c59
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;