diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index d212e64a624..cfcb9b0a5db 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -1587,7 +1587,13 @@ public: r = range_true (type); return true; } - if (!fop_lt.fold_range (r, type, op1, op2, rel)) + frange op1_no_nan = op1; + frange op2_no_nan = op2; + if (op1.maybe_isnan ()) + op1_no_nan.clear_nan (); + if (op2.maybe_isnan ()) + op2_no_nan.clear_nan (); + if (!fop_lt.fold_range (r, type, op1_no_nan, op2_no_nan, rel)) return false; // The result is the same as the ordered version when the // comparison is true or when the operands cannot be NANs. @@ -1692,7 +1698,13 @@ public: r = range_true (type); return true; } - if (!fop_le.fold_range (r, type, op1, op2, rel)) + frange op1_no_nan = op1; + frange op2_no_nan = op2; + if (op1.maybe_isnan ()) + op1_no_nan.clear_nan (); + if (op2.maybe_isnan ()) + op2_no_nan.clear_nan (); + if (!fop_le.fold_range (r, type, op1_no_nan, op2_no_nan, rel)) return false; // The result is the same as the ordered version when the // comparison is true or when the operands cannot be NANs. @@ -1793,7 +1805,13 @@ public: r = range_true (type); return true; } - if (!fop_gt.fold_range (r, type, op1, op2, rel)) + frange op1_no_nan = op1; + frange op2_no_nan = op2; + if (op1.maybe_isnan ()) + op1_no_nan.clear_nan (); + if (op2.maybe_isnan ()) + op2_no_nan.clear_nan (); + if (!fop_gt.fold_range (r, type, op1_no_nan, op2_no_nan, rel)) return false; // The result is the same as the ordered version when the // comparison is true or when the operands cannot be NANs. @@ -1898,7 +1916,13 @@ public: r = range_true (type); return true; } - if (!fop_ge.fold_range (r, type, op1, op2, rel)) + frange op1_no_nan = op1; + frange op2_no_nan = op2; + if (op1.maybe_isnan ()) + op1_no_nan.clear_nan (); + if (op2.maybe_isnan ()) + op2_no_nan.clear_nan (); + if (!fop_ge.fold_range (r, type, op1_no_nan, op2_no_nan, rel)) return false; // The result is the same as the ordered version when the // comparison is true or when the operands cannot be NANs. @@ -2002,7 +2026,13 @@ public: r = range_true (type); return true; } - if (!fop_equal.fold_range (r, type, op1, op2, rel)) + frange op1_no_nan = op1; + frange op2_no_nan = op2; + if (op1.maybe_isnan ()) + op1_no_nan.clear_nan (); + if (op2.maybe_isnan ()) + op2_no_nan.clear_nan (); + if (!fop_equal.fold_range (r, type, op1_no_nan, op2_no_nan, rel)) return false; // The result is the same as the ordered version when the // comparison is true or when the operands cannot be NANs. diff --git a/gcc/testsuite/gcc.target/i386/pr103559-1.c b/gcc/testsuite/gcc.target/i386/pr103559-1.c new file mode 100644 index 00000000000..f43aba14853 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103559-1.c @@ -0,0 +1,13 @@ +/* PR tree-optimization/103559 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump " = .SQRT \\\(" "optimized" } } */ +/* { dg-final { scan-tree-dump " = sqrtf \\\(" "optimized" } } */ + +float sqrtf (float); + +float +foo (float x) +{ + return sqrtf (x); +} diff --git a/gcc/testsuite/gcc.target/i386/pr103559-2.c b/gcc/testsuite/gcc.target/i386/pr103559-2.c new file mode 100644 index 00000000000..304031b677c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103559-2.c @@ -0,0 +1,15 @@ +/* PR tree-optimization/103559 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump " = .SQRT \\\(" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " = sqrtf \\\(" "optimized" } } */ + +float sqrtf (float); + +float +foo (float x) +{ + if (__builtin_isless (x, 0)) + __builtin_unreachable (); + return sqrtf (x); +} diff --git a/gcc/testsuite/gcc.target/i386/pr103559-3.c b/gcc/testsuite/gcc.target/i386/pr103559-3.c new file mode 100644 index 00000000000..862990ade88 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103559-3.c @@ -0,0 +1,15 @@ +/* PR tree-optimization/103559 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not " = .SQRT \\\(" "optimized" } } */ +/* { dg-final { scan-tree-dump " = sqrtf \\\(" "optimized" } } */ + +float sqrtf (float); + +float +foo (float x) +{ + if (!__builtin_isless (x, 0)) + __builtin_unreachable (); + return sqrtf (x); +} diff --git a/gcc/testsuite/gcc.target/i386/pr103559-4.c b/gcc/testsuite/gcc.target/i386/pr103559-4.c new file mode 100644 index 00000000000..ec22b564d53 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103559-4.c @@ -0,0 +1,13 @@ +/* PR tree-optimization/103559 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not " = sqrtf \\\(" "optimized" } } */ + +float sqrtf (float); + +float +foo (float x) +{ + x = x * x; + return sqrtf (x); +} diff --git a/gcc/value-query.cc b/gcc/value-query.cc index e824d86acab..50128502102 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -230,15 +230,21 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) default: break; } - if (BINARY_CLASS_P (expr)) + if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr)) { - range_op_handler op (TREE_CODE (expr), type); + tree op0 = TREE_OPERAND (expr, 0); + tree op1 = TREE_OPERAND (expr, 1); + if (COMPARISON_CLASS_P (expr) + && !Value_Range::supports_type_p (TREE_TYPE (op0))) + return false; + range_op_handler op (TREE_CODE (expr), + BINARY_CLASS_P (expr) ? type : TREE_TYPE (op0)); if (op) { - Value_Range r0 (TREE_TYPE (TREE_OPERAND (expr, 0))); - Value_Range r1 (TREE_TYPE (TREE_OPERAND (expr, 1))); - range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); - range_of_expr (r1, TREE_OPERAND (expr, 1), stmt); + Value_Range r0 (TREE_TYPE (op0)); + Value_Range r1 (TREE_TYPE (op1)); + range_of_expr (r0, op0, stmt); + range_of_expr (r1, op1, stmt); if (!op.fold_range (r, type, r0, r1)) r.set_varying (type); }