range-op-float: Fix up ICE in lower_bound [PR107975]

Message ID Y446AHZfl9DZFrdx@tucnak
State Unresolved
Headers
Series range-op-float: Fix up ICE in lower_bound [PR107975] |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Jakub Jelinek Dec. 5, 2022, 6:35 p.m. UTC
  Hi!

According to https://gcc.gnu.org/pipermail/gcc-regression/2022-December/077258.html
my patch caused some ICEs, e.g. the following testcase ICEs.
The problem is that lower_bound and upper_bound methods on a france assert
that the range isn't VR_NAN or VR_UNDEFINED.
All the op1_range/op2_range methods already return early if lhs.undefined_p,
but the other cases (when lhs is VR_NAN or the other opN is VR_NAN or
VR_UNDEFINED) aren't.  float_binary_op_range_finish will DTRT for those
cases already.

Ok for trunk if this passes bootstrap/regtest?

2022-12-05  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/107975
	* range-op-float.cc (foperator_mult::op1_range,
	foperator_div::op1_range, foperator_div::op2_range): Just
	return float_binary_op_range_finish result if lhs is known
	NAN, or the other operand is known NAN or UNDEFINED.

	* gcc.dg/pr107975.c: New test.


	Jakub
  

Comments

Richard Biener Dec. 6, 2022, 7:17 a.m. UTC | #1
On Mon, 5 Dec 2022, Jakub Jelinek wrote:

> Hi!
> 
> According to https://gcc.gnu.org/pipermail/gcc-regression/2022-December/077258.html
> my patch caused some ICEs, e.g. the following testcase ICEs.
> The problem is that lower_bound and upper_bound methods on a france assert
> that the range isn't VR_NAN or VR_UNDEFINED.
> All the op1_range/op2_range methods already return early if lhs.undefined_p,
> but the other cases (when lhs is VR_NAN or the other opN is VR_NAN or
> VR_UNDEFINED) aren't.  float_binary_op_range_finish will DTRT for those
> cases already.
> 
> Ok for trunk if this passes bootstrap/regtest?

OK.

Richard.

> 2022-12-05  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/107975
> 	* range-op-float.cc (foperator_mult::op1_range,
> 	foperator_div::op1_range, foperator_div::op2_range): Just
> 	return float_binary_op_range_finish result if lhs is known
> 	NAN, or the other operand is known NAN or UNDEFINED.
> 
> 	* gcc.dg/pr107975.c: New test.
> 
> --- gcc/range-op-float.cc.jj	2022-12-05 11:17:34.900573272 +0100
> +++ gcc/range-op-float.cc	2022-12-05 17:58:38.059754128 +0100
> @@ -2146,6 +2146,8 @@ public:
>      bool ret = rdiv.fold_range (r, type, lhs, op2);
>      if (ret == false)
>        return false;
> +    if (lhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
> +      return float_binary_op_range_finish (ret, r, type, lhs);
>      const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound ();
>      const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound ();
>      const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
> @@ -2296,6 +2298,8 @@ public:
>      bool ret = fop_mult.fold_range (r, type, lhs, op2);
>      if (!ret)
>        return ret;
> +    if (lhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
> +      return float_binary_op_range_finish (ret, r, type, lhs);
>      const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound ();
>      const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound ();
>      const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
> @@ -2325,6 +2329,8 @@ public:
>      bool ret = fold_range (r, type, op1, lhs);
>      if (!ret)
>        return ret;
> +    if (lhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
> +      return float_binary_op_range_finish (ret, r, type, lhs);
>      const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound ();
>      const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound ();
>      const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
> --- gcc/testsuite/gcc.dg/pr107975.c.jj	2022-12-05 19:15:56.518851401 +0100
> +++ gcc/testsuite/gcc.dg/pr107975.c	2022-12-05 19:15:04.014620281 +0100
> @@ -0,0 +1,15 @@
> +/* PR tree-optimization/107975 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +/* { dg-add-options ieee } */
> +
> +double
> +foo (double x, double y)
> +{
> +  if (x == 42.0)
> +    return 1.0;
> +  double r = x * y;
> +  if (!__builtin_isnan (r))
> +    __builtin_unreachable ();
> +  return r;
> +}
> 
> 	Jakub
> 
>
  
Toon Moene Dec. 6, 2022, 7:04 p.m. UTC | #2
On 12/5/22 19:35, Jakub Jelinek via Gcc-patches wrote:

> Hi!
> 
> According to https://gcc.gnu.org/pipermail/gcc-regression/2022-December/077258.html

Seen in the wild too - compiling one of the two weather forecasting 
programs I use:

during GIMPLE pass: dom
/home/toon/scratch/hm_home/my_CY46h1/lib/src/surfex/ASSIM/assim_nature_isba_ekf.F90:5:32:

     5 | SUBROUTINE ASSIM_NATURE_ISBA_EKF (KMYPROC, IO, S, K, NP, NPE, 
HPROGRAM, KI, PT2M, PHU2M, HTEST)
       |                                ^
internal compiler error: in lower_bound, at value-range.h:350
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/OFFLIN/open_close_bin_asc_forc.F90.o
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/OFFLIN/open_filein_ol.F90.o
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/OFFLIN/sfx_oasis_def_ol.F90.o
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/SURFEX/abor1_sfx.F90.o
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/SURFEX/albedo.F90.o
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/SURFEX/allocate_physio.F90.o
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/SURFEX/allocate_teb_veg.F90.o
0x7db1c4 frange::lower_bound() const [clone .part.0] [clone .lto_priv.0] 
[clone .lto_priv.0]
         /home/toon/compilers/gcc/gcc/value-range.h:350
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/SURFEX/allocate_teb_veg_pgd.F90.o
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/SURFEX/average2_cover.F90.o
0x83f204 frange::lower_bound() const
         /home/toon/compilers/gcc/gcc/value-range.h:1127
0x83f204 foperator_mult::op1_range(frange&, tree_node*, frange const&, 
frange const&, relation_trio) const
         /home/toon/compilers/gcc/gcc/range-op-float.cc:2149
[ 72%] Building Fortran object 
surfex/CMakeFiles/surfex-core-static.dir/SURFEX/average2_mesh.F90.o
0x1ab62f8 gori_compute::compute_operand1_range(vrange&, 
gimple_range_op_handler&, vrange const&, tree_node*, fur_source&, 
value_relation*)
         /home/toon/compilers/gcc/gcc/gimple-range-gori.cc:1095
0x1ab4f93 gori_compute::compute_operand_range(vrange&, gimple*, vrange 
const&, tree_node*, fur_source&, value_relation*)
         /home/toon/compilers/gcc/gcc/gimple-range-gori.cc:692
0x1ab6378 gori_compute::compute_operand1_range(vrange&, 
gimple_range_op_handler&, vrange const&, tree_node*, fur_source&, 
value_relation*)
         /home/toon/compilers/gcc/gcc/gimple-range-gori.cc:1150
0x1ab4f93 gori_compute::compute_operand_range(vrange&, gimple*, vrange 
const&, tree_node*, fur_source&, value_relation*)
         /home/toon/compilers/gcc/gcc/gimple-range-gori.cc:692
0x1ac5861 gori_compute::outgoing_edge_range_p(vrange&, edge_def*, 
tree_node*, range_query&)
         /home/toon/compilers/gcc/gcc/gimple-range-gori.cc:1373
0x1ac668e ranger_cache::edge_range(vrange&, edge_def*, tree_node*, 
ranger_cache::rfd_mode)
         /home/toon/compilers/gcc/gcc/gimple-range-cache.cc:964
0x1acef14 gimple_ranger::range_on_edge(vrange&, edge_def*, tree_node*)
         /home/toon/compilers/gcc/gcc/gimple-range.cc:241
0x1ab9902 fold_using_range::range_of_phi(vrange&, gphi*, fur_source&)
         /home/toon/compilers/gcc/gcc/gimple-range-fold.cc:759
0x1ac5240 fold_using_range::fold_stmt(vrange&, gimple*, fur_source&, 
tree_node*)
         /home/toon/compilers/gcc/gcc/gimple-range-fold.cc:491
0x1ac813e gimple_ranger::fold_range_internal(vrange&, gimple*, tree_node*)
         /home/toon/compilers/gcc/gcc/gimple-range.cc:257
0x1ac813e gimple_ranger::prefill_stmt_dependencies(tree_node*)
         /home/toon/compilers/gcc/gcc/gimple-range.cc:392
0x1ac88ba gimple_ranger::range_of_stmt(vrange&, gimple*, tree_node*)
         /home/toon/compilers/gcc/gcc/gimple-range.cc:314
0x1ace076 gimple_ranger::range_on_entry(vrange&, basic_block_def*, 
tree_node*)
         /home/toon/compilers/gcc/gcc/gimple-range.cc:153
0x115d524 path_range_query::internal_range_of_expr(vrange&, tree_node*, 
gimple*)
         /home/toon/compilers/gcc/gcc/gimple-range-path.cc:176
0x115d6b0 path_range_query::range_of_expr(vrange&, tree_node*, gimple*)
         /home/toon/compilers/gcc/gcc/gimple-range-path.cc:202
0x1ac3f4a fold_using_range::range_of_range_op(vrange&, 
gimple_range_op_handler&, fur_source&)
         /home/toon/compilers/gcc/gcc/gimple-range-fold.cc:558
0x1ac50ba fold_using_range::fold_stmt(vrange&, gimple*, fur_source&, 
tree_node*)
         /home/toon/compilers/gcc/gcc/gimple-range-fold.cc:489
Please submit a full bug report, with preprocessed source (by using 
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
  

Patch

--- gcc/range-op-float.cc.jj	2022-12-05 11:17:34.900573272 +0100
+++ gcc/range-op-float.cc	2022-12-05 17:58:38.059754128 +0100
@@ -2146,6 +2146,8 @@  public:
     bool ret = rdiv.fold_range (r, type, lhs, op2);
     if (ret == false)
       return false;
+    if (lhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
+      return float_binary_op_range_finish (ret, r, type, lhs);
     const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound ();
     const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound ();
     const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
@@ -2296,6 +2298,8 @@  public:
     bool ret = fop_mult.fold_range (r, type, lhs, op2);
     if (!ret)
       return ret;
+    if (lhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
+      return float_binary_op_range_finish (ret, r, type, lhs);
     const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound ();
     const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound ();
     const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
@@ -2325,6 +2329,8 @@  public:
     bool ret = fold_range (r, type, op1, lhs);
     if (!ret)
       return ret;
+    if (lhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
+      return float_binary_op_range_finish (ret, r, type, lhs);
     const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound ();
     const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound ();
     const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
--- gcc/testsuite/gcc.dg/pr107975.c.jj	2022-12-05 19:15:56.518851401 +0100
+++ gcc/testsuite/gcc.dg/pr107975.c	2022-12-05 19:15:04.014620281 +0100
@@ -0,0 +1,15 @@ 
+/* PR tree-optimization/107975 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-add-options ieee } */
+
+double
+foo (double x, double y)
+{
+  if (x == 42.0)
+    return 1.0;
+  double r = x * y;
+  if (!__builtin_isnan (r))
+    __builtin_unreachable ();
+  return r;
+}