diff --git a/gcc/match.pd b/gcc/match.pd index e98db52af84946cf579c6434e06d450713a47162..7abfd11601a956ecb59c945256c9f30dc0b6f6c9 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -342,16 +342,42 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (negate @0))) (if (flag_reciprocal_math) - /* Convert (A/B)/C to A/(B*C) */ + /* Convert (A/B)/C to A/(B*C) where B is not a constant. */ (simplify (rdiv (rdiv:s @0 @1) @2) - (rdiv @0 (mult @1 @2))) + (if (TREE_CODE (@1) != REAL_CST) + (rdiv @0 (mult @1 @2)))) + + /* Simplify x / (C * y) to (x / C) / y where C is a constant. */ + (simplify + (rdiv @0 + (mult @1 REAL_CST@2)) + (rdiv (rdiv @0 @2) @1)) /* Convert A/(B/C) to (A/B)*C */ (simplify (rdiv @0 (rdiv:s @1 @2)) (mult (rdiv @0 @1) @2))) +(if (!flag_trapping_math) + /* Simplify x / (- y) to -x / y. */ + (simplify + (rdiv @0 (negate @1)) + (rdiv (negate @0) @1))) + +(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_equal (TREE_REAL_CST_PTR (@0), &dconst0) + && !REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0))) + (op @1 @2)) + (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0))) + (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 @@ -3446,6 +3472,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (!HONOR_SNANS (type)) @0)) + /* Simplify (x * C1) cmp C2 -> x cmp C2 / C1 + and simplify (x / C1) cmp C2 -> x cmp C2 * C1. */ + (for cmp (lt le gt ge) + neg_cmp (gt ge lt le) + (for op (mult rdiv) + inv_op (rdiv mult) + (simplify + (cmp (op @0 REAL_CST@1) REAL_CST@2) + (switch + (if (!real_equal (TREE_REAL_CST_PTR (@1), &dconst0) + && !REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1))) + (cmp @0 (inv_op @2 @1))) + (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1))) + (neg_cmp @0 (inv_op @2 @1))))))) + /* 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..c12e5cfb2a8388068fa1731cc2305f9fe5139fd6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/associate_comparison_1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-funsafe-math-optimizations -fdump-tree-optimized" } */ + +int +lt_cmp (float x, float y) +{ + return x / 2 <= 0; +} + +int +inv_cmp (float x, float y) +{ + return 5 / x >= 0; +} + + +/* { dg-final { scan-tree-dump-not " / " "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/associate_division_2.c b/gcc/testsuite/gcc.dg/associate_division_2.c new file mode 100644 index 0000000000000000000000000000000000000000..1f9c1741ce980f1148016e37399134aa8a619b1d --- /dev/null +++ b/gcc/testsuite/gcc.dg/associate_division_2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast -fdump-tree-optimized" } */ + +float +neg_mov (float w, float x, float *y, float *z) +{ + *z = x / (- w); + *y = 3 / w; + + return 5 / w; +} + +/* { dg-final { scan-tree-dump-times " / " 1 "optimized" } } */