]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2015-07-15 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Jul 2015 08:35:15 +0000 (08:35 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Jul 2015 08:35:15 +0000 (08:35 +0000)
* genmatch.c (parser::peek, parser::peek_ident): Add argument
to tell how many tokens to peek ahead (default 1).
(parser::eat_token, parser::eat_ident): Return token consumed.
(parser::parse_result): Parse new switch statement.
* match.pd: Use case statements where appropriate.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@225809 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/genmatch.c
gcc/match.pd

index 6340afe464f8329a164728862aa960d6aa5983e8..44fa51a36169d913e8c56ec4ae794d40dc4c2989 100644 (file)
@@ -1,3 +1,11 @@
+2015-07-15  Richard Biener  <rguenther@suse.de>
+
+       * genmatch.c (parser::peek, parser::peek_ident): Add argument
+       to tell how many tokens to peek ahead (default 1).
+       (parser::eat_token, parser::eat_ident): Return token consumed.
+       (parser::parse_result): Parse new switch statement.
+       * match.pd: Use case statements where appropriate.
+
 2015-07-15  Uros Bizjak  <ubizjak@gmail.com>
 
        PR rtl-optimization/58066
index fa140dfe158ba97411f78267e846cb01672711f8..1434719a88ed023047e5180d4ce3e60459938081 100644 (file)
@@ -3014,13 +3014,13 @@ public:
 
 private:
   const cpp_token *next ();
-  const cpp_token *peek ();
-  const cpp_token *peek_ident (const char * = NULL);
+  const cpp_token *peek (unsigned = 1);
+  const cpp_token *peek_ident (const char * = NULL, unsigned = 1);
   const cpp_token *expect (enum cpp_ttype);
-  void eat_token (enum cpp_ttype);
+  const cpp_token *eat_token (enum cpp_ttype);
   const char *get_string ();
   const char *get_ident ();
-  void eat_ident (const char *);
+  const cpp_token *eat_ident (const char *);
   const char *get_number ();
 
   id_base *parse_operation ();
@@ -3078,7 +3078,7 @@ parser::next ()
 /* Peek at the next non-whitespace token from R.  */
 
 const cpp_token *
-parser::peek ()
+parser::peek (unsigned num)
 {
   const cpp_token *token;
   unsigned i = 0;
@@ -3086,8 +3086,9 @@ parser::peek ()
     {
       token = cpp_peek_token (r, i++);
     }
-  while (token->type == CPP_PADDING
-        && token->type != CPP_EOF);
+  while ((token->type == CPP_PADDING
+         && token->type != CPP_EOF)
+        || (--num > 0));
   /* If we peek at EOF this is a fatal error as it leaves the
      cpp_reader in unusable state.  Assume we really wanted a
      token and thus this EOF is unexpected.  */
@@ -3100,9 +3101,9 @@ parser::peek ()
    token is not an identifier or equal to ID if supplied).  */
 
 const cpp_token *
-parser::peek_ident (const char *id)
+parser::peek_ident (const char *id, unsigned num)
 {
-  const cpp_token *token = peek ();
+  const cpp_token *token = peek (num);
   if (token->type != CPP_NAME)
     return 0;
 
@@ -3131,10 +3132,10 @@ parser::expect (enum cpp_ttype tk)
 
 /* Consume the next token from R and assert it is of type TK.  */
 
-void
+const cpp_token *
 parser::eat_token (enum cpp_ttype tk)
 {
-  expect (tk);
+  return expect (tk);
 }
 
 /* Read the next token from R and assert it is of type CPP_STRING and
@@ -3159,13 +3160,14 @@ parser::get_ident ()
 
 /* Eat an identifier token with value S from R.  */
 
-void
+const cpp_token *
 parser::eat_ident (const char *s)
 {
   const cpp_token *token = peek ();
   const char *t = get_ident ();
   if (strcmp (s, t) != 0)
     fatal_at (token, "expected '%s' got '%s'\n", s, t);
+  return token;
 }
 
 /* Read the next token from R and assert it is of type CPP_NUMBER and
@@ -3557,6 +3559,58 @@ parser::parse_result (operand *result, predicate_id *matcher)
       eat_token (CPP_CLOSE_PAREN);
       return withe;
     }
+  else if (peek_ident ("switch"))
+    {
+      token = eat_ident ("switch");
+      eat_token (CPP_OPEN_PAREN);
+      eat_ident ("if");
+      if_expr *ife = new if_expr ();
+      operand *res = ife;
+      ife->cond = parse_c_expr (CPP_OPEN_PAREN);
+      if (peek ()->type == CPP_OPEN_PAREN)
+       ife->trueexpr = parse_result (result, matcher);
+      else
+       ife->trueexpr = parse_op ();
+      eat_token (CPP_CLOSE_PAREN);
+      if (peek ()->type != CPP_OPEN_PAREN
+         || !peek_ident ("if", 2))
+       fatal_at (token, "switch can be implemented with a single if");
+      while  (peek ()->type != CPP_CLOSE_PAREN)
+       {
+         if (peek ()->type == CPP_OPEN_PAREN)
+           {
+             if (peek_ident ("if", 2))
+               {
+                 eat_token (CPP_OPEN_PAREN);
+                 eat_ident ("if");
+                 ife->falseexpr = new if_expr ();
+                 ife = as_a <if_expr *> (ife->falseexpr);
+                 ife->cond = parse_c_expr (CPP_OPEN_PAREN);
+                 if (peek ()->type == CPP_OPEN_PAREN)
+                   ife->trueexpr = parse_result (result, matcher);
+                 else
+                   ife->trueexpr = parse_op ();
+                 eat_token (CPP_CLOSE_PAREN);
+               }
+             else
+               {
+                 /* switch default clause */
+                 ife->falseexpr = parse_result (result, matcher);
+                 eat_token (CPP_CLOSE_PAREN);
+                 return res;
+               }
+           }
+         else
+           {
+             /* switch default clause */
+             ife->falseexpr = parse_op ();
+             eat_token (CPP_CLOSE_PAREN);
+             return res;
+           }
+       }
+      eat_token (CPP_CLOSE_PAREN);
+      return res;
+    }
   else
     {
       operand *op = result;
index 8694854faa102b1f46662ebaf74653840a515ad4..8bedb235788882a11dc8884c759ae548e0e9b7b2 100644 (file)
@@ -1107,43 +1107,44 @@ along with GCC; see the file COPYING3.  If not see
       unsigned int final_prec = TYPE_PRECISION (type);
       int final_unsignedp = TYPE_UNSIGNED (type);
     }
-   /* In addition to the cases of two conversions in a row
-      handled below, if we are converting something to its own
-      type via an object of identical or wider precision, neither
-      conversion is needed.  */
-   (if (((GIMPLE && useless_type_conversion_p (type, inside_type))
-        || (GENERIC
-            && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type)))
-       && (((inter_int || inter_ptr) && final_int)
-           || (inter_float && final_float))
-       && inter_prec >= final_prec)
-    (ocvt @0)
-
-   /* Likewise, if the intermediate and initial types are either both
-      float or both integer, we don't need the middle conversion if the
-      former is wider than the latter and doesn't change the signedness
-      (for integers).  Avoid this if the final type is a pointer since
-      then we sometimes need the middle conversion.  Likewise if the
-      final type has a precision not equal to the size of its mode.  */
-   (if (((inter_int && inside_int) || (inter_float && inside_float))
-       && (final_int || final_float)
-       && inter_prec >= inside_prec
-       && (inter_float || inter_unsignedp == inside_unsignedp)
-       && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
-             && TYPE_MODE (type) == TYPE_MODE (inter_type)))
-    (ocvt @0)
-
-   /* If we have a sign-extension of a zero-extended value, we can
-      replace that by a single zero-extension.  Likewise if the
-      final conversion does not change precision we can drop the
-      intermediate conversion.  */
-   (if (inside_int && inter_int && final_int
-       && ((inside_prec < inter_prec && inter_prec < final_prec
-            && inside_unsignedp && !inter_unsignedp)
-           || final_prec == inter_prec))
-    (ocvt @0)
-
-   /* Two conversions in a row are not needed unless:
+   (switch
+    /* In addition to the cases of two conversions in a row
+       handled below, if we are converting something to its own
+       type via an object of identical or wider precision, neither
+       conversion is needed.  */
+    (if (((GIMPLE && useless_type_conversion_p (type, inside_type))
+         || (GENERIC
+             && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type)))
+        && (((inter_int || inter_ptr) && final_int)
+            || (inter_float && final_float))
+        && inter_prec >= final_prec)
+     (ocvt @0))
+
+    /* Likewise, if the intermediate and initial types are either both
+       float or both integer, we don't need the middle conversion if the
+       former is wider than the latter and doesn't change the signedness
+       (for integers).  Avoid this if the final type is a pointer since
+       then we sometimes need the middle conversion.  Likewise if the
+       final type has a precision not equal to the size of its mode.  */
+    (if (((inter_int && inside_int) || (inter_float && inside_float))
+        && (final_int || final_float)
+        && inter_prec >= inside_prec
+        && (inter_float || inter_unsignedp == inside_unsignedp)
+        && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
+              && TYPE_MODE (type) == TYPE_MODE (inter_type)))
+     (ocvt @0))
+
+    /* If we have a sign-extension of a zero-extended value, we can
+       replace that by a single zero-extension.  Likewise if the
+       final conversion does not change precision we can drop the
+       intermediate conversion.  */
+    (if (inside_int && inter_int && final_int
+        && ((inside_prec < inter_prec && inter_prec < final_prec
+             && inside_unsignedp && !inter_unsignedp)
+            || final_prec == inter_prec))
+     (ocvt @0))
+
+    /* Two conversions in a row are not needed unless:
        - some conversion is floating-point (overstrict for now), or
        - some conversion is a vector (overstrict for now), or
        - the intermediate type is narrower than both initial and
@@ -1154,39 +1155,39 @@ along with GCC; see the file COPYING3.  If not see
          intermediate and final types differ, or
        - the final type is a pointer type and the precisions of the
          initial and intermediate types differ.  */
-   (if (! inside_float && ! inter_float && ! final_float
-       && ! inside_vec && ! inter_vec && ! final_vec
-       && (inter_prec >= inside_prec || inter_prec >= final_prec)
-       && ! (inside_int && inter_int
-             && inter_unsignedp != inside_unsignedp
-             && inter_prec < final_prec)
-       && ((inter_unsignedp && inter_prec > inside_prec)
-           == (final_unsignedp && final_prec > inter_prec))
-       && ! (inside_ptr && inter_prec != final_prec)
-       && ! (final_ptr && inside_prec != inter_prec)
-       && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
-             && TYPE_MODE (type) == TYPE_MODE (inter_type)))
-    (ocvt @0)
-
-   /* A truncation to an unsigned type (a zero-extension) should be
-      canonicalized as bitwise and of a mask.  */
-   (if (final_int && inter_int && inside_int
-       && final_prec == inside_prec
-       && final_prec > inter_prec
-       && inter_unsignedp)
-    (convert (bit_and @0 { wide_int_to_tree
-                            (inside_type,
-                             wi::mask (inter_prec, false,
-                                       TYPE_PRECISION (inside_type))); }))
-
-   /* If we are converting an integer to a floating-point that can
-      represent it exactly and back to an integer, we can skip the
-      floating-point conversion.  */
-   (if (GIMPLE /* PR66211 */
-       && inside_int && inter_float && final_int &&
-       (unsigned) significand_size (TYPE_MODE (inter_type))
-       >= inside_prec - !inside_unsignedp)
-    (convert @0)))))))))))
+    (if (! inside_float && ! inter_float && ! final_float
+        && ! inside_vec && ! inter_vec && ! final_vec
+        && (inter_prec >= inside_prec || inter_prec >= final_prec)
+        && ! (inside_int && inter_int
+              && inter_unsignedp != inside_unsignedp
+              && inter_prec < final_prec)
+        && ((inter_unsignedp && inter_prec > inside_prec)
+            == (final_unsignedp && final_prec > inter_prec))
+        && ! (inside_ptr && inter_prec != final_prec)
+        && ! (final_ptr && inside_prec != inter_prec)
+        && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
+              && TYPE_MODE (type) == TYPE_MODE (inter_type)))
+     (ocvt @0))
+
+    /* A truncation to an unsigned type (a zero-extension) should be
+       canonicalized as bitwise and of a mask.  */
+    (if (final_int && inter_int && inside_int
+        && final_prec == inside_prec
+        && final_prec > inter_prec
+        && inter_unsignedp)
+     (convert (bit_and @0 { wide_int_to_tree
+                             (inside_type,
+                              wi::mask (inter_prec, false,
+                                        TYPE_PRECISION (inside_type))); })))
+
+    /* If we are converting an integer to a floating-point that can
+       represent it exactly and back to an integer, we can skip the
+       floating-point conversion.  */
+    (if (GIMPLE /* PR66211 */
+        && inside_int && inter_float && final_int &&
+        (unsigned) significand_size (TYPE_MODE (inter_type))
+        >= inside_prec - !inside_unsignedp)
+     (convert @0)))))))
 
 /* If we have a narrowing conversion to an integral type that is fed by a
    BIT_AND_EXPR, we might be able to remove the BIT_AND_EXPR if it merely
@@ -1463,58 +1464,60 @@ along with GCC; see the file COPYING3.  If not see
  (simplify
   (cmp @0 REAL_CST@1)
   /* IEEE doesn't distinguish +0 and -0 in comparisons.  */
-  /* a CMP (-0) -> a CMP 0  */
-  (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)))
-   (cmp @0 { build_real (TREE_TYPE (@1), dconst0); })
-  /* x != NaN is always true, other ops are always false.  */
-  (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
-       && ! HONOR_SNANS (@1))
-   { constant_boolean_node (cmp == NE_EXPR, type); }
-  /* Fold comparisons against infinity.  */
-  (if (REAL_VALUE_ISINF (TREE_REAL_CST (@1))
-       && MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (@1))))
-   (with
-    {
-      REAL_VALUE_TYPE max;
-      enum tree_code code = cmp;
-      bool neg = REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1));
-      if (neg)
-        code = swap_tree_comparison (code);
-    }
-    /* x > +Inf is always false, if with ignore sNANs.  */
-    (if (code == GT_EXPR
-        && ! HONOR_SNANS (@0))
-     { constant_boolean_node (false, type); }
-    (if (code == LE_EXPR)
-     /* x <= +Inf is always true, if we don't case about NaNs.  */
-     (if (! HONOR_NANS (@0))
-      { constant_boolean_node (true, type); }
-      /* x <= +Inf is the same as x == x, i.e. isfinite(x).  */
-      (eq @0 @0))
-    /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX.  */
-    (if (code == EQ_EXPR || code == GE_EXPR)
-     (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
-      (if (neg)
-       (lt @0 { build_real (TREE_TYPE (@0), max); })
-       (gt @0 { build_real (TREE_TYPE (@0), max); })))
-    /* x < +Inf is always equal to x <= DBL_MAX.  */
-    (if (code == LT_EXPR)
-     (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
-      (if (neg)
-       (ge @0 { build_real (TREE_TYPE (@0), max); })
-       (le @0 { build_real (TREE_TYPE (@0), max); })))
-    /* x != +Inf is always equal to !(x > DBL_MAX).  */
-    (if (code == NE_EXPR)
-     (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
-      (if (! HONOR_NANS (@0))
-       (if (neg)
-        (ge @0 { build_real (TREE_TYPE (@0), max); })
-       (le @0 { build_real (TREE_TYPE (@0), max); }))
-       (if (neg)
-       (bit_xor (lt @0 { build_real (TREE_TYPE (@0), max); })
-                       { build_one_cst (type); })
-       (bit_xor (gt @0 { build_real (TREE_TYPE (@0), max); })
-                       { build_one_cst (type); }))))))))))))))
+  (switch
+   /* a CMP (-0) -> a CMP 0  */
+   (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)))
+    (cmp @0 { build_real (TREE_TYPE (@1), dconst0); }))
+   /* x != NaN is always true, other ops are always false.  */
+   (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
+       && ! HONOR_SNANS (@1))
+    { constant_boolean_node (cmp == NE_EXPR, type); })
+   /* Fold comparisons against infinity.  */
+   (if (REAL_VALUE_ISINF (TREE_REAL_CST (@1))
+       && MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (@1))))
+    (with
+     {
+       REAL_VALUE_TYPE max;
+       enum tree_code code = cmp;
+       bool neg = REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1));
+       if (neg)
+         code = swap_tree_comparison (code);
+     }
+     (switch
+      /* x > +Inf is always false, if with ignore sNANs.  */
+      (if (code == GT_EXPR
+          && ! HONOR_SNANS (@0))
+       { constant_boolean_node (false, type); })
+      (if (code == LE_EXPR)
+       /* x <= +Inf is always true, if we don't case about NaNs.  */
+       (if (! HONOR_NANS (@0))
+       { constant_boolean_node (true, type); }
+       /* x <= +Inf is the same as x == x, i.e. isfinite(x).  */
+       (eq @0 @0)))
+      /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX.  */
+      (if (code == EQ_EXPR || code == GE_EXPR)
+       (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
+       (if (neg)
+        (lt @0 { build_real (TREE_TYPE (@0), max); })
+        (gt @0 { build_real (TREE_TYPE (@0), max); }))))
+      /* x < +Inf is always equal to x <= DBL_MAX.  */
+      (if (code == LT_EXPR)
+       (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
+       (if (neg)
+        (ge @0 { build_real (TREE_TYPE (@0), max); })
+        (le @0 { build_real (TREE_TYPE (@0), max); }))))
+      /* x != +Inf is always equal to !(x > DBL_MAX).  */
+      (if (code == NE_EXPR)
+       (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
+       (if (! HONOR_NANS (@0))
+        (if (neg)
+         (ge @0 { build_real (TREE_TYPE (@0), max); })
+         (le @0 { build_real (TREE_TYPE (@0), max); }))
+        (if (neg)
+         (bit_xor (lt @0 { build_real (TREE_TYPE (@0), max); })
+          { build_one_cst (type); })
+         (bit_xor (gt @0 { build_real (TREE_TYPE (@0), max); })
+          { build_one_cst (type); }))))))))))
 
  /* If this is a comparison of a real constant with a PLUS_EXPR
     or a MINUS_EXPR of a real constant, we can convert it into a
@@ -1549,65 +1552,68 @@ along with GCC; see the file COPYING3.  If not see
   (for sq (SQRT)
    (simplify
     (cmp (sq @0) REAL_CST@1)
-    (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
-     /* sqrt(x) < y is always false, if y is negative.  */
-     (if (cmp == EQ_EXPR || cmp == LT_EXPR || cmp == LE_EXPR)
-      { constant_boolean_node (false, type); }
-     /* sqrt(x) > y is always true, if y is negative and we
-       don't care about NaNs, i.e. negative values of x.  */
-     (if (cmp == NE_EXPR || !HONOR_NANS (@0))
-      { constant_boolean_node (true, type); }
-     /* sqrt(x) > y is the same as x >= 0, if y is negative.  */
-     (ge @0 { build_real (TREE_TYPE (@0), dconst0); })))
-    (if (cmp == GT_EXPR || cmp == GE_EXPR)
-     (with
-      {
-               REAL_VALUE_TYPE c2;
-       REAL_ARITHMETIC (c2, MULT_EXPR, TREE_REAL_CST (@1), TREE_REAL_CST (@1));
-       real_convert (&c2, TYPE_MODE (TREE_TYPE (@0)), &c2);
-      }
-      (if (REAL_VALUE_ISINF (c2))
-       /* sqrt(x) > y is x == +Inf, when y is very large.  */
-       (if (HONOR_INFINITIES (@0))
-        (eq @0 { build_real (TREE_TYPE (@0), c2); })
+    (switch
+     (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
+      (switch
+       /* sqrt(x) < y is always false, if y is negative.  */
+       (if (cmp == EQ_EXPR || cmp == LT_EXPR || cmp == LE_EXPR)
        { constant_boolean_node (false, type); })
-       /* sqrt(x) > c is the same as x > c*c.  */
-       (cmp @0 { build_real (TREE_TYPE (@0), c2); })))
-    (if (cmp == LT_EXPR || cmp == LE_EXPR)
-     (with
-      {
-               REAL_VALUE_TYPE c2;
-       REAL_ARITHMETIC (c2, MULT_EXPR, TREE_REAL_CST (@1), TREE_REAL_CST (@1));
-       real_convert (&c2, TYPE_MODE (TREE_TYPE (@0)), &c2);
-      }
-      (if (REAL_VALUE_ISINF (c2))
-       /* sqrt(x) < y is always true, when y is a very large
-         value and we don't care about NaNs or Infinities.  */
-       (if (! HONOR_NANS (@0) && ! HONOR_INFINITIES (@0))
-        { constant_boolean_node (true, type); }
-       /* sqrt(x) < y is x != +Inf when y is very large and we
-         don't care about NaNs.  */
-       (if (! HONOR_NANS (@0))
-        (ne @0 { build_real (TREE_TYPE (@0), c2); })
-       /* sqrt(x) < y is x >= 0 when y is very large and we
-         don't care about Infinities.  */
-       (if (! HONOR_INFINITIES (@0))
-        (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
-       /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large.  */
-       (if (GENERIC)
-        (truth_andif
-        (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
-        (ne @0 { build_real (TREE_TYPE (@0), c2); }))))))
-      /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs.  */
-      (if (! REAL_VALUE_ISINF (c2)
-           && ! HONOR_NANS (@0))
-       (cmp @0 { build_real (TREE_TYPE (@0), c2); })
-      /* sqrt(x) < c is the same as x >= 0 && x < c*c.  */
-      (if (! REAL_VALUE_ISINF (c2)
-           && GENERIC)
-       (truth_andif
-        (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
-       (cmp @0 { build_real (TREE_TYPE (@0), c2); })))))))))))))
+       /* sqrt(x) > y is always true, if y is negative and we
+         don't care about NaNs, i.e. negative values of x.  */
+       (if (cmp == NE_EXPR || !HONOR_NANS (@0))
+       { constant_boolean_node (true, type); })
+       /* sqrt(x) > y is the same as x >= 0, if y is negative.  */
+       (ge @0 { build_real (TREE_TYPE (@0), dconst0); })))
+     (if (cmp == GT_EXPR || cmp == GE_EXPR)
+      (with
+       {
+         REAL_VALUE_TYPE c2;
+        REAL_ARITHMETIC (c2, MULT_EXPR,
+                         TREE_REAL_CST (@1), TREE_REAL_CST (@1));
+        real_convert (&c2, TYPE_MODE (TREE_TYPE (@0)), &c2);
+       }
+       (if (REAL_VALUE_ISINF (c2))
+       /* sqrt(x) > y is x == +Inf, when y is very large.  */
+       (if (HONOR_INFINITIES (@0))
+        (eq @0 { build_real (TREE_TYPE (@0), c2); })
+        { constant_boolean_node (false, type); })
+       /* sqrt(x) > c is the same as x > c*c.  */
+       (cmp @0 { build_real (TREE_TYPE (@0), c2); }))))
+     (if (cmp == LT_EXPR || cmp == LE_EXPR)
+      (with
+       {
+                REAL_VALUE_TYPE c2;
+        REAL_ARITHMETIC (c2, MULT_EXPR,
+                         TREE_REAL_CST (@1), TREE_REAL_CST (@1));
+        real_convert (&c2, TYPE_MODE (TREE_TYPE (@0)), &c2);
+       }
+       (if (REAL_VALUE_ISINF (c2))
+        (switch
+        /* sqrt(x) < y is always true, when y is a very large
+           value and we don't care about NaNs or Infinities.  */
+        (if (! HONOR_NANS (@0) && ! HONOR_INFINITIES (@0))
+         { constant_boolean_node (true, type); })
+        /* sqrt(x) < y is x != +Inf when y is very large and we
+           don't care about NaNs.  */
+        (if (! HONOR_NANS (@0))
+         (ne @0 { build_real (TREE_TYPE (@0), c2); }))
+        /* sqrt(x) < y is x >= 0 when y is very large and we
+           don't care about Infinities.  */
+        (if (! HONOR_INFINITIES (@0))
+         (ge @0 { build_real (TREE_TYPE (@0), dconst0); }))
+        /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large.  */
+        (if (GENERIC)
+         (truth_andif
+          (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+          (ne @0 { build_real (TREE_TYPE (@0), c2); }))))
+       /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs.  */
+       (if (! HONOR_NANS (@0))
+        (cmp @0 { build_real (TREE_TYPE (@0), c2); })
+        /* sqrt(x) < c is the same as x >= 0 && x < c*c.  */
+        (if (GENERIC)
+         (truth_andif
+          (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+          (cmp @0 { build_real (TREE_TYPE (@0), c2); }))))))))))))
 
 /* Unordered tests if either argument is a NaN.  */
 (simplify