Commit 08039bd8 by Roger Sayle Committed by Roger Sayle

fold-const.c (omit_two_operands): New function.


	* fold-const.c (omit_two_operands): New function.
	* tree.h (omit_two_operands): Prototype here.
	* builtins.c (fold_builtin_unordered_cmp): New function to lower
	C99 unordered comparison builtins to the appropriate tree nodes.
	(fold_builtin_1): Use fold_builtin_unordered_cmp to lower
	BUILT_IN_ISGREATER, BUILT_IN_ISGREATEREQUAL, BUILT_IN_ISLESS,
	BUILT_IN_ISLESSEQUAL and BUILT_IN_ISLESSGREATER.  Manually lower
	BUILT_IN_ISUNORDERED comparisons to an UNORDERED_EXPR tree node.
	(simplify_builtin_memcmp, simplify_builtin_strncmp,
	simplify_builtin_strncat, simplify_builtin_strspn): Use the new
	omit_two_operands function to build the required COMPOUND_EXPRs.

From-SVN: r83040
parent a2a2059f
2004-06-12 Roger Sayle <roger@eyesopen.com>
* fold-const.c (omit_two_operands): New function.
* tree.h (omit_two_operands): Prototype here.
* builtins.c (fold_builtin_unordered_cmp): New function to lower
C99 unordered comparison builtins to the appropriate tree nodes.
(fold_builtin_1): Use fold_builtin_unordered_cmp to lower
BUILT_IN_ISGREATER, BUILT_IN_ISGREATEREQUAL, BUILT_IN_ISLESS,
BUILT_IN_ISLESSEQUAL and BUILT_IN_ISLESSGREATER. Manually lower
BUILT_IN_ISUNORDERED comparisons to an UNORDERED_EXPR tree node.
(simplify_builtin_memcmp, simplify_builtin_strncmp,
simplify_builtin_strncat, simplify_builtin_strspn): Use the new
omit_two_operands function to build the required COMPOUND_EXPRs.
2004-06-12 Steven Bosscher <stevenb@suse.de>, 2004-06-12 Steven Bosscher <stevenb@suse.de>,
Andreas Jaeger <aj@suse.de> Andreas Jaeger <aj@suse.de>
......
...@@ -168,6 +168,8 @@ static tree fold_builtin_toascii (tree); ...@@ -168,6 +168,8 @@ static tree fold_builtin_toascii (tree);
static tree fold_builtin_isdigit (tree); static tree fold_builtin_isdigit (tree);
static tree fold_builtin_fabs (tree, tree); static tree fold_builtin_fabs (tree, tree);
static tree fold_builtin_abs (tree, tree); static tree fold_builtin_abs (tree, tree);
static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
enum tree_code);
static tree simplify_builtin_memcmp (tree); static tree simplify_builtin_memcmp (tree);
static tree simplify_builtin_strcmp (tree); static tree simplify_builtin_strcmp (tree);
...@@ -7608,6 +7610,33 @@ fold_builtin_abs (tree arglist, tree type) ...@@ -7608,6 +7610,33 @@ fold_builtin_abs (tree arglist, tree type)
return fold (build1 (ABS_EXPR, type, arg)); return fold (build1 (ABS_EXPR, type, arg));
} }
/* Fold a call to an unordered comparison function such as
__builtin_isgreater(). ARGLIST is the funtion's argument list
and TYPE is the functions return type. UNORDERED_CODE and
ORDERED_CODE are comparison codes that give the opposite of
the desired result. UNORDERED_CODE is used for modes that can
hold NaNs and ORDERED_CODE is used for the rest. */
static tree
fold_builtin_unordered_cmp (tree arglist, tree type,
enum tree_code unordered_code,
enum tree_code ordered_code)
{
enum tree_code code;
tree arg0, arg1;
if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
return 0;
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
code = MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
: ordered_code;
return fold (build1 (TRUTH_NOT_EXPR, type,
fold (build2 (code, type, arg0, arg1))));
}
/* Used by constant folding to eliminate some builtin calls early. EXP is /* Used by constant folding to eliminate some builtin calls early. EXP is
the CALL_EXPR of a call to a builtin function. */ the CALL_EXPR of a call to a builtin function. */
...@@ -8160,6 +8189,28 @@ fold_builtin_1 (tree exp) ...@@ -8160,6 +8189,28 @@ fold_builtin_1 (tree exp)
case BUILT_IN_COPYSIGNL: case BUILT_IN_COPYSIGNL:
return fold_builtin_copysign (arglist, type); return fold_builtin_copysign (arglist, type);
case BUILT_IN_ISGREATER:
return fold_builtin_unordered_cmp (arglist, type, UNLE_EXPR, LE_EXPR);
case BUILT_IN_ISGREATEREQUAL:
return fold_builtin_unordered_cmp (arglist, type, UNLT_EXPR, LT_EXPR);
case BUILT_IN_ISLESS:
return fold_builtin_unordered_cmp (arglist, type, UNGE_EXPR, GE_EXPR);
case BUILT_IN_ISLESSEQUAL:
return fold_builtin_unordered_cmp (arglist, type, UNGT_EXPR, GT_EXPR);
case BUILT_IN_ISLESSGREATER:
return fold_builtin_unordered_cmp (arglist, type, UNEQ_EXPR, EQ_EXPR);
case BUILT_IN_ISUNORDERED:
if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
{
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))))
return omit_two_operands (type, integer_zero_node, arg0, arg1);
return fold (build2 (UNORDERED_EXPR, type, arg0, arg1));
}
break;
default: default:
break; break;
} }
...@@ -8772,13 +8823,9 @@ simplify_builtin_memcmp (tree arglist) ...@@ -8772,13 +8823,9 @@ simplify_builtin_memcmp (tree arglist)
/* If the len parameter is zero, return zero. */ /* If the len parameter is zero, return zero. */
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0) if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
{ /* Evaluate and ignore arg1 and arg2 in case they have side-effects. */
/* Evaluate and ignore arg1 and arg2 in case they have return omit_two_operands (integer_type_node, integer_zero_node,
side-effects. */ arg1, arg2);
return build2 (COMPOUND_EXPR, integer_type_node, arg1,
build2 (COMPOUND_EXPR, integer_type_node,
arg2, integer_zero_node));
}
p1 = c_getstr (arg1); p1 = c_getstr (arg1);
p2 = c_getstr (arg2); p2 = c_getstr (arg2);
...@@ -8913,13 +8960,9 @@ simplify_builtin_strncmp (tree arglist) ...@@ -8913,13 +8960,9 @@ simplify_builtin_strncmp (tree arglist)
/* If the len parameter is zero, return zero. */ /* If the len parameter is zero, return zero. */
if (integer_zerop (arg3)) if (integer_zerop (arg3))
{ /* Evaluate and ignore arg1 and arg2 in case they have side-effects. */
/* Evaluate and ignore arg1 and arg2 in case they have return omit_two_operands (integer_type_node, integer_zero_node,
side-effects. */ arg1, arg2);
return build2 (COMPOUND_EXPR, integer_type_node, arg1,
build2 (COMPOUND_EXPR, integer_type_node,
arg2, integer_zero_node));
}
/* If arg1 and arg2 are equal (and not volatile), return zero. */ /* If arg1 and arg2 are equal (and not volatile), return zero. */
if (operand_equal_p (arg1, arg2, 0)) if (operand_equal_p (arg1, arg2, 0))
...@@ -9030,8 +9073,7 @@ simplify_builtin_strncat (tree arglist) ...@@ -9030,8 +9073,7 @@ simplify_builtin_strncat (tree arglist)
/* If the requested length is zero, or the src parameter string /* If the requested length is zero, or the src parameter string
length is zero, return the dst parameter. */ length is zero, return the dst parameter. */
if (integer_zerop (len) || (p && *p == '\0')) if (integer_zerop (len) || (p && *p == '\0'))
return build2 (COMPOUND_EXPR, TREE_TYPE (dst), src, return omit_two_operands (TREE_TYPE (dst), dst, src, len);
build2 (COMPOUND_EXPR, integer_type_node, len, dst));
/* If the requested len is greater than or equal to the string /* If the requested len is greater than or equal to the string
length, call strcat. */ length, call strcat. */
...@@ -9089,13 +9131,10 @@ simplify_builtin_strspn (tree arglist) ...@@ -9089,13 +9131,10 @@ simplify_builtin_strspn (tree arglist)
/* If either argument is "", return 0. */ /* If either argument is "", return 0. */
if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')) if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
{ /* Evaluate and ignore both arguments in case either one has
/* Evaluate and ignore both arguments in case either one has side-effects. */
side-effects. */ return omit_two_operands (integer_type_node, integer_zero_node,
return build2 (COMPOUND_EXPR, integer_type_node, s1, s1, s2);
build2 (COMPOUND_EXPR, integer_type_node,
s2, integer_zero_node));
}
return 0; return 0;
} }
} }
......
...@@ -2828,6 +2828,29 @@ pedantic_omit_one_operand (tree type, tree result, tree omitted) ...@@ -2828,6 +2828,29 @@ pedantic_omit_one_operand (tree type, tree result, tree omitted)
return pedantic_non_lvalue (t); return pedantic_non_lvalue (t);
} }
/* Return a tree for the case when the result of an expression is RESULT
converted to TYPE and OMITTED1 and OMITTED2 were previously operands
of the expression but are now not needed.
If OMITTED1 or OMITTED2 has side effects, they must be evaluated.
If both OMITTED1 and OMITTED2 have side effects, OMITTED1 is
evaluated before OMITTED2. Otherwise, if neither has side effects,
just do the conversion of RESULT to TYPE. */
tree
omit_two_operands (tree type, tree result, tree omitted1, tree omitted2)
{
tree t = fold_convert (type, result);
if (TREE_SIDE_EFFECTS (omitted2))
t = build2 (COMPOUND_EXPR, type, omitted2, t);
if (TREE_SIDE_EFFECTS (omitted1))
t = build2 (COMPOUND_EXPR, type, omitted1, t);
return TREE_CODE (t) != COMPOUND_EXPR ? non_lvalue (t) : t;
}
/* Return a simplified tree node for the truth-negation of ARG. This /* Return a simplified tree node for the truth-negation of ARG. This
never alters ARG itself. We assume that ARG is an operation that never alters ARG itself. We assume that ARG is an operation that
......
...@@ -3508,6 +3508,7 @@ enum operand_equal_flag ...@@ -3508,6 +3508,7 @@ enum operand_equal_flag
extern int operand_equal_p (tree, tree, unsigned int); extern int operand_equal_p (tree, tree, unsigned int);
extern tree omit_one_operand (tree, tree, tree); extern tree omit_one_operand (tree, tree, tree);
extern tree omit_two_operands (tree, tree, tree, tree);
extern tree invert_truthvalue (tree); extern tree invert_truthvalue (tree);
extern tree nondestructive_fold_unary_to_constant (enum tree_code, tree, tree); extern tree nondestructive_fold_unary_to_constant (enum tree_code, tree, tree);
extern tree nondestructive_fold_binary_to_constant (enum tree_code, tree, tree, tree); extern tree nondestructive_fold_binary_to_constant (enum tree_code, tree, tree, tree);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment