On Mon, 15 Aug 2016, Richard Biener wrote: > > The following fixes PR76490 which happens because how VRP expects > +INF vs. +INF(OVF) to behave wrt comparisons. I fixed all > operand_equal_p cases that matter. > > Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
The following is what I applied - it adds more similar fixes and has to XFAIL gcc.dg/pr52904.c because that was only "fixed" when the bug was introduced. Boostrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2016-08-17 Richard Biener <rguent...@suse.de> PR tree-optimization/76490 * tree-vrp.c (update_value_range): Preserve overflow infinities when intersecting with ranges from get_range_info. (operand_less_p): Handle overflow infinities correctly. (value_range_constant_singleton): Use vrp_operand_equal_p to handle overflow max/min correctly. (vrp_valueize): Likewise. (union_ranges): Likewise. (intersect_ranges): Likewise. (vrp_visit_phi_node): Improve iteration limitation to only apply when we'll possibly re-visit the PHI via a changed argument on the backedge. * gfortran.fortran-torture/compile/pr76490.f90: New testcase. * gcc.dg/pr52904.c: XFAIL. Index: gcc/tree-vrp.c =================================================================== *** gcc/tree-vrp.c.orig 2016-08-17 10:30:24.164280986 +0200 --- gcc/tree-vrp.c 2016-08-17 10:59:12.416332674 +0200 *************** update_value_range (const_tree var, valu *** 775,782 **** { value_range nr; nr.type = rtype; ! nr.min = wide_int_to_tree (TREE_TYPE (var), min); ! nr.max = wide_int_to_tree (TREE_TYPE (var), max); nr.equiv = NULL; vrp_intersect_ranges (new_vr, &nr); } --- 775,794 ---- { value_range nr; nr.type = rtype; ! /* Range info on SSA names doesn't carry overflow information ! so make sure to preserve the overflow bit on the lattice. */ ! if (new_vr->type == VR_RANGE ! && is_negative_overflow_infinity (new_vr->min) ! && wi::eq_p (new_vr->min, min)) ! nr.min = new_vr->min; ! else ! nr.min = wide_int_to_tree (TREE_TYPE (var), min); ! if (new_vr->type == VR_RANGE ! && is_positive_overflow_infinity (new_vr->max) ! && wi::eq_p (new_vr->max, max)) ! nr.max = new_vr->max; ! else ! nr.max = wide_int_to_tree (TREE_TYPE (var), max); nr.equiv = NULL; vrp_intersect_ranges (new_vr, &nr); } *************** operand_less_p (tree val, tree val2) *** 1139,1145 **** { /* LT is folded faster than GE and others. Inline the common case. */ if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST) ! return tree_int_cst_lt (val, val2); else { tree tcmp; --- 1151,1160 ---- { /* LT is folded faster than GE and others. Inline the common case. */ if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST) ! { ! if (! is_positive_overflow_infinity (val2)) ! return tree_int_cst_lt (val, val2); ! } else { tree tcmp; *************** static tree *** 1423,1429 **** value_range_constant_singleton (value_range *vr) { if (vr->type == VR_RANGE ! && operand_equal_p (vr->min, vr->max, 0) && is_gimple_min_invariant (vr->min)) return vr->min; --- 1438,1444 ---- value_range_constant_singleton (value_range *vr) { if (vr->type == VR_RANGE ! && vrp_operand_equal_p (vr->min, vr->max) && is_gimple_min_invariant (vr->min)) return vr->min; *************** vrp_valueize (tree name) *** 7006,7013 **** { value_range *vr = get_value_range (name); if (vr->type == VR_RANGE ! && (vr->min == vr->max ! || operand_equal_p (vr->min, vr->max, 0))) return vr->min; } return name; --- 7021,7027 ---- { value_range *vr = get_value_range (name); if (vr->type == VR_RANGE ! && vrp_operand_equal_p (vr->min, vr->max)) return vr->min; } return name; *************** union_ranges (enum value_range_type *vr0 *** 7973,7980 **** enum value_range_type vr1type, tree vr1min, tree vr1max) { ! bool mineq = operand_equal_p (*vr0min, vr1min, 0); ! bool maxeq = operand_equal_p (*vr0max, vr1max, 0); /* [] is vr0, () is vr1 in the following classification comments. */ if (mineq && maxeq) --- 7987,7994 ---- enum value_range_type vr1type, tree vr1min, tree vr1max) { ! bool mineq = vrp_operand_equal_p (*vr0min, vr1min); ! bool maxeq = vrp_operand_equal_p (*vr0max, vr1max); /* [] is vr0, () is vr1 in the following classification comments. */ if (mineq && maxeq) *************** intersect_ranges (enum value_range_type *** 8244,8251 **** enum value_range_type vr1type, tree vr1min, tree vr1max) { ! bool mineq = operand_equal_p (*vr0min, vr1min, 0); ! bool maxeq = operand_equal_p (*vr0max, vr1max, 0); /* [] is vr0, () is vr1 in the following classification comments. */ if (mineq && maxeq) --- 8258,8265 ---- enum value_range_type vr1type, tree vr1min, tree vr1max) { ! bool mineq = vrp_operand_equal_p (*vr0min, vr1min); ! bool maxeq = vrp_operand_equal_p (*vr0max, vr1max); /* [] is vr0, () is vr1 in the following classification comments. */ if (mineq && maxeq) *************** vrp_visit_phi_node (gphi *phi) *** 8703,8709 **** print_gimple_stmt (dump_file, phi, 0, dump_flags); } ! bool may_simulate_again = false; edges = 0; for (i = 0; i < gimple_phi_num_args (phi); i++) { --- 8717,8723 ---- print_gimple_stmt (dump_file, phi, 0, dump_flags); } ! bool may_simulate_backedge_again = false; edges = 0; for (i = 0; i < gimple_phi_num_args (phi); i++) { *************** vrp_visit_phi_node (gphi *phi) *** 8729,8736 **** /* See if we are eventually going to change one of the args. */ gimple *def_stmt = SSA_NAME_DEF_STMT (arg); if (! gimple_nop_p (def_stmt) ! && prop_simulate_again_p (def_stmt)) ! may_simulate_again = true; vr_arg = *(get_value_range (arg)); /* Do not allow equivalences or symbolic ranges to leak in from --- 8743,8751 ---- /* See if we are eventually going to change one of the args. */ gimple *def_stmt = SSA_NAME_DEF_STMT (arg); if (! gimple_nop_p (def_stmt) ! && prop_simulate_again_p (def_stmt) ! && e->flags & EDGE_DFS_BACK) ! may_simulate_backedge_again = true; vr_arg = *(get_value_range (arg)); /* Do not allow equivalences or symbolic ranges to leak in from *************** vrp_visit_phi_node (gphi *phi) *** 8808,8820 **** edge; this helps us avoid an overflow infinity for conditionals which are not in a loop. If the old value-range was VR_UNDEFINED use the updated range and iterate one more time. If we will not ! simulate this PHI again with the same number of edges then iterate ! one more time. */ if (edges > 0 && gimple_phi_num_args (phi) > 1 && edges == old_edges && lhs_vr->type != VR_UNDEFINED ! && may_simulate_again) { /* Compare old and new ranges, fall back to varying if the values are not comparable. */ --- 8823,8834 ---- edge; this helps us avoid an overflow infinity for conditionals which are not in a loop. If the old value-range was VR_UNDEFINED use the updated range and iterate one more time. If we will not ! simulate this PHI again via the backedge allow us to iterate. */ if (edges > 0 && gimple_phi_num_args (phi) > 1 && edges == old_edges && lhs_vr->type != VR_UNDEFINED ! && may_simulate_backedge_again) { /* Compare old and new ranges, fall back to varying if the values are not comparable. */ Index: gcc/testsuite/gfortran.fortran-torture/compile/pr76490.f90 =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gfortran.fortran-torture/compile/pr76490.f90 2016-08-17 11:11:06.016569077 +0200 *************** *** 0 **** --- 1,23 ---- + program membug + call bug1() + end program membug + subroutine unknown(x1,y1,ibig) + write(*,*)x1,y1,ibig + end subroutine unknown + subroutine bug1() + real arrayq(3000) + isize=0 + ibig=-1 + x2=0 + 10 continue + isize=isize+1 + arrayq(isize)=x2 + 15 continue + call unknown(x1,y1,ibig) + if(ibig.eq.1)then + goto 10 + elseif(ibig.eq.2)then + isize=max(1,isize-1) + goto 15 + endif + end subroutine bug1 Index: gcc/testsuite/gcc.dg/pr52904.c =================================================================== *** gcc/testsuite/gcc.dg/pr52904.c.orig 2016-08-17 11:09:58.667791403 +0200 --- gcc/testsuite/gcc.dg/pr52904.c 2016-08-17 11:10:11.279937030 +0200 *************** wait_reading_process_output (void) *** 14,20 **** nfds++; } ! if (nfds < 0) /* { dg-bogus "assuming signed overflow does not occur" } */ return 1; return 0; } --- 14,20 ---- nfds++; } ! if (nfds < 0) /* { dg-bogus "assuming signed overflow does not occur" "" { xfail *-*-* } } */ return 1; return 0; }