This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Improve merge_ranges (PR tree-optimization/69615)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Biener <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sun, 3 Jun 2018 19:36:52 +0200
- Subject: [PATCH] Improve merge_ranges (PR tree-optimization/69615)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
We canonicalize x < type_max_val (type (x)) as x != type_max_val (type (x))
and similarly for x > type_min_val (type (x)). Unfortunately the former
form is what is often more beneficial for merge_ranges, if we have as in the
testcase e.g. x >= 0 && x != __INT_MAX__, in?_p is different and we don't
optimize it, but it can be optimized into [0, __INT_MAX__-1] range.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?
2018-06-03 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/69615
* fold-const.c (merge_ranges): If range1 is - [x, x] and x is the
maximum or minimum of the type, try to merge it also as if
range1 is + [-, x - 1] or + [x + 1, -].
* gcc.dg/pr69615.c: New test.
--- gcc/fold-const.c.jj 2018-05-31 20:53:33.000000000 +0200
+++ gcc/fold-const.c 2018-06-02 19:20:10.210975502 +0200
@@ -5084,6 +5084,29 @@ merge_ranges (int *pin_p, tree *plow, tr
tem = high0, high0 = high1, high1 = tem;
}
+ /* If the second range is != high1 where high1 is the type maximum of
+ the type, try first merging with < high1 range. */
+ if (low1
+ && high1
+ && TREE_CODE (low1) == INTEGER_CST
+ && (TREE_CODE (TREE_TYPE (low1)) == INTEGER_TYPE
+ || (TREE_CODE (TREE_TYPE (low1)) == ENUMERAL_TYPE
+ && known_eq (TYPE_PRECISION (TREE_TYPE (low1)),
+ GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (low1))))))
+ && operand_equal_p (low1, high1, 0))
+ {
+ if (tree_int_cst_equal (low1, TYPE_MAX_VALUE (TREE_TYPE (low1)))
+ && merge_ranges (pin_p, plow, phigh, in0_p, low0, high0,
+ !in1_p, NULL_TREE, range_predecessor (low1)))
+ return true;
+ /* Similarly for the second range != low1 where low1 is the type minimum
+ of the type, try first merging with > low1 range. */
+ if (tree_int_cst_equal (low1, TYPE_MIN_VALUE (TREE_TYPE (low1)))
+ && merge_ranges (pin_p, plow, phigh, in0_p, low0, high0,
+ !in1_p, range_successor (low1), NULL_TREE))
+ return true;
+ }
+
/* Now flag two cases, whether the ranges are disjoint or whether the
second range is totally subsumed in the first. Note that the tests
below are simplified by the ones above. */
--- gcc/testsuite/gcc.dg/pr69615.c.jj 2018-06-02 19:40:26.282663273 +0200
+++ gcc/testsuite/gcc.dg/pr69615.c 2018-06-02 19:40:01.427633205 +0200
@@ -0,0 +1,37 @@
+/* PR tree-optimization/69615 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not " >= 0" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " < 0" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " <= 23" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " > 23" "optimized" } } */
+
+extern void foo (void);
+
+void
+f1 (int x)
+{
+ if (x >= 0 && x <= __INT_MAX__ - 1)
+ foo ();
+}
+
+void
+f2 (int x, int y)
+{
+ if (x >= 0 && y && x <= __INT_MAX__ - 1)
+ foo ();
+}
+
+void
+f3 (int x)
+{
+ if (x > -__INT_MAX__ - 1 && x <= 23)
+ foo ();
+}
+
+void
+f4 (int x, int y)
+{
+ if (x > -__INT_MAX__ - 1 && y && x <= 23)
+ foo ();
+}
Jakub