On Tue, Oct 17, 2017 at 6:28 PM, Wilco Dijkstra <wilco.dijks...@arm.com> wrote: > This patch implements some of the optimizations discussed in > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71026. > > Simplify (C / x > 0.0) into x > 0.0. > > If C is negative the comparison is reversed. > > Simplify (x * C1) > C2 into x > (C2 / C1). > > Again, if C1 is negative the comparison is reversed. > Both transformations are only done with -funsafe-math-optimizations, > the constant is non-zero, and not a NaN. > > OK for commit? > > ChangeLog > 2017-10-17 Wilco Dijkstra <wdijk...@arm.com> > Jackson Woodruff <jackson.woodr...@arm.com> > > gcc/ > PR 71026/tree-optimization > * match.pd: Simplify floating point comparisons. > > gcc/testsuite/ > PR 71026/tree-optimization > * gcc.dg/associate_comparison_1.c: New test. > -- > diff --git a/gcc/match.pd b/gcc/match.pd > index > e58a65af59b44a6b82ed8705f62966c5e6f251ac..cb48f079b4a310272e49cc319a1b3b0ff2023ba4 > 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -352,6 +352,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (rdiv @0 (rdiv:s @1 @2)) > (mult (rdiv @0 @1) @2))) > > +(if (flag_unsafe_math_optimizations) > + /* Simplify (C / x op 0.0) to x op 0.0 for C > 0. */ > + (for op (lt le gt ge) > + neg_op (gt ge lt le) > + (simplify > + (op (rdiv REAL_CST@0 @1) real_zerop@2) > + (switch > + (if (real_less (&dconst0, TREE_REAL_CST_PTR (@0)))
Note that real_less (0., +Inf) so I think you either need to check C is 'normal' or ! HONOR_INFINITIES. There's also the underflow issue I guess this is what -funsafe-math-optimization is for. I think ignoring underflows is dangerous though. > + (op @1 @2)) > + /* For C < 0, use the inverted operator. */ > + (if (real_less (TREE_REAL_CST_PTR (@0), &dconst0)) > + (neg_op @1 @2)))))) > + > /* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ > (for div (trunc_div ceil_div floor_div round_div exact_div) > (simplify > @@ -3546,6 +3559,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (rdiv @2 @1)) > (rdiv (op @0 @2) @1))) > > + (for cmp (lt le gt ge) > + neg_cmp (gt ge lt le) > + /* Simplify (x * C1) cmp C2 -> x cmp (C2 / C1), where C1 != 0. */ > + (simplify > + (cmp (mult @0 REAL_CST@1) REAL_CST@2) > + (with > + { tree tem = const_binop (RDIV_EXPR, type, @2, @1); } > + (if (tem) > + (switch > + (if (real_less (&dconst0, TREE_REAL_CST_PTR (@1))) > + (cmp @0 { tem; })) > + (if (real_less (TREE_REAL_CST_PTR (@1), &dconst0)) > + (neg_cmp @0 { tem; }))))))) > + Drops possible overflow/underflow in x * C1 and may create underflow or overflow with C2/C1 which you should detect here at least. Existing overflows may be guarded against with a HONOR_INFINITIES check. When overflow/underflow can be disregarded is there any reason remaining to make this guarded by flag_unsafe_math_optimizations? Are there any cases where rounding issues can flip the comparison result? Richard. > /* Simplify sqrt(x) * sqrt(y) -> sqrt(x*y). */ > (for root (SQRT CBRT) > (simplify > diff --git a/gcc/testsuite/gcc.dg/associate_comparison_1.c > b/gcc/testsuite/gcc.dg/associate_comparison_1.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..d051f052e13812c91cbd2d559bf2af8fae128ee1 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/associate_comparison_1.c > @@ -0,0 +1,34 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -funsafe-math-optimizations -fdump-tree-optimized" } */ > + > +int > +cmp_mul_1 (float x) > +{ > + return x * 3 <= 100; > +} > + > +int > +cmp_mul_2 (float x) > +{ > + return x * -5 > 100; > +} > + > +int > +div_cmp_1 (float x, float y) > +{ > + return x / 3 <= y; > +} > + > +int > +div_cmp_2 (float x, float y) > +{ > + return x / 3 <= 1; > +} > + > +int > +inv_cmp (float x) > +{ > + return 5 / x >= 0; > +} > + > +/* { dg-final { scan-tree-dump-not " / " "optimized" } } */ >