Commit 64d3a1f0 by Richard Biener Committed by Richard Biener

genmatch.c (parser::peek, [...]): Add argument to tell how many tokens to peek ahead (default 1).

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.

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