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 ;-).