builtins.c (fold_builtin_memcpy, [...]): New functions.
* builtins.c (fold_builtin_memcpy, fold_builtin_mempcpy, fold_builtin_memmove, fold_builtin_strcpy, fold_builtin_strncpy, fold_builtin_memcmp, fold_builtin_strcmp, fold_builtin_strncmp): New functions. (expand_builtin_memcpy): Use integer_zerop instead of testing host_integerp and tree_low_cst directly. Move misapplied hunk for optimization wher SRC and DEST point to the same location. (expand_builtin_mempcpy): From here. (expand_builtin_memmove): Use integer_zerop instead of testing host_integerp and tree_low_cst_directly. (expand_builtin_memset): Likewise. (expand_builtin_memcmp): Likewise (and for integer_onep). (expand_builtin_strncmp): Likewise. (fold_builtin): Call the appropriate fold_builtin_foo functions to optimize memcpy, mempcpy, memmove, strcpy, strncpy, memcmp, strcmp and strncmp. From-SVN: r72547
This commit is contained in:
parent
8725a9b499
commit
5bb650ec1b
2 changed files with 321 additions and 16 deletions
|
@ -1,3 +1,22 @@
|
|||
2003-10-15 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* builtins.c (fold_builtin_memcpy, fold_builtin_mempcpy,
|
||||
fold_builtin_memmove, fold_builtin_strcpy, fold_builtin_strncpy,
|
||||
fold_builtin_memcmp, fold_builtin_strcmp, fold_builtin_strncmp):
|
||||
New functions.
|
||||
(expand_builtin_memcpy): Use integer_zerop instead of testing
|
||||
host_integerp and tree_low_cst directly. Move misapplied hunk
|
||||
for optimization wher SRC and DEST point to the same location.
|
||||
(expand_builtin_mempcpy): From here.
|
||||
(expand_builtin_memmove): Use integer_zerop instead of testing
|
||||
host_integerp and tree_low_cst_directly.
|
||||
(expand_builtin_memset): Likewise.
|
||||
(expand_builtin_memcmp): Likewise (and for integer_onep).
|
||||
(expand_builtin_strncmp): Likewise.
|
||||
(fold_builtin): Call the appropriate fold_builtin_foo functions
|
||||
to optimize memcpy, mempcpy, memmove, strcpy, strncpy, memcmp,
|
||||
strcmp and strncmp.
|
||||
|
||||
2003-10-15 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* config/darwin-protos.h (machopic_non_lazy_ptr_name): Delete
|
||||
|
@ -11,8 +30,8 @@
|
|||
|
||||
2003-10-15 Gábor Lóki <alga@rgai.hu>
|
||||
|
||||
* fold-const.c (tree_swap_operands_p): disables
|
||||
some features when optimizing for size.
|
||||
* fold-const.c (tree_swap_operands_p): Disable some features
|
||||
when optimizing for size.
|
||||
|
||||
2003-10-15 David Daney <ddaney@avtrex.com>
|
||||
|
||||
|
|
314
gcc/builtins.c
314
gcc/builtins.c
|
@ -157,6 +157,14 @@ static tree fold_builtin_trunc (tree);
|
|||
static tree fold_builtin_floor (tree);
|
||||
static tree fold_builtin_ceil (tree);
|
||||
static tree fold_builtin_bitop (tree);
|
||||
static tree fold_builtin_memcpy (tree);
|
||||
static tree fold_builtin_mempcpy (tree);
|
||||
static tree fold_builtin_memmove (tree);
|
||||
static tree fold_builtin_strcpy (tree);
|
||||
static tree fold_builtin_strncpy (tree);
|
||||
static tree fold_builtin_memcmp (tree);
|
||||
static tree fold_builtin_strcmp (tree);
|
||||
static tree fold_builtin_strncmp (tree);
|
||||
|
||||
/* Return the alignment in bits of EXP, a pointer valued expression.
|
||||
But don't return more than MAX_ALIGN no matter what.
|
||||
|
@ -2474,13 +2482,21 @@ expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
|
|||
return 0;
|
||||
|
||||
/* If the LEN parameter is zero, return DEST. */
|
||||
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
|
||||
if (integer_zerop (len))
|
||||
{
|
||||
/* Evaluate and ignore SRC in case it has side-effects. */
|
||||
expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
return expand_expr (dest, target, mode, EXPAND_NORMAL);
|
||||
}
|
||||
|
||||
/* If SRC and DEST are the same (and not volatile), return DEST. */
|
||||
if (operand_equal_p (src, dest, 0))
|
||||
{
|
||||
/* Evaluate and ignore LEN in case it has side-effects. */
|
||||
expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
return expand_expr (dest, target, mode, EXPAND_NORMAL);
|
||||
}
|
||||
|
||||
/* If either SRC is not a pointer type, don't do this
|
||||
operation in-line. */
|
||||
if (src_align == 0)
|
||||
|
@ -2597,14 +2613,6 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
|
|||
return expand_expr (dest, target, mode, EXPAND_NORMAL);
|
||||
}
|
||||
|
||||
/* If SRC and DEST are the same (and not volatile), return DEST. */
|
||||
if (operand_equal_p (src, dest, 0))
|
||||
{
|
||||
/* Evaluate and ignore LEN in case it has side-effects. */
|
||||
expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
return expand_expr (dest, target, mode, EXPAND_NORMAL);
|
||||
}
|
||||
|
||||
/* If either SRC is not a pointer type, don't do this
|
||||
operation in-line. */
|
||||
if (src_align == 0)
|
||||
|
@ -2675,7 +2683,7 @@ expand_builtin_memmove (tree arglist, rtx target, enum machine_mode mode)
|
|||
return 0;
|
||||
|
||||
/* If the LEN parameter is zero, return DEST. */
|
||||
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
|
||||
if (integer_zerop (len))
|
||||
{
|
||||
/* Evaluate and ignore SRC in case it has side-effects. */
|
||||
expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
|
@ -2975,7 +2983,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
|
|||
return 0;
|
||||
|
||||
/* If the LEN parameter is zero, return DEST. */
|
||||
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
|
||||
if (integer_zerop (len))
|
||||
{
|
||||
/* Evaluate and ignore VAL in case it has side-effects. */
|
||||
expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
|
@ -3098,7 +3106,7 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
|
|||
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* If the len parameter is zero, return zero. */
|
||||
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
|
||||
if (integer_zerop (len))
|
||||
{
|
||||
/* Evaluate and ignore arg1 and arg2 in case they have
|
||||
side-effects. */
|
||||
|
@ -3131,7 +3139,7 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
|
|||
|
||||
/* If len parameter is one, return an expression corresponding to
|
||||
(*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
|
||||
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
|
||||
if (integer_onep (len))
|
||||
{
|
||||
tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
|
||||
tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
|
||||
|
@ -3392,7 +3400,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
|
|||
arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* If the len parameter is zero, return zero. */
|
||||
if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
|
||||
if (integer_zerop (arg3))
|
||||
{
|
||||
/* Evaluate and ignore arg1 and arg2 in case they have
|
||||
side-effects. */
|
||||
|
@ -6190,6 +6198,260 @@ fold_builtin_exponent (tree exp, const REAL_VALUE_TYPE *value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Fold function call to builtin memcpy. Return
|
||||
NULL_TREE if no simplification can be made. */
|
||||
|
||||
static tree
|
||||
fold_builtin_memcpy (tree exp)
|
||||
{
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree dest, src, len;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
|
||||
return 0;
|
||||
|
||||
dest = TREE_VALUE (arglist);
|
||||
src = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* If the LEN parameter is zero, return DEST. */
|
||||
if (integer_zerop (len))
|
||||
return omit_one_operand (TREE_TYPE (exp), dest, src);
|
||||
|
||||
/* If SRC and DEST are the same (and not volatile), return DEST. */
|
||||
if (operand_equal_p (src, dest, 0))
|
||||
return omit_one_operand (TREE_TYPE (exp), dest, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fold function call to builtin mempcpy. Return
|
||||
NULL_TREE if no simplification can be made. */
|
||||
|
||||
static tree
|
||||
fold_builtin_mempcpy (tree exp)
|
||||
{
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree dest, src, len;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
|
||||
return 0;
|
||||
|
||||
dest = TREE_VALUE (arglist);
|
||||
src = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* If the LEN parameter is zero, return DEST. */
|
||||
if (integer_zerop (len))
|
||||
return omit_one_operand (TREE_TYPE (exp), dest, src);
|
||||
|
||||
/* If SRC and DEST are the same (and not volatile), return DEST+LEN. */
|
||||
if (operand_equal_p (src, dest, 0))
|
||||
{
|
||||
tree temp = convert (TREE_TYPE (dest), len);
|
||||
temp = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, len));
|
||||
return convert (TREE_TYPE (exp), temp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fold function call to builtin memmove. Return
|
||||
NULL_TREE if no simplification can be made. */
|
||||
|
||||
static tree
|
||||
fold_builtin_memmove (tree exp)
|
||||
{
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree dest, src, len;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
|
||||
return 0;
|
||||
|
||||
dest = TREE_VALUE (arglist);
|
||||
src = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* If the LEN parameter is zero, return DEST. */
|
||||
if (integer_zerop (len))
|
||||
return omit_one_operand (TREE_TYPE (exp), dest, src);
|
||||
|
||||
/* If SRC and DEST are the same (and not volatile), return DEST. */
|
||||
if (operand_equal_p (src, dest, 0))
|
||||
return omit_one_operand (TREE_TYPE (exp), dest, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fold function call to builtin strcpy. Return
|
||||
NULL_TREE if no simplification can be made. */
|
||||
|
||||
static tree
|
||||
fold_builtin_strcpy (tree exp)
|
||||
{
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree dest, src;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
|
||||
return 0;
|
||||
|
||||
dest = TREE_VALUE (arglist);
|
||||
src = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
|
||||
/* If SRC and DEST are the same (and not volatile), return DEST. */
|
||||
if (operand_equal_p (src, dest, 0))
|
||||
return convert (TREE_TYPE (exp), dest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fold function call to builtin strncpy. Return
|
||||
NULL_TREE if no simplification can be made. */
|
||||
|
||||
static tree
|
||||
fold_builtin_strncpy (tree exp)
|
||||
{
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree dest, src, len;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
|
||||
return 0;
|
||||
|
||||
dest = TREE_VALUE (arglist);
|
||||
src = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* If the LEN parameter is zero, return DEST. */
|
||||
if (integer_zerop (len))
|
||||
return omit_one_operand (TREE_TYPE (exp), dest, src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fold function call to builtin memcmp. Return
|
||||
NULL_TREE if no simplification can be made. */
|
||||
|
||||
static tree
|
||||
fold_builtin_memcmp (tree exp)
|
||||
{
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree arg1, arg2, len;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
|
||||
return 0;
|
||||
|
||||
arg1 = TREE_VALUE (arglist);
|
||||
arg2 = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* If the LEN parameter is zero, return zero. */
|
||||
if (integer_zerop (len))
|
||||
{
|
||||
tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
|
||||
return omit_one_operand (TREE_TYPE (exp), temp, arg1);
|
||||
}
|
||||
|
||||
/* If ARG1 and ARG2 are the same (and not volatile), return zero. */
|
||||
if (operand_equal_p (arg1, arg2, 0))
|
||||
return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fold function call to builtin strcmp. Return
|
||||
NULL_TREE if no simplification can be made. */
|
||||
|
||||
static tree
|
||||
fold_builtin_strcmp (tree exp)
|
||||
{
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree arg1, arg2;
|
||||
const char *p1, *p2;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
|
||||
return 0;
|
||||
|
||||
arg1 = TREE_VALUE (arglist);
|
||||
arg2 = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
|
||||
/* If ARG1 and ARG2 are the same (and not volatile), return zero. */
|
||||
if (operand_equal_p (arg1, arg2, 0))
|
||||
return convert (TREE_TYPE (exp), integer_zero_node);
|
||||
|
||||
p1 = c_getstr (arg1);
|
||||
p2 = c_getstr (arg2);
|
||||
|
||||
if (p1 && p2)
|
||||
{
|
||||
tree temp;
|
||||
const int i = strcmp (p1, p2);
|
||||
if (i < 0)
|
||||
temp = integer_minus_one_node;
|
||||
else if (i > 0)
|
||||
temp = integer_one_node;
|
||||
else
|
||||
temp = integer_zero_node;
|
||||
return convert (TREE_TYPE (exp), temp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fold function call to builtin strncmp. Return
|
||||
NULL_TREE if no simplification can be made. */
|
||||
|
||||
static tree
|
||||
fold_builtin_strncmp (tree exp)
|
||||
{
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree arg1, arg2, len;
|
||||
const char *p1, *p2;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
|
||||
return 0;
|
||||
|
||||
arg1 = TREE_VALUE (arglist);
|
||||
arg2 = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* If the LEN parameter is zero, return zero. */
|
||||
if (integer_zerop (len))
|
||||
{
|
||||
tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
|
||||
return omit_one_operand (TREE_TYPE (exp), temp, arg1);
|
||||
}
|
||||
|
||||
/* If ARG1 and ARG2 are the same (and not volatile), return zero. */
|
||||
if (operand_equal_p (arg1, arg2, 0))
|
||||
return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
|
||||
|
||||
p1 = c_getstr (arg1);
|
||||
p2 = c_getstr (arg2);
|
||||
|
||||
if (host_integerp (len, 1) && p1 && p2)
|
||||
{
|
||||
tree temp;
|
||||
const int i = strncmp (p1, p2, tree_low_cst (len, 1));
|
||||
if (i < 0)
|
||||
temp = integer_minus_one_node;
|
||||
else if (i > 0)
|
||||
temp = integer_one_node;
|
||||
else
|
||||
temp = integer_zero_node;
|
||||
return convert (TREE_TYPE (exp), temp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Used by constant folding to eliminate some builtin calls early. EXP is
|
||||
the CALL_EXPR of a call to a builtin function. */
|
||||
|
||||
|
@ -6585,6 +6847,30 @@ fold_builtin (tree exp)
|
|||
case BUILT_IN_PARITYLL:
|
||||
return fold_builtin_bitop (exp);
|
||||
|
||||
case BUILT_IN_MEMCPY:
|
||||
return fold_builtin_memcpy (exp);
|
||||
|
||||
case BUILT_IN_MEMPCPY:
|
||||
return fold_builtin_mempcpy (exp);
|
||||
|
||||
case BUILT_IN_MEMMOVE:
|
||||
return fold_builtin_memmove (exp);
|
||||
|
||||
case BUILT_IN_STRCPY:
|
||||
return fold_builtin_strcpy (exp);
|
||||
|
||||
case BUILT_IN_STRNCPY:
|
||||
return fold_builtin_strncpy (exp);
|
||||
|
||||
case BUILT_IN_MEMCMP:
|
||||
return fold_builtin_memcmp (exp);
|
||||
|
||||
case BUILT_IN_STRCMP:
|
||||
return fold_builtin_strcmp (exp);
|
||||
|
||||
case BUILT_IN_STRNCMP:
|
||||
return fold_builtin_strncmp (exp);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue