aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/generic-match-head.c9
-rw-r--r--gcc/gimple-match-head.c24
-rw-r--r--gcc/match.pd14
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr85726-1.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr85726-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr85726-3.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr85726-4.c15
9 files changed, 117 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b60efcf..a40d99e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2018-12-06 Jakub Jelinek <jakub@redhat.com>
+ PR tree-optimization/85726
+ * generic-match-head.c (optimize_successive_divisions_p): New function.
+ * gimple-match-head.c (optimize_successive_divisions_p): Likewise.
+ * match.pd: Don't combine successive divisions if they aren't exact
+ and optimize_successive_divisions_p is false.
+
PR fortran/88304
* tree-nested.c (convert_nonlocal_reference_stmt): Remove clobbers
for non-local automatic decls.
diff --git a/gcc/generic-match-head.c b/gcc/generic-match-head.c
index f7b6b1f..0165bd0 100644
--- a/gcc/generic-match-head.c
+++ b/gcc/generic-match-head.c
@@ -77,3 +77,12 @@ canonicalize_math_after_vectorization_p ()
{
return false;
}
+
+/* Return true if successive divisions can be optimized.
+ Defer to GIMPLE opts. */
+
+static inline bool
+optimize_successive_divisions_p (tree, tree)
+{
+ return false;
+}
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index d6c60ab..374232b 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -1163,3 +1163,27 @@ optimize_pow_to_exp (tree arg0, tree arg1)
return false;
return true;
}
+
+/* Return true if a division INNER_DIV / DIVISOR where INNER_DIV
+ is another division can be optimized. Don't optimize if INNER_DIV
+ is used in a TRUNC_MOD_EXPR with DIVISOR as second operand. */
+
+static bool
+optimize_successive_divisions_p (tree divisor, tree inner_div)
+{
+ if (!gimple_in_ssa_p (cfun))
+ return false;
+
+ imm_use_iterator imm_iter;
+ use_operand_p use_p;
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, inner_div)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (!is_gimple_assign (use_stmt)
+ || gimple_assign_rhs_code (use_stmt) != TRUNC_MOD_EXPR
+ || !operand_equal_p (gimple_assign_rhs2 (use_stmt), divisor, 0))
+ continue;
+ return false;
+ }
+ return true;
+}
diff --git a/gcc/match.pd b/gcc/match.pd
index 698d27f..fbb4d6fa 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -312,17 +312,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
and floor_div is trickier and combining round_div even more so. */
(for div (trunc_div exact_div)
(simplify
- (div (div @0 INTEGER_CST@1) INTEGER_CST@2)
+ (div (div@3 @0 INTEGER_CST@1) INTEGER_CST@2)
(with {
wi::overflow_type overflow;
wide_int mul = wi::mul (wi::to_wide (@1), wi::to_wide (@2),
TYPE_SIGN (type), &overflow);
}
- (if (!overflow)
- (div @0 { wide_int_to_tree (type, mul); })
- (if (TYPE_UNSIGNED (type)
- || mul != wi::min_value (TYPE_PRECISION (type), SIGNED))
- { build_zero_cst (type); })))))
+ (if (div == EXACT_DIV_EXPR
+ || optimize_successive_divisions_p (@2, @3))
+ (if (!overflow)
+ (div @0 { wide_int_to_tree (type, mul); })
+ (if (TYPE_UNSIGNED (type)
+ || mul != wi::min_value (TYPE_PRECISION (type), SIGNED))
+ { build_zero_cst (type); }))))))
/* Combine successive multiplications. Similar to above, but handling
overflow is different. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bc5bf67..13d2e25 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2018-12-06 Jakub Jelinek <jakub@redhat.com>
+ PR tree-optimization/85726
+ * gcc.dg/tree-ssa/pr85726-1.c: New test.
+ * gcc.dg/tree-ssa/pr85726-2.c: New test.
+ * gcc.dg/tree-ssa/pr85726-3.c: New test.
+ * gcc.dg/tree-ssa/pr85726-4.c: New test.
+
PR fortran/88304
* gfortran.fortran-torture/compile/pr88304.f90: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr85726-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr85726-1.c
new file mode 100644
index 0000000..25c3e49
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr85726-1.c
@@ -0,0 +1,19 @@
+/* PR tree-optimization/85726 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " / 16;" "optimized" } } */
+/* { dg-final { scan-tree-dump " / 3;" "optimized" } } */
+/* { dg-final { scan-tree-dump " % 3;" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " / 48;" "optimized" } } */
+
+int ww, vv;
+
+int
+foo (int y)
+{
+ int z = y / 16;
+ int w = z / 3;
+ int v = z % 3;
+ ww = w;
+ return v;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr85726-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr85726-2.c
new file mode 100644
index 0000000..834a689
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr85726-2.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/85726 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " / 3145728;" "optimized" } } */
+/* { dg-final { scan-tree-dump "y = 0;" "optimized" } } */
+
+int x, y;
+
+void
+foo (int n)
+{
+ int c = 3 << 20;
+ x = n / c;
+ y = x / c;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr85726-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr85726-3.c
new file mode 100644
index 0000000..7241fb0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr85726-3.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/85726 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times " / 3;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " / 15;" 1 "optimized" } } */
+
+int x, y, z;
+
+void
+foo (int n)
+{
+ x = n / 3;
+ y = x / 5;
+ z = n / 15;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr85726-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr85726-4.c
new file mode 100644
index 0000000..f57cf3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr85726-4.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/85726 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times " / 4;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " / 16;" 1 "optimized" } } */
+
+int x, y, z;
+
+void
+foo (int n)
+{
+ x = n / 4;
+ y = x / 4;
+ z = y * 16 | 15;
+}