On Fri, Apr 12, 2024 at 1:25 AM Andrew Pinski (QUIC)
<quic_apin...@quicinc.com> wrote:
>
> > -----Original Message-----
> > From: Richard Biener <richard.guent...@gmail.com>
> > Sent: Thursday, April 11, 2024 2:31 AM
> > To: Andrew Pinski (QUIC) <quic_apin...@quicinc.com>
> > Cc: gcc-patches@gcc.gnu.org
> > Subject: Re: [PATCH] match: Fix `!a?b:c` and `a?~t:t` patterns for signed 1 
> > bit
> > types [PR114666]
> >
> > On Thu, Apr 11, 2024 at 10:43 AM Andrew Pinski
> > <quic_apin...@quicinc.com> wrote:
> > >
> > > The issue here is that the `a?~t:t` pattern assumed (maybe correctly)
> > > that a here was always going to be a unsigned boolean type. This fixes
> > > the problem in both patterns to cast the operand to boolean type first.
> > >
> > > I should note that VRP seems to be keep on wanting to produce `a ==
> > > 0?1:-2` from `((int)a) ^ 1` is a bit odd and partly is the cause of
> > > the issue and there seems to be some disconnect on what should be the
> > > canonical form. That will be something to look at for GCC 15.
> > >
> > > Bootstrapped and tested on x86_64-linux-gnu with no regressions.
> > >
> > >         PR tree-optimization/114666
> > >
> > > gcc/ChangeLog:
> > >
> > >         * match.pd (`!a?b:c`): Cast `a` to boolean type for cond for
> > >         gimple.
> > >         (`a?~t:t`): Cast `a` to boolean type before casting it
> > >         to the type.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > >         * gcc.c-torture/execute/bitfld-signed1-1.c: New test.
> > >
> > > Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> > > ---
> > >  gcc/match.pd                                        | 10 +++++++---
> > >  .../gcc.c-torture/execute/bitfld-signed1-1.c        | 13 +++++++++++++
> > >  2 files changed, 20 insertions(+), 3 deletions(-)  create mode 100644
> > > gcc/testsuite/gcc.c-torture/execute/bitfld-signed1-1.c
> > >
> > > diff --git a/gcc/match.pd b/gcc/match.pd index
> > > 15a1e7350d4..ffc928b656a 100644
> > > --- a/gcc/match.pd
> > > +++ b/gcc/match.pd
> > > @@ -5895,7 +5895,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > >   /* !A ? B : C -> A ? C : B.  */
> > >   (simplify
> > >    (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
> > > -  (cnd @0 @2 @1)))
> > > +  /* For gimple, make sure the operand to COND is a boolean type,
> > > +     truth_valued_p will match 1bit integers too. */  (if (GIMPLE &&
> > > + cnd == COND_EXPR)
> > > +   (cnd (convert:boolean_type_node @0) @2 @1)
> > > +   (cnd @0 @2 @1))))
> >
> > This looks "wrong" for GENERIC still?
>
> I tired without the GIMPLE check and ran into the testcase 
> gcc.dg/torture/builtins-isinf-sign-1.c failing. Because the extra convert was 
> blocking seeing both sides of an equal was the same (I didn't look into it 
> further than that). So I decided to limit it to GIMPLE only.
>
> > But this is not really part of the fix but deciding we should not have
> > signed:1 as
> > cond operand?  I'll note that truth_valued_p allows signed:1.
> >
> > Maybe as minimal surgery add a TYPE_UNSIGNED (TREE_TPE (@0)) check here
> > instead?
>
> That might work, let me try.
>
> >
> > >  /* abs/negative simplifications moved from
> > fold_cond_expr_with_comparison.
> > >
> > > @@ -7099,8 +7103,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > >         && (!wascmp || TYPE_PRECISION (type) == 1))
> > >     (if ((!TYPE_UNSIGNED (type) && TREE_CODE (type) == BOOLEAN_TYPE)
> > >         || TYPE_PRECISION (type) == 1)
> > > -    (bit_xor (convert:type @0) @2)
> > > -    (bit_xor (negate (convert:type @0)) @2)))))
> > > +    (bit_xor (convert:type (convert:boolean_type_node @0)) @2)
> > > +    (bit_xor (negate (convert:type (convert:boolean_type_node @0)))
> > > + @2)))))
> > >  #endif
> >
> > This looks OK, but then testing TYPE_UNSIGNED (TREE_TYPE (@0)) might be
> > better?
> >
>
> Let me do that just like the other pattern.
>
> > Does this all just go downhill from what VRP creates?  That is, would IL
> > checking have had a chance detecting it if we say signed:1 are not valid as
> > condition?
>
> Yes. So what VRP produces in the testcase is:
> `_2 == 0 ? 1 : -2u` (where _2 is the signed 1bit integer).
> Now maybe the COND_EXPR should be the canonical form for constants (but that 
> is for a different patch I think, I added it to the list of things I should 
> look into for GCC 15).

Ah OK, so the !A ? B : C -> A ? C : B transform turns the
"proper" conditional into an improper one (if we want to restrict it).
And then the other pattern matches doing the wrong transform.

> >
> > That said, the latter pattern definitely needs guarding/adjustment, I'm not
> > sure the former is wrong?  Semantically [VEC_]COND_EXPR is op0 != 0 ? ... : 
> > ...
>
> I forgot to mention that to fix the bug only one of the 2 hunks are needed.
>
> >
> > Richard.
> >
> > >  /* Simplify pointer equality compares using PTA.  */ diff --git
> > > a/gcc/testsuite/gcc.c-torture/execute/bitfld-signed1-1.c
> > > b/gcc/testsuite/gcc.c-torture/execute/bitfld-signed1-1.c
> > > new file mode 100644
> > > index 00000000000..b0ff120ea51
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.c-torture/execute/bitfld-signed1-1.c
> > > @@ -0,0 +1,13 @@
> > > +/* PR tree-optimization/114666 */
> > > +/* We used to miscompile this to be always aborting
> > > +   due to the use of the signed 1bit into the COND_EXPR. */
> > > +
> > > +struct {
> > > +  signed a : 1;
> > > +} b = {-1};
> > > +char c;
> > > +int main()
> > > +{
> > > +  if ((b.a ^ 1UL) < 3)
> > > +    __builtin_abort();
> > > +}
> > > --
> > > 2.43.0
> > >

Reply via email to