aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c22
-rw-r--r--gcc/match.pd10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr87287.c34
5 files changed, 55 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6314c60..7ce34fa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2018-09-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/87287
+ * fold-const.c (fold_binary_loc) <case EQ_EXPR>: Move signed modulo
+ X % C == 0 to X % (unsigned) C == 0 optimization to ...
+ * match.pd (X % C == 0): ... here. New optimization.
+
2018-09-12 Jakub Jelinek <jakub@redhat.com>
PR middle-end/82853
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3bcf272..71c18eb 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -10661,28 +10661,6 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
}
}
- /* If this is an NE or EQ comparison of zero against the result of a
- signed MOD operation whose second operand is a power of 2, make
- the MOD operation unsigned since it is simpler and equivalent. */
- if (integer_zerop (arg1)
- && !TYPE_UNSIGNED (TREE_TYPE (arg0))
- && (TREE_CODE (arg0) == TRUNC_MOD_EXPR
- || TREE_CODE (arg0) == CEIL_MOD_EXPR
- || TREE_CODE (arg0) == FLOOR_MOD_EXPR
- || TREE_CODE (arg0) == ROUND_MOD_EXPR)
- && integer_pow2p (TREE_OPERAND (arg0, 1)))
- {
- tree newtype = unsigned_type_for (TREE_TYPE (arg0));
- tree newmod = fold_build2_loc (loc, TREE_CODE (arg0), newtype,
- fold_convert_loc (loc, newtype,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, newtype,
- TREE_OPERAND (arg0, 1)));
-
- return fold_build2_loc (loc, code, type, newmod,
- fold_convert_loc (loc, newtype, arg1));
- }
-
/* Fold ((X >> C1) & C2) == 0 and ((X >> C1) & C2) != 0 where
C1 is a valid shift constant, and C2 is a power of two, i.e.
a single bit. */
diff --git a/gcc/match.pd b/gcc/match.pd
index be669ca..6d54dcb 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -470,7 +470,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& TYPE_OVERFLOW_UNDEFINED (type)
&& wi::multiple_of_p (wi::to_wide (@1), wi::to_wide (@2),
TYPE_SIGN (type)))
- { build_zero_cst (type); })))
+ { build_zero_cst (type); }))
+ /* For (X % C) == 0, if X is signed and C is power of 2, use unsigned
+ modulo and comparison, since it is simpler and equivalent. */
+ (for cmp (eq ne)
+ (simplify
+ (cmp (mod @0 integer_pow2p@2) integer_zerop@1)
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (cmp (mod (convert:utype @0) (convert:utype @2)) (convert:utype @1)))))))
/* X % -C is the same as X % C. */
(simplify
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5a50c80..2102f5a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-09-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/87287
+ * gcc.dg/tree-ssa/pr87287.c: New test.
+
2018-09-12 David Malcolm <dmalcolm@redhat.com>
PR c++/85110
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr87287.c b/gcc/testsuite/gcc.dg/tree-ssa/pr87287.c
new file mode 100644
index 0000000..cba4f43
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr87287.c
@@ -0,0 +1,34 @@
+/* PR tree-optimization/87287 */
+/* { dg-options "-O2 -fdump-tree-cddce1" } */
+/* { dg-final { scan-tree-dump-not " % 16" "cddce1" } } */
+/* { dg-final { scan-tree-dump-times " & 15" 4 "cddce1" } } */
+
+void f0 (void);
+
+int
+f1 (int x)
+{
+ return x % 16 == 0;
+}
+
+int
+f2 (int x)
+{
+ int y = x % 16;
+ return y != 0;
+}
+
+void
+f3 (int x)
+{
+ if (x % 16 != 0)
+ f0 ();
+}
+
+void
+f4 (int x)
+{
+ int y = x % 16;
+ if (y == 0)
+ f0 ();
+}