@@ -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
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */