Hi! This is a fairly trivial change fixing a false negative in -Wmaybe-uninitialized. I am pretty sure this is simply an overlooked case (is_value_included_in() is not meant to deal with the case where both compare codes are NE_EXPRs, neither does it need to, since their handling is trivial).
In a nutshell, what happens is values of v restricted by (v != 2) are incorrectly considered a subset of values of v restricted by (v != 1). As if "v != 2, therefore v != 1". This is by no means a gcc-9 regression; I'll ping the patch once stage4 is over, if needed. This came up when I was experimenting with moving the uninit passes around. On mainline, the late uninit pass runs very late, so reliably triggering the affected path is a bit tricky. So I created a GIMPLE test (it reproduces the behavior precisely, but might be fragile w.r.t. future versions of the textual representation) and then with a hint from Alexander managed to produce a simple C test. [By the way, the first take was to insert an asm with a lot of newlines to prevent the dom pass from rewriting the CFG due to high cost of duplicating instructions. This didn't work out; I think the dom pass does not respect sizes of inline asms. I plan to create a testcase and file a bug later.] I ran regression testing on x86_64-pc-linux-gnu and saw no new regressions modulo a handful of flaky UNRESOLVED tests under gcc.dg/tree-prof. `BOOT_CFLAGS="-O -Wno-error=maybe-uninitialized -Wmaybe-uninitialized" bootstrap` also succeeded producing no new warnings. OK for stage1?
gcc/ChangeLog: * tree-ssa-uninit.c (is_pred_expr_subset_of): Correctly handle a case where the operand of both simple predicates is the same, both compare codes are NE_EXPR, and the integer values are different (e.g. neither of the predicate expressions 'v != 1' and 'v != 2' should be considered a subset of the other). gcc/testsuite/ChangeLog: * gcc.dg/uninit-25-gimple.c: New test. * gcc.dg/uninit-25.c: New test. --- gcc/testsuite/gcc.dg/uninit-25-gimple.c | 41 +++++++++++++++++++++++++ gcc/testsuite/gcc.dg/uninit-25.c | 23 ++++++++++++++ gcc/tree-ssa-uninit.c | 3 ++ 3 files changed, 67 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/uninit-25-gimple.c create mode 100644 gcc/testsuite/gcc.dg/uninit-25.c diff --git a/gcc/testsuite/gcc.dg/uninit-25-gimple.c b/gcc/testsuite/gcc.dg/uninit-25-gimple.c new file mode 100644 index 00000000000..0c0acd6b83e --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-25-gimple.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */ + +unsigned int __GIMPLE (ssa,startwith("uninit1")) +foo (unsigned int v) +{ + unsigned int undef; /* { dg-warning "may be used uninitialized" } */ + unsigned int _2; + unsigned int _9; + unsigned int _10; + + __BB(2): + if (v_4(D) != 1u) + goto __BB3; + else + goto __BB4; + + __BB(3): + undef_8 = 8u; // 'undef' is defined conditionally (under 'v != 1' predicate) + goto __BB4; + + __BB(4): + // An undef value flows into a phi. + undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8); + if (v_4(D) != 2u) // This condition is neither a superset nor a subset of 'v != 1'. + goto __BB5; + else + goto __BB6; + + __BB(5): + _9 = undef_1; // The phi value is used here (under 'v != 2' predicate). + goto __BB7; + + __BB(6): + _10 = v_4(D); + goto __BB7; + + __BB(7): + _2 = __PHI (__BB5: _9, __BB6: _10); + return _2; +} diff --git a/gcc/testsuite/gcc.dg/uninit-25.c b/gcc/testsuite/gcc.dg/uninit-25.c new file mode 100644 index 00000000000..ffffce3f91c --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-25.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O -Wmaybe-uninitialized" } */ + +extern unsigned bar (void); +extern void quux (void); + +unsigned foo (unsigned v) +{ + unsigned u; + if (v != 1) + u = bar (); + + // Prevent the "dom" pass from changing the CFG layout based on the inference + // 'if (v != 1) is false then (v != 2) is true'. (Now it would have to + // duplicate the loop in order to do so, which is deemed expensive.) + for (int i = 0; i < 10; i++) + quux (); + + if (v != 2) + return u; /* { dg-warning "may be used uninitialized" } */ + + return 0; +} diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 55a55a05c96..1de7d21d2eb 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -1488,6 +1488,9 @@ is_pred_expr_subset_of (pred_info expr1, pred_info expr2) if (expr2.invert) code2 = invert_tree_comparison (code2, false); + if (code1 == NE_EXPR && code2 == NE_EXPR) + return false; + if ((code1 == EQ_EXPR || code1 == BIT_AND_EXPR) && code2 == BIT_AND_EXPR) return (wi::to_wide (expr1.pred_rhs) == (wi::to_wide (expr1.pred_rhs) & wi::to_wide (expr2.pred_rhs))); -- 2.20.1
-- Vlad