aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1996-06-28 14:35:10 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1996-06-28 14:35:10 -0400
commitd7f21d631f9250504b35e3873598ca5c34dd3a76 (patch)
treef4903329b5407b3096e2800d0a33826234154e94
parentb71e9de07c8ce5245b6489470d389b042c6aee69 (diff)
downloadgcc-d7f21d631f9250504b35e3873598ca5c34dd3a76.zip
gcc-d7f21d631f9250504b35e3873598ca5c34dd3a76.tar.gz
gcc-d7f21d631f9250504b35e3873598ca5c34dd3a76.tar.bz2
(expand_builtin, case BUILTIN_MEMSET): Open code memset where val == 0.
From-SVN: r12363
-rw-r--r--gcc/expr.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 1603b62..5dd6700 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8531,6 +8531,58 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return force_operand (dest_rtx, NULL_RTX);
}
+ case BUILT_IN_MEMSET:
+ /* If not optimizing, call the library function. */
+ if (!optimize && ! CALLED_AS_BUILT_IN (fndecl))
+ break;
+
+ if (arglist == 0
+ /* Arg could be non-pointer if user redeclared this fcn wrong. */
+ || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
+ || TREE_CHAIN (arglist) == 0
+ || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
+ != INTEGER_TYPE)
+ || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
+ || (INTEGER_CST
+ != (TREE_CODE (TREE_TYPE
+ (TREE_VALUE
+ (TREE_CHAIN (TREE_CHAIN (arglist))))))))
+ break;
+ else
+ {
+ tree dest = TREE_VALUE (arglist);
+ tree val = TREE_VALUE (TREE_CHAIN (arglist));
+ tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ tree type;
+
+ int dest_align
+ = get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
+ rtx dest_rtx, dest_mem;
+
+ /* If DEST is not a pointer type, don't do this
+ operation in-line. */
+ if (dest_align == 0)
+ break;
+
+ /* If VAL is not 0, don't do this operation in-line. */
+ if (expand_expr (val, NULL_RTX, VOIDmode, 0) != const0_rtx)
+ break;
+
+ dest_rtx = expand_expr (dest, NULL_RTX, ptr_mode, EXPAND_SUM);
+ dest_mem = gen_rtx (MEM, BLKmode,
+ memory_address (BLKmode, dest_rtx));
+ /* There could be a void* cast on top of the object. */
+ while (TREE_CODE (dest) == NOP_EXPR)
+ dest = TREE_OPERAND (dest, 0);
+ type = TREE_TYPE (TREE_TYPE (dest));
+ MEM_IN_STRUCT_P (dest_mem) = AGGREGATE_TYPE_P (type);
+
+ clear_storage (dest_mem, expand_expr (len, NULL_RTX, VOIDmode, 0),
+ dest_align);
+
+ return force_operand (dest_rtx, NULL_RTX);
+ }
+
/* These comparison functions need an instruction that returns an actual
index. An ordinary compare that just sets the condition codes
is not enough. */