summaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/match.pd')
-rw-r--r--gcc/match.pd30
1 files changed, 30 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index f97a99888ca..36270d0b108 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2351,6 +2351,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(ge @0 { build_real (TREE_TYPE (@0), dconst0); })
(cmp @0 { build_real (TREE_TYPE (@0), c2); }))))))))))))
+/* Fold A /[ex] B CMP C to A CMP B * C. */
+(for cmp (eq ne)
+ (simplify
+ (cmp (exact_div @0 @1) INTEGER_CST@2)
+ (if (!integer_zerop (@1))
+ (if (wi::eq_p (@2, 0))
+ (cmp @0 @2)
+ (if (TREE_CODE (@1) == INTEGER_CST)
+ (with
+ {
+ bool ovf;
+ wide_int prod = wi::mul (@2, @1, TYPE_SIGN (TREE_TYPE (@1)), &ovf);
+ }
+ (if (ovf)
+ { constant_boolean_node (cmp == NE_EXPR, type); }
+ (cmp @0 { wide_int_to_tree (TREE_TYPE (@0), prod); }))))))))
+(for cmp (lt le gt ge)
+ (simplify
+ (cmp (exact_div @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (wi::gt_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1))))
+ (with
+ {
+ bool ovf;
+ wide_int prod = wi::mul (@2, @1, TYPE_SIGN (TREE_TYPE (@1)), &ovf);
+ }
+ (if (ovf)
+ { constant_boolean_node (wi::lt_p (@2, 0, TYPE_SIGN (TREE_TYPE (@2)))
+ != (cmp == LT_EXPR || cmp == LE_EXPR), type); }
+ (cmp @0 { wide_int_to_tree (TREE_TYPE (@0), prod); }))))))
+
/* Unordered tests if either argument is a NaN. */
(simplify
(bit_ior (unordered @0 @0) (unordered @1 @1))