diff mbox series

tree-ssa-uninit: suppress more spurious warnings

Message ID 87v9y9ebyz.fsf@ispras.ru
State New
Headers show
Series tree-ssa-uninit: suppress more spurious warnings | expand

Commit Message

Vladislav Ivanishin May 17, 2019, 8:12 a.m. UTC
Hi!

Without the patch, two of the newly added tests fail with bogus warnings:

- gcc.dg/uninit-28-gimple.c (Definition guarded with NE_EXPR, use with
  BIT_AND_EXPR.  This is an FP my previous patch [1] knowingly
  overlooks.)
- gcc.dg/uninit-30-gimple.c (EQ_EXPR in the predicate guarding use.
  This is what I spotted while refactoring.  It never worked, and is
  easy to handle).

Bootstraped with `BOOT_CFLAGS="-O -Wno-error=maybe-uninitialized
-Wuninitialized"` and regtested on x86_64-pc-linux-gnu.  OK for trunk?

Also, Richard, would you mind being a sponsor for my svn account?

[1]: https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00896.html

Comments

Jeff Law May 17, 2019, 4:43 p.m. UTC | #1
On 5/17/19 2:12 AM, Vladislav Ivanishin wrote:
> Hi!
> 
> Without the patch, two of the newly added tests fail with bogus warnings:
> 
> - gcc.dg/uninit-28-gimple.c (Definition guarded with NE_EXPR, use with
>   BIT_AND_EXPR.  This is an FP my previous patch [1] knowingly
>   overlooks.)
> - gcc.dg/uninit-30-gimple.c (EQ_EXPR in the predicate guarding use.
>   This is what I spotted while refactoring.  It never worked, and is
>   easy to handle).
> 
> Bootstraped with `BOOT_CFLAGS="-O -Wno-error=maybe-uninitialized
> -Wuninitialized"` and regtested on x86_64-pc-linux-gnu.  OK for trunk?
> 
> Also, Richard, would you mind being a sponsor for my svn account?
> 
> [1]: https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00896.html
> 
> 
> 0001-tree-ssa-uninit-suppress-more-spurious-warnings.patch
> 
> 	* tree-ssa-uninit.c (value_sat_pred_p): This new function is a wrapper
>         around is_value_included_in that knows how to handle BIT_AND_EXPR.
>         (is_pred_expr_subset_of): Use the new function.  Handle more cases where
>         code1 == EQ_EXPR and where code1 == BIT_AND_EXPR and thus fix some false
>         positives.
> 
> testsuite/
>         * gcc.dg/uninit-28-gimple.c: New test.
>         * gcc.dg/uninit-29-gimple.c: New test.
>         * gcc.dg/uninit-30-gimple.c: New test.
>         * gcc.dg/uninit-31-gimple.c: New test.
So my question is are these showing up in practice?  The gimple based
tests seem to be skipping the optimizers that would have eliminated this
stuff.

In each of the testcases I would have expected jump threading to have
eliminated the problematical path through the CFG.

I'm not philosophically opposed to improving tree-ssa-uninit.c, but I
just want to understand why we're looking at this aspect of it right now.

If you wanted an interesting project to tackle, separating the predicate
analysis done by tree-ssa-uninit.c from using it to prune false positive
-Wuninitialized warnings would be hugely appreciated.  I think there's
value in re-using the predicate analysis elsewhere in GCC.

jeff

ps. You could list me as a sponsor if Richi doesn't respond.
Alexander Monakov May 17, 2019, 4:59 p.m. UTC | #2
On Fri, 17 May 2019, Jeff Law wrote:

> So my question is are these showing up in practice?  The gimple based
> tests seem to be skipping the optimizers that would have eliminated this
> stuff.
> 
> In each of the testcases I would have expected jump threading to have
> eliminated the problematical path through the CFG.

If there's anything slightly complicated, like say a loop, between the
(lack of) definition and the use, optimizations won't be able to simplify
the flow and the false positive/negative can be seen.

In fact Vlad's first patch submission used a trivial loop in a C testcase
alongside a minimized gimple testcase to showcase how this happens:
https://gcc.gnu.org/ml/gcc-patches/2019-04/msg00040.html

Alexander
Richard Biener May 20, 2019, 9:44 a.m. UTC | #3
On Fri, May 17, 2019 at 10:12 AM Vladislav Ivanishin <vlad@ispras.ru> wrote:
>
> Hi!
>
> Without the patch, two of the newly added tests fail with bogus warnings:
>
> - gcc.dg/uninit-28-gimple.c (Definition guarded with NE_EXPR, use with
>   BIT_AND_EXPR.  This is an FP my previous patch [1] knowingly
>   overlooks.)
> - gcc.dg/uninit-30-gimple.c (EQ_EXPR in the predicate guarding use.
>   This is what I spotted while refactoring.  It never worked, and is
>   easy to handle).
>
> Bootstraped with `BOOT_CFLAGS="-O -Wno-error=maybe-uninitialized
> -Wuninitialized"` and regtested on x86_64-pc-linux-gnu.  OK for trunk?

OK.

> Also, Richard, would you mind being a sponsor for my svn account?

Sure.
Thanks,
Richard.

> [1]: https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00896.html
>
>
> --
> Vlad
Christophe Lyon May 22, 2019, 8:24 a.m. UTC | #4
On Fri, 17 May 2019 at 10:12, Vladislav Ivanishin <vlad@ispras.ru> wrote:
>
> Hi!
>
> Without the patch, two of the newly added tests fail with bogus warnings:
>
> - gcc.dg/uninit-28-gimple.c (Definition guarded with NE_EXPR, use with
>   BIT_AND_EXPR.  This is an FP my previous patch [1] knowingly
>   overlooks.)
> - gcc.dg/uninit-30-gimple.c (EQ_EXPR in the predicate guarding use.
>   This is what I spotted while refactoring.  It never worked, and is
>   easy to handle).
>
> Bootstraped with `BOOT_CFLAGS="-O -Wno-error=maybe-uninitialized
> -Wuninitialized"` and regtested on x86_64-pc-linux-gnu.  OK for trunk?
>

Hi,

As you have probably noticed already, the new test uninit-28.c fails:
/gcc/testsuite/gcc.dg/uninit-28-gimple.c:9:16: warning: 'undef' may be
used uninitialized in this function [-Wmaybe-uninitialized]
FAIL: gcc.dg/uninit-28-gimple.c  (test for bogus messages, line 9)
at least on arm & aarch64

Christophe

> Also, Richard, would you mind being a sponsor for my svn account?
>
> [1]: https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00896.html
>
>
> --
> Vlad
Rainer Orth May 22, 2019, 8:57 a.m. UTC | #5
Hi Christophe,

> On Fri, 17 May 2019 at 10:12, Vladislav Ivanishin <vlad@ispras.ru> wrote:
>>
>> Hi!
>>
>> Without the patch, two of the newly added tests fail with bogus warnings:
>>
>> - gcc.dg/uninit-28-gimple.c (Definition guarded with NE_EXPR, use with
>>   BIT_AND_EXPR.  This is an FP my previous patch [1] knowingly
>>   overlooks.)
>> - gcc.dg/uninit-30-gimple.c (EQ_EXPR in the predicate guarding use.
>>   This is what I spotted while refactoring.  It never worked, and is
>>   easy to handle).
>>
>> Bootstraped with `BOOT_CFLAGS="-O -Wno-error=maybe-uninitialized
>> -Wuninitialized"` and regtested on x86_64-pc-linux-gnu.  OK for trunk?
>>
>
> Hi,
>
> As you have probably noticed already, the new test uninit-28.c fails:
> /gcc/testsuite/gcc.dg/uninit-28-gimple.c:9:16: warning: 'undef' may be
> used uninitialized in this function [-Wmaybe-uninitialized]
> FAIL: gcc.dg/uninit-28-gimple.c  (test for bogus messages, line 9)
> at least on arm & aarch64

I'm seeing it on sparc-sun-solaris2.11, and there are gcc-testresults
reports for i?86, mips64el, powerpc*, s390x, and x86_64.

	Rainer
Rainer Orth May 22, 2019, 9:10 a.m. UTC | #6
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

>> On Fri, 17 May 2019 at 10:12, Vladislav Ivanishin <vlad@ispras.ru> wrote:
>>>
>>> Hi!
>>>
>>> Without the patch, two of the newly added tests fail with bogus warnings:
>>>
>>> - gcc.dg/uninit-28-gimple.c (Definition guarded with NE_EXPR, use with
>>>   BIT_AND_EXPR.  This is an FP my previous patch [1] knowingly
>>>   overlooks.)
>>> - gcc.dg/uninit-30-gimple.c (EQ_EXPR in the predicate guarding use.
>>>   This is what I spotted while refactoring.  It never worked, and is
>>>   easy to handle).
>>>
>>> Bootstraped with `BOOT_CFLAGS="-O -Wno-error=maybe-uninitialized
>>> -Wuninitialized"` and regtested on x86_64-pc-linux-gnu.  OK for trunk?
>>>
>>
>> Hi,
>>
>> As you have probably noticed already, the new test uninit-28.c fails:
>> /gcc/testsuite/gcc.dg/uninit-28-gimple.c:9:16: warning: 'undef' may be
>> used uninitialized in this function [-Wmaybe-uninitialized]
>> FAIL: gcc.dg/uninit-28-gimple.c  (test for bogus messages, line 9)
>> at least on arm & aarch64
>
> I'm seeing it on sparc-sun-solaris2.11, and there are gcc-testresults
> reports for i?86, mips64el, powerpc*, s390x, and x86_64.

There are a couple more testsuite regressions that are likely fallout
from this patch:

+FAIL: gcc.dg/pr67512.c (test for excess errors)

  32 and 64-bit i386-pc-solaris2.11, also on aarch64-unknown-linux-gnu

+FAIL: gcc.dg/uninit-18.c  (test for bogus messages, line 13)

  32 and 64-bit i386-pc-solaris2.11, also on aarch64-unknown-linux-gnu,
  powerpc64le-unknown-linux-gnu

+FAIL: gcc.dg/uninit-pr90394-1-gimple.c  (test for warnings, line 9)

  32 and 64-bit i386-pc-solaris2.11, also on aarch64-unknown-linux-gnu,
  powerpc64le-unknown-linux-gnu, s390x-ibm-linux-gnu

	Rainer
Vladislav Ivanishin May 22, 2019, 2:44 p.m. UTC | #7
Christophe, Rainer,

Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> Hi Christophe,
>
>> On Fri, 17 May 2019 at 10:12, Vladislav Ivanishin <vlad@ispras.ru> wrote:
>>>
>> As you have probably noticed already, the new test uninit-28.c fails:
>> /gcc/testsuite/gcc.dg/uninit-28-gimple.c:9:16: warning: 'undef' may be
>> used uninitialized in this function [-Wmaybe-uninitialized]
>> FAIL: gcc.dg/uninit-28-gimple.c  (test for bogus messages, line 9)
>> at least on arm & aarch64

Thanks for spotting.  I managed to reproduce the failure on x86_64 (I
started from revision and configure options in one of H.J.'s test
results [1]) and it seems, another check-in is to blame.  The stage1
compiler is always fine w.r.t. the result on uninit-28-gimple.c.  The
stage2 compiler seems to be miscompiled.

r271460 is already bad, yes, but the problem starts earlier (better to
pick another test as an indicator, or bisect just the stage1 compiler,
compiling pseudo-stage2 with it from newer sources).

I'm going to bisect the regression and report to the appropriate thread
unless someone beats me to it.

[1]: https://gcc.gnu.org/ml/gcc-testresults/2019-05/msg02436.html

> I'm seeing it on sparc-sun-solaris2.11, and there are gcc-testresults
> reports for i?86, mips64el, powerpc*, s390x, and x86_64.
>
> 	Rainer
Jeff Law May 22, 2019, 3:19 p.m. UTC | #8
On 5/22/19 8:44 AM, Vladislav Ivanishin wrote:
> Christophe, Rainer,
> 
> Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:
> 
>> Hi Christophe,
>>
>>> On Fri, 17 May 2019 at 10:12, Vladislav Ivanishin <vlad@ispras.ru> wrote:
>>>>
>>> As you have probably noticed already, the new test uninit-28.c fails:
>>> /gcc/testsuite/gcc.dg/uninit-28-gimple.c:9:16: warning: 'undef' may be
>>> used uninitialized in this function [-Wmaybe-uninitialized]
>>> FAIL: gcc.dg/uninit-28-gimple.c  (test for bogus messages, line 9)
>>> at least on arm & aarch64
> 
> Thanks for spotting.  I managed to reproduce the failure on x86_64 (I
> started from revision and configure options in one of H.J.'s test
> results [1]) and it seems, another check-in is to blame.  The stage1
> compiler is always fine w.r.t. the result on uninit-28-gimple.c.  The
> stage2 compiler seems to be miscompiled.
> 
> r271460 is already bad, yes, but the problem starts earlier (better to
> pick another test as an indicator, or bisect just the stage1 compiler,
> compiling pseudo-stage2 with it from newer sources).
> 
> I'm going to bisect the regression and report to the appropriate thread
> unless someone beats me to it.
> 
> [1]: https://gcc.gnu.org/ml/gcc-testresults/2019-05/msg02436.html
> 
>> I'm seeing it on sparc-sun-solaris2.11, and there are gcc-testresults
>> reports for i?86, mips64el, powerpc*, s390x, and x86_64.
FWIW I'm also seeing uninit-18 failing on the ppc targets.

And I'll reiterate my concern that these are likely masking issues
earlier in the optimizer pipeline.  For example uninit-18 really should
be fixed by threading in either DOM or VRP.

Jeff
Iain Sandoe May 22, 2019, 3:44 p.m. UTC | #9
> On 22 May 2019, at 16:19, Jeff Law <law@redhat.com> wrote:
> 
> On 5/22/19 8:44 AM, Vladislav Ivanishin wrote:
>> Christophe, Rainer,
>> 
>> Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:
>> 
>>> Hi Christophe,
>>> 
>>>> On Fri, 17 May 2019 at 10:12, Vladislav Ivanishin <vlad@ispras.ru> wrote:
>>>>> 
>>>> As you have probably noticed already, the new test uninit-28.c fails:
>>>> /gcc/testsuite/gcc.dg/uninit-28-gimple.c:9:16: warning: 'undef' may be
>>>> used uninitialized in this function [-Wmaybe-uninitialized]
>>>> FAIL: gcc.dg/uninit-28-gimple.c  (test for bogus messages, line 9)
>>>> at least on arm & aarch64
>> 
>> Thanks for spotting.  I managed to reproduce the failure on x86_64 (I
>> started from revision and configure options in one of H.J.'s test
>> results [1]) and it seems, another check-in is to blame.  The stage1
>> compiler is always fine w.r.t. the result on uninit-28-gimple.c.  The
>> stage2 compiler seems to be miscompiled.
>> 
>> r271460 is already bad, yes, but the problem starts earlier (better to
>> pick another test as an indicator, or bisect just the stage1 compiler,
>> compiling pseudo-stage2 with it from newer sources).
>> 
>> I'm going to bisect the regression and report to the appropriate thread
>> unless someone beats me to it.
>> 
>> [1]: https://gcc.gnu.org/ml/gcc-testresults/2019-05/msg02436.html
>> 
>>> I'm seeing it on sparc-sun-solaris2.11, and there are gcc-testresults
>>> reports for i?86, mips64el, powerpc*, s390x, and x86_64.
> FWIW I'm also seeing uninit-18 failing on the ppc targets.

uninit-18, 19 are failing on x86_64-darwin16 (m32 and m64) at least, too
(although uninit-28 is passing there).

Iain

> 
> And I'll reiterate my concern that these are likely masking issues
> earlier in the optimizer pipeline.  For example uninit-18 really should
> be fixed by threading in either DOM or VRP.
> 
> Jeff
Vladislav Ivanishin May 23, 2019, 1:50 p.m. UTC | #10
Iain Sandoe <idsandoe@googlemail.com> writes:

>> On 22 May 2019, at 16:19, Jeff Law <law@redhat.com> wrote:
>> 
>> On 5/22/19 8:44 AM, Vladislav Ivanishin wrote:
>>> Christophe, Rainer,
>>> 
>>> Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:
>>> 
>>>> Hi Christophe,
>>>> 
>>>>> On Fri, 17 May 2019 at 10:12, Vladislav Ivanishin <vlad@ispras.ru> wrote:
>>>>>> 
>>>>> As you have probably noticed already, the new test uninit-28.c fails:
>>>>> /gcc/testsuite/gcc.dg/uninit-28-gimple.c:9:16: warning: 'undef' may be
>>>>> used uninitialized in this function [-Wmaybe-uninitialized]
>>>>> FAIL: gcc.dg/uninit-28-gimple.c  (test for bogus messages, line 9)
>>>>> at least on arm & aarch64
>>> 
>>> Thanks for spotting.  I managed to reproduce the failure on x86_64 (I
>>> started from revision and configure options in one of H.J.'s test
>>> results [1]) and it seems, another check-in is to blame.  The stage1
>>> compiler is always fine w.r.t. the result on uninit-28-gimple.c.  The
>>> stage2 compiler seems to be miscompiled.
>>> 
>>> r271460 is already bad, yes, but the problem starts earlier (better to
>>> pick another test as an indicator, or bisect just the stage1 compiler,
>>> compiling pseudo-stage2 with it from newer sources).
>>> 
>>> I'm going to bisect the regression and report to the appropriate thread
>>> unless someone beats me to it.

OK, this is the right thread after all.  Failure on uninit-28-gimple.c
is fixed by Martin's patch for PR90587 (checked on x84_64-pc-linux-gnu).

Thank you!

If the problems persist on other tests and targets, please let me know.
I'll check gcc-testresults when testers pick up the fix.

Vlad

>>> 
>>> [1]: https://gcc.gnu.org/ml/gcc-testresults/2019-05/msg02436.html
>>> 
>>>> I'm seeing it on sparc-sun-solaris2.11, and there are gcc-testresults
>>>> reports for i?86, mips64el, powerpc*, s390x, and x86_64.
>> FWIW I'm also seeing uninit-18 failing on the ppc targets.
>
> uninit-18, 19 are failing on x86_64-darwin16 (m32 and m64) at least, too
> (although uninit-28 is passing there).
>
> Iain
>
>> 
>> And I'll reiterate my concern that these are likely masking issues
>> earlier in the optimizer pipeline.  For example uninit-18 really should
>> be fixed by threading in either DOM or VRP.
>> 
>> Jeff
diff mbox series

Patch

	* tree-ssa-uninit.c (value_sat_pred_p): This new function is a wrapper
        around is_value_included_in that knows how to handle BIT_AND_EXPR.
        (is_pred_expr_subset_of): Use the new function.  Handle more cases where
        code1 == EQ_EXPR and where code1 == BIT_AND_EXPR and thus fix some false
        positives.

testsuite/
        * gcc.dg/uninit-28-gimple.c: New test.
        * gcc.dg/uninit-29-gimple.c: New test.
        * gcc.dg/uninit-30-gimple.c: New test.
        * gcc.dg/uninit-31-gimple.c: New test.
---
 gcc/testsuite/gcc.dg/uninit-28-gimple.c | 47 ++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/uninit-29-gimple.c | 45 +++++++++++++++++++++++
 gcc/testsuite/gcc.dg/uninit-30-gimple.c | 43 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/uninit-31-gimple.c | 48 +++++++++++++++++++++++++
 gcc/tree-ssa-uninit.c                   | 37 +++++++++++++------
 5 files changed, 210 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/uninit-28-gimple.c
 create mode 100644 gcc/testsuite/gcc.dg/uninit-29-gimple.c
 create mode 100644 gcc/testsuite/gcc.dg/uninit-30-gimple.c
 create mode 100644 gcc/testsuite/gcc.dg/uninit-31-gimple.c

diff --git a/gcc/testsuite/gcc.dg/uninit-28-gimple.c b/gcc/testsuite/gcc.dg/uninit-28-gimple.c
new file mode 100644
index 00000000000..0648b8a4aa7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-28-gimple.c
@@ -0,0 +1,47 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */
+
+unsigned int __GIMPLE (ssa,startwith("uninit1"))
+foo (unsigned int v)
+{
+  /* Uninit warning here would be bogus, because (16 & 3) == 0 and therefore
+     if v == 16, the uninit value is not used (the use is properly guarded).  */
+  unsigned int undef;        /* { dg-bogus "may be used uninitialized" } */
+  unsigned int _2;
+  unsigned int _9;
+  unsigned int _10;
+  unsigned pred;
+
+  __BB(2):
+  if (v_4(D) != 16u)
+    goto __BB3;
+  else
+    goto __BB4;
+
+  /* 'undef' is defined conditionally (under 'v != 16' predicate)  */
+  __BB(3):
+  undef_8 = 8u;
+  goto __BB4;
+
+  /* An undef value flows into a phi.  */
+  __BB(4):
+  undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+  pred = v_4(D) & 3u;
+  if (pred != 0u)
+    goto __BB5;
+  else
+    goto __BB6;
+
+  /* The phi value is used here (under 'v & 3' predicate).  */
+  __BB(5):
+  _9 = undef_1;
+  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-29-gimple.c b/gcc/testsuite/gcc.dg/uninit-29-gimple.c
new file mode 100644
index 00000000000..cb5bc97164e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-29-gimple.c
@@ -0,0 +1,45 @@ 
+/* { 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;
+  unsigned pred;
+
+  __BB(2):
+  pred = v_4(D) & 3u;
+  if (pred != 0u)
+    goto __BB3;
+  else
+    goto __BB4;
+
+  /* 'undef' is defined conditionally (under 'v & 3' predicate)  */
+  __BB(3):
+  undef_8 = 8u;
+  goto __BB4;
+
+  /* An undef value flows into a phi.  */
+  __BB(4):
+  undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+  if (v_4(D) != 16u)
+    goto __BB5;
+  else
+    goto __BB6;
+
+  /* The phi value is used here (under 'v != 16' predicate).  */
+  __BB(5):
+  _9 = undef_1;
+  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-30-gimple.c b/gcc/testsuite/gcc.dg/uninit-30-gimple.c
new file mode 100644
index 00000000000..8c91f79d509
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-30-gimple.c
@@ -0,0 +1,43 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */
+
+unsigned int __GIMPLE (ssa,startwith("uninit1"))
+foo (unsigned int v)
+{
+  unsigned int undef;        /* { dg-bogus "may be used uninitialized" } */
+  unsigned int _2;
+  unsigned int _9;
+  unsigned int _10;
+
+  __BB(2):
+  if (v_4(D) < 100u)
+    goto __BB3;
+  else
+    goto __BB4;
+
+  /* 'undef' is defined conditionally (under 'v < 100' predicate).  */
+  __BB(3):
+  undef_8 = 8u;
+  goto __BB4;
+
+  /* An undef value flows into a phi.  */
+  __BB(4):
+  undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+  if (v_4(D) == 42u)
+    goto __BB5;
+  else
+    goto __BB6;
+
+  /* The phi value is used here (under 'v == 42' predicate).  */
+  __BB(5):
+  _9 = undef_1;
+  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-31-gimple.c b/gcc/testsuite/gcc.dg/uninit-31-gimple.c
new file mode 100644
index 00000000000..01118ef9823
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-31-gimple.c
@@ -0,0 +1,48 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */
+
+unsigned int __GIMPLE (ssa,startwith("uninit1"))
+foo (unsigned int v)
+{
+  /* If v == 2, then undef is used w/o being initialized.  */
+  unsigned int undef;        /* { dg-warning "may be used uninitialized" } */
+  unsigned int _2;
+  unsigned int _9;
+  unsigned int _10;
+  unsigned int pred2;
+  unsigned int pred1;
+
+  __BB(2):
+  pred2 = v_4(D) & 5u;
+  if (pred2 != 0u)
+    goto __BB3;
+  else
+    goto __BB4;
+
+  /* 'undef' is defined conditionally (under 'v & 5' predicate).  */
+  __BB(3):
+  undef_8 = 8u;
+  goto __BB4;
+
+  /* An undef value flows into a phi.  */
+  __BB(4):
+  undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+  pred1 = v_4(D) & 3u;
+  if (pred1 != 0u)
+    goto __BB5;
+  else
+    goto __BB6;
+
+  /* The phi value is used here (under 'v & 3' predicate).  */
+  __BB(5):
+  _9 = undef_1;
+  goto __BB7;
+
+  __BB(6):
+  _10 = v_4(D);
+  goto __BB7;
+
+  __BB(7):
+  _2 = __PHI (__BB5: _9, __BB6: _10);
+  return _2;
+}
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index b89da4017e8..bc07afe32c8 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -1045,6 +1045,26 @@  is_value_included_in (tree val, tree boundary, enum tree_code cmpc)
   return result;
 }
 
+/* Returns whether VAL satisfies (x CMPC BOUNDARY) predicate.  CMPC can be
+   either one of the range comparison codes ({GE,LT,EQ,NE}_EXPR and the like),
+   or BIT_AND_EXPR.  EXACT_P is only meaningful for the latter.  It modifies the
+   question from whether VAL & BOUNDARY != 0 to whether VAL & BOUNDARY == VAL.
+   For other values of CMPC, EXACT_P is ignored.  */
+
+static bool
+value_sat_pred_p (tree val, tree boundary, enum tree_code cmpc,
+		  bool exact_p = false)
+{
+  if (cmpc != BIT_AND_EXPR)
+    return is_value_included_in (val, boundary, cmpc);
+
+  wi::tree_to_wide_ref andw = wi::to_wide (val) & wi::to_wide (boundary);
+  if (exact_p)
+    return andw == wi::to_wide (val);
+  else
+    return andw.to_uhwi ();
+}
+
 /* Returns true if PRED is common among all the predicate
    chains (PREDS) (and therefore can be factored out).
    NUM_PRED_CHAIN is the size of array PREDS.  */
@@ -1471,18 +1491,15 @@  is_pred_expr_subset_of (pred_info expr1, pred_info expr2)
   if (code2 == NE_EXPR && code1 == NE_EXPR)
     return false;
 
-  if (code2 == NE_EXPR && code1 != BIT_AND_EXPR)
-    return !is_value_included_in (expr2.pred_rhs, expr1.pred_rhs, code1);
+  if (code2 == NE_EXPR)
+    return !value_sat_pred_p (expr2.pred_rhs, expr1.pred_rhs, code1);
 
-  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)));
+  if (code1 == EQ_EXPR)
+    return value_sat_pred_p (expr1.pred_rhs, expr2.pred_rhs, code2);
 
-  if (code1 != code2)
-    return false;
-
-  if (is_value_included_in (expr1.pred_rhs, expr2.pred_rhs, code2))
-    return true;
+  if (code1 == code2)
+    return value_sat_pred_p (expr1.pred_rhs, expr2.pred_rhs, code2,
+			     code1 == BIT_AND_EXPR);
 
   return false;
 }
-- 
2.20.1