From 3729852e407e5e1c4f1bbacea1b53e61d7609dad Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 3 Sep 2019 09:50:46 +0200 Subject: [PATCH] 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 From-SVN: r275330 --- gcc/ChangeLog | 8 ++++ gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/gcc.c-torture/execute/pr91597.c | 48 +++++++++++++++++++ gcc/tree-vrp.c | 4 +- 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr91597.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a0f9178c8b..1d20ffc9d5a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-09-03 Jakub Jelinek + Richard Biener + + 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 PR middle-end/91605 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index efb25dff085..651baebe5f7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-09-03 Jakub Jelinek + Richard Biener + + PR tree-optimization/91597 + * gcc.c-torture/execute/pr91597.c: New test. + 2019-09-03 Alexandre Oliva * gcc.target/i386/20020616-1.c: Preserve full register across diff --git a/gcc/testsuite/gcc.c-torture/execute/pr91597.c b/gcc/testsuite/gcc.c-torture/execute/pr91597.c new file mode 100644 index 00000000000..6a917cb58af --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr91597.c @@ -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; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index bc0648080db..0a7e7c7609b 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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); -- 2.30.2