fold-const.c (omit_two_operands): New function.
authorRoger Sayle <roger@eyesopen.com>
Sat, 12 Jun 2004 19:41:51 +0000 (19:41 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sat, 12 Jun 2004 19:41:51 +0000 (19:41 +0000)
* 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

gcc/ChangeLog
gcc/builtins.c
gcc/fold-const.c
gcc/tree.h

index 792940ca05999fb7089ddabc3d33a152d1142abd..69df57bf8148f8519e8a34a57db2bed3a8f467bd 100644 (file)
@@ -1,3 +1,17 @@
+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>,
            Andreas Jaeger  <aj@suse.de>
 
index 199900e2228f908b8623ed1bcd59a17e652038ed..78611ca6fe684b3512dbfc07302552924ac4aed4 100644 (file)
@@ -168,6 +168,8 @@ static tree fold_builtin_toascii (tree);
 static tree fold_builtin_isdigit (tree);
 static tree fold_builtin_fabs (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_strcmp (tree);
@@ -7608,6 +7610,33 @@ fold_builtin_abs (tree arglist, tree type)
   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
    the CALL_EXPR of a call to a builtin function.  */
 
@@ -8160,6 +8189,28 @@ fold_builtin_1 (tree exp)
     case BUILT_IN_COPYSIGNL:
       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:
       break;
     }
@@ -8772,13 +8823,9 @@ simplify_builtin_memcmp (tree arglist)
 
   /* If the len parameter is zero, return zero.  */
   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
-    {
-      /* Evaluate and ignore arg1 and arg2 in case they have
-         side-effects.  */
-      return build2 (COMPOUND_EXPR, integer_type_node, arg1,
-                    build2 (COMPOUND_EXPR, integer_type_node,
-                            arg2, integer_zero_node));
-    }
+    /* Evaluate and ignore arg1 and arg2 in case they have side-effects.  */
+    return omit_two_operands (integer_type_node, integer_zero_node,
+                             arg1, arg2);
 
   p1 = c_getstr (arg1);
   p2 = c_getstr (arg2);
@@ -8913,13 +8960,9 @@ simplify_builtin_strncmp (tree arglist)
 
   /* If the len parameter is zero, return zero.  */
   if (integer_zerop (arg3))
-    {
-      /* Evaluate and ignore arg1 and arg2 in case they have
-        side-effects.  */
-      return build2 (COMPOUND_EXPR, integer_type_node, arg1,
-                    build2 (COMPOUND_EXPR, integer_type_node,
-                            arg2, integer_zero_node));
-    }
+    /* Evaluate and ignore arg1 and arg2 in case they have side-effects.  */
+    return omit_two_operands (integer_type_node, integer_zero_node,
+                             arg1, arg2);
 
   /* If arg1 and arg2 are equal (and not volatile), return zero.  */
   if (operand_equal_p (arg1, arg2, 0))
@@ -9030,8 +9073,7 @@ simplify_builtin_strncat (tree arglist)
       /* If the requested length is zero, or the src parameter string
           length is zero, return the dst parameter.  */
       if (integer_zerop (len) || (p && *p == '\0'))
-       return build2 (COMPOUND_EXPR, TREE_TYPE (dst), src,
-                      build2 (COMPOUND_EXPR, integer_type_node, len, dst));
+        return omit_two_operands (TREE_TYPE (dst), dst, src, len);
 
       /* If the requested len is greater than or equal to the string
          length, call strcat.  */
@@ -9089,13 +9131,10 @@ simplify_builtin_strspn (tree arglist)
 
       /* If either argument is "", return 0.  */
       if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
-       {
-         /* Evaluate and ignore both arguments in case either one has
-            side-effects.  */
-         return build2 (COMPOUND_EXPR, integer_type_node, s1,
-                        build2 (COMPOUND_EXPR, integer_type_node,
-                                s2, integer_zero_node));
-       }
+       /* Evaluate and ignore both arguments in case either one has
+          side-effects.  */
+       return omit_two_operands (integer_type_node, integer_zero_node,
+                                 s1, s2);
       return 0;
     }
 }
index 3a7053e802ec01848d6b09073bfcf9ccf02b72bc..02f4128af49f4c11b32843137c4834280c80167b 100644 (file)
@@ -2828,6 +2828,29 @@ pedantic_omit_one_operand (tree type, tree result, tree omitted)
 
   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;
+}
+
 \f
 /* Return a simplified tree node for the truth-negation of ARG.  This
    never alters ARG itself.  We assume that ARG is an operation that
index 09c2fe3170769b357a8c58fb9f6ccd3be78b82a4..e0ba912becda878dd4dcc01d4d0783a488b693b9 100644 (file)
@@ -3508,6 +3508,7 @@ enum operand_equal_flag
 extern int operand_equal_p (tree, tree, unsigned int);
 
 extern tree omit_one_operand (tree, tree, tree);
+extern tree omit_two_operands (tree, tree, tree, tree);
 extern tree invert_truthvalue (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);