The following finally fixes PR42108 (well, hopefully...) by using
range-information on SSA names to allow the integer divisions introduced
by Fortran array lowering being hoisted out of loops, thus detecting
them as not trapping.

I chose to enhance tree_single_nonzero_warnv_p for this and adjusted
operation_could_trap_helper_p to use this helper.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2014-12-09  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/42108
        * fold-const.c (tree_single_nonzero_warnv_p): Use range
        information associated with SSA names.
        * tree-eh.c (operation_could_trap_helper_p): Use
        tree_single_nonzero_warnv_p to check for trapping non-fp
        operation.
        * tree-vrp.c (remove_range_assertions): Remove bogus assert.

        * gfortran.dg/pr42108.f90: Adjust testcase.

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c    (revision 218479)
+++ gcc/fold-const.c    (working copy)
@@ -83,6 +83,8 @@ along with GCC; see the file COPYING3.
 #include "cgraph.h"
 #include "generic-match.h"
 #include "optabs.h"
+#include "stringpool.h"
+#include "tree-ssanames.h"
 
 /* Nonzero if we are folding constants inside an initializer; zero
    otherwise.  */
@@ -15362,6 +15381,26 @@ tree_single_nonzero_warnv_p (tree t, boo
        }
       break;
 
+    case SSA_NAME:
+      if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
+       {
+         wide_int minv, maxv;
+         enum value_range_type rtype = get_range_info (t, &minv, &maxv);
+         if (rtype == VR_RANGE)
+           {
+             if (wi::lt_p (maxv, 0, TYPE_SIGN (TREE_TYPE (t)))
+                 || wi::gt_p (minv, 0, TYPE_SIGN (TREE_TYPE (t))))
+               return true;
+           }
+         else if (rtype == VR_ANTI_RANGE)
+           {
+             if (wi::le_p (minv, 0, TYPE_SIGN (TREE_TYPE (t)))
+                 && wi::ge_p (maxv, 0, TYPE_SIGN (TREE_TYPE (t))))
+               return true;
+           }
+       }
+      break;
+
     default:
       break;
     }
Index: gcc/tree-eh.c
===================================================================
--- gcc/tree-eh.c       (revision 218479)
+++ gcc/tree-eh.c       (working copy)
@@ -2440,13 +2440,16 @@ operation_could_trap_helper_p (enum tree
     case ROUND_MOD_EXPR:
     case TRUNC_MOD_EXPR:
     case RDIV_EXPR:
-      if (honor_snans || honor_trapv)
-       return true;
-      if (fp_operation)
-       return flag_trapping_math;
-      if (!TREE_CONSTANT (divisor) || integer_zerop (divisor))
-        return true;
-      return false;
+      {
+       if (honor_snans || honor_trapv)
+         return true;
+       if (fp_operation)
+         return flag_trapping_math;
+       bool sop;
+       if (!tree_single_nonzero_warnv_p (divisor, &sop))
+         return true;
+       return false;
+      }
 
     case LT_EXPR:
     case LE_EXPR:
Index: gcc/testsuite/gfortran.dg/pr42108.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pr42108.f90       (revision 218479)
+++ gcc/testsuite/gfortran.dg/pr42108.f90       (working copy)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-O2 -fdump-tree-fre1" }
+! { dg-options "-O2 -fdump-tree-fre1 -fdump-tree-lim1-details" }
 
 subroutine  eval(foo1,foo2,foo3,foo4,x,n,nnd)
   implicit real*8 (a-h,o-z)
@@ -21,7 +21,10 @@ subroutine  eval(foo1,foo2,foo3,foo4,x,n
   end do
 end subroutine eval
 
-! There should be only one load from n left
+! There should be only one load from n left and the division should
+! be hoisted out of the loop
 
 ! { dg-final { scan-tree-dump-times "\\*n_" 1 "fre1" } }
+! { dg-final { scan-tree-dump-times "Moving statement" 5 "lim1" } }
 ! { dg-final { cleanup-tree-dump "fre1" } }
+! { dg-final { cleanup-tree-dump "lim1" } }
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c      (revision 218479)
+++ gcc/tree-vrp.c      (working copy)
@@ -6866,12 +6866,9 @@ remove_range_assertions (void)
            tree lhs = gimple_assign_lhs (stmt);
            tree rhs = gimple_assign_rhs1 (stmt);
            tree var;
-           tree cond = fold (ASSERT_EXPR_COND (rhs));
            use_operand_p use_p;
            imm_use_iterator iter;
 
-           gcc_assert (cond != boolean_false_node);
-
            var = ASSERT_EXPR_VAR (rhs);
            gcc_assert (TREE_CODE (var) == SSA_NAME);
 

Reply via email to