https://gcc.gnu.org/bugzilla/show_bug.cgi?id=24021
Aldy Hernandez <aldyh at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Assignee|unassigned at gcc dot gnu.org |aldyh at gcc dot gnu.org CC| |sayle at gcc dot gnu.org --- Comment #20 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- (In reply to Andrew Macleod from comment #19) > We can use the original testcase as the litmus test for basic support if we > compile it with > > -O2 -fno-tree-fre -fno-tree-dominator-opts > > The unroller will unroll the loop and the VRP2 pass will be presented with: > > <bb 2> [local count: 97603129]: > i_1 = 1.1000000149011611438876201418679556809365749359130859375e-1; > i_17 = i_1 + 1.00000001490116119384765625e-1; > i_22 = i_17 + 1.00000001490116119384765625e-1; > i_27 = i_22 + 1.00000001490116119384765625e-1; > i_32 = i_27 + 1.00000001490116119384765625e-1; > i_37 = i_32 + 1.00000001490116119384765625e-1; > i_42 = i_37 + 1.00000001490116119384765625e-1; > i_47 = i_42 + 1.00000001490116119384765625e-1; > i_52 = i_47 + 1.00000001490116119384765625e-1; > if (i_52 == 0.0) > goto <bb 4>; [50.00%] > else > goto <bb 3>; [50.00%] > > <bb 3> [local count: 48801565]: > > <bb 4> [local count: 97603129]: > # lastPoint_12 = PHI <i_52(2), 2.0e+0(3)> > return lastPoint_12; > > Which is we can track floating point ranges in VRP and simplification, > recognize that i_52 != 0.0 and VRP2 should be able to resolve this to > > return 2.0e+0; We can definitely get this with the current work. All that's missing is the snippet implementing the PLUS_EXPR operator. A simple implementation (with likely the NAN bits wrong :)) follows: diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index d1c7a3b571b..cba7166ad2b 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -1055,6 +1055,54 @@ foperator_mult::fold_range (frange &r, tree type, return true; } +class foperator_plus : public range_operator +{ + using range_operator::fold_range; +public: + virtual bool fold_range (frange &r, tree type, + const frange &lh, + const frange &rh, + relation_kind rel = VREL_NONE) const override; +} fop_plus; + +bool +foperator_plus::fold_range (frange &r, tree type, + const frange &lh, + const frange &rh, + relation_kind) const +{ + if (empty_range_varying (r, type, lh, rh)) + return true; + + if (lh.get_prop (FRANGE_PROP_NAN) + || rh.get_prop (FRANGE_PROP_NAN)) + { + r.set_varying (type); + return true; + } + + enum tree_code code_lb, code_ub; + tree lh_lb = lh.lower_bound (&code_lb); + tree lh_ub = lh.upper_bound (&code_ub); + tree rh_lb = rh.lower_bound (); + tree rh_ub = rh.upper_bound (); + + REAL_VALUE_TYPE res_lb, res_ub; + real_arithmetic (&res_lb, PLUS_EXPR, + TREE_REAL_CST_PTR (lh_lb), + TREE_REAL_CST_PTR (rh_lb)); + real_arithmetic (&res_ub, PLUS_EXPR, + TREE_REAL_CST_PTR (lh_ub), + TREE_REAL_CST_PTR (rh_ub)); + + r.set (code_lb, + build_real (type, res_lb), + build_real (type, res_ub), + code_ub); + return true; +} + + class floating_table : public range_op_table { public: @@ -1081,6 +1129,7 @@ floating_table::floating_table () set (UNORDERED_EXPR, fop_unordered); set (ORDERED_EXPR, fop_ordered); set (MULT_EXPR, fop_mult); + set (PLUS_EXPR, fop_plus); } #if CHECKING_P And voila... ./cc1 a.c -quiet -I/tmp -O2 -fno-tree-fre -fno-tree-dominator-opts -fno-thread-jumps -fdump-tree-vrp2-details=/dev/stdout Folding statement: i_1 = 1.1000000149011611438876201418679556809365749359130859375e-1; Queued stmt for removal. Folds to: 1.1000000149011611438876201418679556809365749359130859375e-1 Folding statement: i_17 = i_1 + 1.00000001490116119384765625e-1; Queued stmt for removal. Folds to: 2.1000000298023223377352763918679556809365749359130859375e-1 ... ... ... double BG_SplineLength () { double i; double lastPoint; <bb 2> [local count: 97603129]: return 2.0e+0; } Notice the -fno-thread-jumps, because otherwise the now floating point aware threader will thread the conditional before VRP2 gets a chance to see it. I should probably take this PR ;-).