The problem in the testcase was that tree-complex.c was trying
to fold ABS_EXPRs of SSA names that didn't yet have a definition
(because the SSA names were real and imaginary parts of a complex
SSA name whose definition hadn't yet been visited by the pass).
tree-complex.c uses a straightforward walk in index order:

  /* ??? Ideally we'd traverse the blocks in breadth-first order.  */
  old_last_basic_block = last_basic_block_for_fn (cfun);
  FOR_EACH_BB_FN (bb, cfun)
    {

and in the testcase, we have a block A with a single successor B that
comes before it.  B has no other predecessor and has a complex division
that uses an SSA name X defined in A, so we split the components of X
before we reach the definition of X.  (I imagine cfgcleanup would
clean this up by joining A and B.)

Tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard


gcc/
        PR tree-optimization/68146
        * fold-const.c (tree_binary_nonnegative_warnv_p): Check for null
        SSA_NAME_DEF_STMTs.
        (integer_valued_real_call_p): Likewise.

gcc/testsuite/
        * gfortran.fortran-torture/compile/pr68146.f90: New test.

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 16bff5f..c99e78e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -12867,6 +12867,8 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, 
tree type, tree op0,
 bool
 tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p, int depth)
 {
+  gimple *stmt;
+
   if (TYPE_UNSIGNED (TREE_TYPE (t)))
     return true;
 
@@ -12892,8 +12894,9 @@ tree_single_nonnegative_warnv_p (tree t, bool 
*strict_overflow_p, int depth)
         to provide it through dataflow propagation.  */
       return (!name_registered_for_update_p (t)
              && depth < PARAM_VALUE (PARAM_MAX_SSA_NAME_QUERY_DEPTH)
-             && gimple_stmt_nonnegative_warnv_p (SSA_NAME_DEF_STMT (t),
-                                                 strict_overflow_p, depth));
+             && (stmt = SSA_NAME_DEF_STMT (t))
+             && gimple_stmt_nonnegative_warnv_p (stmt, strict_overflow_p,
+                                                 depth));
 
     default:
       return tree_simple_nonnegative_warnv_p (TREE_CODE (t), TREE_TYPE (t));
@@ -13508,6 +13511,7 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, 
tree arg1, int depth)
 bool
 integer_valued_real_single_p (tree t, int depth)
 {
+  gimple *stmt;
   switch (TREE_CODE (t))
     {
     case REAL_CST:
@@ -13524,8 +13528,8 @@ integer_valued_real_single_p (tree t, int depth)
         to provide it through dataflow propagation.  */
       return (!name_registered_for_update_p (t)
              && depth < PARAM_VALUE (PARAM_MAX_SSA_NAME_QUERY_DEPTH)
-             && gimple_stmt_integer_valued_real_p (SSA_NAME_DEF_STMT (t),
-                                                   depth));
+             && (stmt = SSA_NAME_DEF_STMT (t))
+             && gimple_stmt_integer_valued_real_p (stmt, depth));
 
     default:
       break;
diff --git a/gcc/testsuite/gfortran.fortran-torture/compile/pr68146.f90 
b/gcc/testsuite/gfortran.fortran-torture/compile/pr68146.f90
new file mode 100644
index 0000000..7f75ec0
--- /dev/null
+++ b/gcc/testsuite/gfortran.fortran-torture/compile/pr68146.f90
@@ -0,0 +1,11 @@
+subroutine foo(a1, a2, s1, s2, n)
+  integer :: n
+  complex(kind=8) :: a1(n), a2(n), s1, s2
+  do i = 1, n
+     a1(i) = i
+  end do
+  s1 = 20.0 / s2
+  do i = 1, n
+     a2(i) = i / s2
+  end do
+end subroutine foo

Reply via email to