re PR tree-optimization/91597 (GCC miscompiles a branch depending on a pointer tag)

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.

Co-Authored-By: Richard Biener <rguenther@suse.de>

From-SVN: r275330
This commit is contained in:
Jakub Jelinek 2019-09-03 09:50:46 +02:00 committed by Jakub Jelinek
parent e4a8d4a7ec
commit 3729852e40
4 changed files with 63 additions and 3 deletions

View file

@ -1,3 +1,11 @@
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.
2019-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR middle-end/91605

View file

@ -1,3 +1,9 @@
2019-09-03 Jakub Jelinek <jakub@redhat.com>
Richard Biener <rguenther@suse.de>
PR tree-optimization/91597
* gcc.c-torture/execute/pr91597.c: New test.
2019-09-03 Alexandre Oliva <oliva@adacore.com>
* gcc.target/i386/20020616-1.c: Preserve full register across

View file

@ -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;
}

View file

@ -1741,9 +1741,7 @@ extract_range_from_binary_expr (value_range_base *vr,
{
/* 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);