This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Improve merge_ranges (PR tree-optimization/69615)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]