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] Remove invalid pointer BIT_AND_EXPR vrp optimization (PR tree-optimization/91597)


Hi!

As discussed in the PR, this optimization introduced in r161707
is invalid, even when neither of the vrs include NULL, the result
can still be NULL.  While for usual uses (where the second argument
is INTEGER_CST with all bits set except a few last ones and first argument
is a pointer to real object) it is true, if one of the argument is a made up
pointer (say (void *) 1), or the other argument some weird mask as in this
testcase (1), we still get a NULL pointer from the operation.

Dunno if we could say use points-to info to check that one of the arguments
is a real object pointer and have some limited set of pointer realignments
we'd say result in non-NULL pointers.

Anyway, this patch just removes the optimization, bootstrapped/regtested on
x86_64-linux and i686-linux, ok for trunk and 9.x (the testcase is
miscompiled only in 9.x)?

2019-09-03  Jakub Jelinek  <jakub@redhat.com>
	    Richard Biener  <rguenther@suse.de>

	PR tree-optimization/91597
	* tree-vrp.c (extract_range_from_binary_expr): Remove unsafe
	BIT_AND_EXPR optimization for pointers, even if both operand
	ranges don't include NULL, the result can be NULL.

	* gcc.c-torture/execute/pr91597.c: New test.

--- gcc/tree-vrp.c.jj	2019-08-12 09:32:17.811773387 +0200
+++ gcc/tree-vrp.c	2019-09-02 19:14:14.276914085 +0200
@@ -1741,9 +1741,7 @@ extract_range_from_binary_expr (value_ra
 	{
 	  /* For pointer types, we are really only interested in asserting
 	     whether the expression evaluates to non-NULL.  */
-	  if (!range_includes_zero_p (&vr0) && !range_includes_zero_p (&vr1))
-	    vr->set_nonzero (expr_type);
-	  else if (vr0.zero_p () || vr1.zero_p ())
+	  if (vr0.zero_p () || vr1.zero_p ())
 	    vr->set_zero (expr_type);
 	  else
 	    vr->set_varying (expr_type);
--- gcc/testsuite/gcc.c-torture/execute/pr91597.c.jj	2019-09-02 19:13:07.746915030 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr91597.c	2019-09-02 19:03:32.147575358 +0200
@@ -0,0 +1,48 @@
+/* PR tree-optimization/91597 */
+
+enum E { A, B, C };
+struct __attribute__((aligned (4))) S { enum E e; };
+
+enum E
+foo (struct S *o)
+{
+  if (((__UINTPTR_TYPE__) (o) & 1) == 0)
+    return o->e;
+  else
+    return A;
+}
+
+int
+bar (struct S *o)
+{
+  return foo (o) == B || foo (o) == C;
+}
+
+static inline void
+baz (struct S *o, int d)
+{
+  if (__builtin_expect (!bar (o), 0))
+    __builtin_abort ();
+  if (d > 2) return;
+  baz (o, d + 1);
+}
+
+void
+qux (struct S *o)
+{
+  switch (o->e)
+    {
+    case A: return;
+    case B: baz (o, 0); break;
+    case C: baz (o, 0); break;
+    }
+}
+
+struct S s = { C };
+
+int
+main ()
+{
+  qux (&s);
+  return 0;
+}

	Jakub


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