diff mbox series

[v1] Match: Bugfix .SAT_TRUNC honor types has no mode precision [PR115961]

Message ID 20240717094826.394649-1-pan2.li@intel.com
State New
Headers show
Series [v1] Match: Bugfix .SAT_TRUNC honor types has no mode precision [PR115961] | expand

Commit Message

Li, Pan2 July 17, 2024, 9:48 a.m. UTC
From: Pan Li <pan2.li@intel.com>

The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
when bitfield like below will be recog as .SAT_TRUNC.

struct e
{
  unsigned pre : 12;
  unsigned a : 4;
};

__attribute__((noipa))
void bug (e * v, unsigned def, unsigned use) {
  e & defE = *v;
  defE.a = min_u (use + 1, 0xf);
}

This patch would like to add type_has_mode_precision_p for the
.SAT_TRUNC matching to get rid of this.

The below test suites are passed for this patch:
1. The rv64gcv fully regression tests.
2. The x86 bootstrap tests.
3. The x86 fully regression tests.

	PR target/115961

gcc/ChangeLog:

	* match.pd: Add type_has_mode_precision_p check for .SAT_TRUNC.

gcc/testsuite/ChangeLog:

	* g++.target/i386/pr115961-run-1.C: New test.
	* g++.target/riscv/rvv/base/pr115961-run-1.C: New test.

Signed-off-by: Pan Li <pan2.li@intel.com>
---
 gcc/match.pd                                  |  4 +--
 .../g++.target/i386/pr115961-run-1.C          | 34 +++++++++++++++++++
 .../riscv/rvv/base/pr115961-run-1.C           | 34 +++++++++++++++++++
 3 files changed, 70 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C
 create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C

Comments

Richard Biener July 17, 2024, 11:12 a.m. UTC | #1
On Wed, Jul 17, 2024 at 11:48 AM <pan2.li@intel.com> wrote:
>
> From: Pan Li <pan2.li@intel.com>
>
> The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
> when bitfield like below will be recog as .SAT_TRUNC.
>
> struct e
> {
>   unsigned pre : 12;
>   unsigned a : 4;
> };
>
> __attribute__((noipa))
> void bug (e * v, unsigned def, unsigned use) {
>   e & defE = *v;
>   defE.a = min_u (use + 1, 0xf);
> }
>
> This patch would like to add type_has_mode_precision_p for the
> .SAT_TRUNC matching to get rid of this.
>
> The below test suites are passed for this patch:
> 1. The rv64gcv fully regression tests.
> 2. The x86 bootstrap tests.
> 3. The x86 fully regression tests.

Hmm, rather than restricting the matching the issue is the optab query or
in this case how *_optab_supported_p blindly uses TYPE_MODE without
either asserting the type has mode precision or failing the query in this case.

I think it would be simplest to adjust direct_optab_supported_p
(and convert_optab_supported_p) to reject such operations?  Richard, do
you agree or should callers check this instead?

So, instead of match.pd the check would need to be in vector pattern matching
and SSA math opts.  Or alternatively in internal-fn.cc as laid out above.

Richard.

>         PR target/115961
>
> gcc/ChangeLog:
>
>         * match.pd: Add type_has_mode_precision_p check for .SAT_TRUNC.
>
> gcc/testsuite/ChangeLog:
>
>         * g++.target/i386/pr115961-run-1.C: New test.
>         * g++.target/riscv/rvv/base/pr115961-run-1.C: New test.
>
> Signed-off-by: Pan Li <pan2.li@intel.com>
> ---
>  gcc/match.pd                                  |  4 +--
>  .../g++.target/i386/pr115961-run-1.C          | 34 +++++++++++++++++++
>  .../riscv/rvv/base/pr115961-run-1.C           | 34 +++++++++++++++++++
>  3 files changed, 70 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C
>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 24a0bbead3e..8121ec09f53 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -3240,7 +3240,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>   (bit_ior:c (negate (convert (gt @0 INTEGER_CST@1)))
>     (convert @0))
>   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
> -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
> +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p (type))
>   (with
>    {
>     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
> @@ -3255,7 +3255,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  (match (unsigned_integer_sat_trunc @0)
>   (convert (min @0 INTEGER_CST@1))
>   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
> -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
> +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p (type))
>   (with
>    {
>     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
> diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> new file mode 100644
> index 00000000000..b8c8aef3b17
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> @@ -0,0 +1,34 @@
> +/* PR target/115961 */
> +/* { dg-do run } */
> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> +
> +struct e
> +{
> +  unsigned pre : 12;
> +  unsigned a : 4;
> +};
> +
> +static unsigned min_u (unsigned a, unsigned b)
> +{
> +  return (b < a) ? b : a;
> +}
> +
> +__attribute__((noipa))
> +void bug (e * v, unsigned def, unsigned use) {
> +  e & defE = *v;
> +  defE.a = min_u (use + 1, 0xf);
> +}
> +
> +__attribute__((noipa, optimize(0)))
> +int main(void)
> +{
> +  e v = { 0xded, 3 };
> +
> +  bug(&v, 32, 33);
> +
> +  if (v.a != 0xf)
> +    __builtin_abort ();
> +
> +  return 0;
> +}
> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> new file mode 100644
> index 00000000000..b8c8aef3b17
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> @@ -0,0 +1,34 @@
> +/* PR target/115961 */
> +/* { dg-do run } */
> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> +
> +struct e
> +{
> +  unsigned pre : 12;
> +  unsigned a : 4;
> +};
> +
> +static unsigned min_u (unsigned a, unsigned b)
> +{
> +  return (b < a) ? b : a;
> +}
> +
> +__attribute__((noipa))
> +void bug (e * v, unsigned def, unsigned use) {
> +  e & defE = *v;
> +  defE.a = min_u (use + 1, 0xf);
> +}
> +
> +__attribute__((noipa, optimize(0)))
> +int main(void)
> +{
> +  e v = { 0xded, 3 };
> +
> +  bug(&v, 32, 33);
> +
> +  if (v.a != 0xf)
> +    __builtin_abort ();
> +
> +  return 0;
> +}
> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> --
> 2.34.1
>
Andrew Pinski July 17, 2024, 5:54 p.m. UTC | #2
On Wed, Jul 17, 2024 at 4:13 AM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Wed, Jul 17, 2024 at 11:48 AM <pan2.li@intel.com> wrote:
> >
> > From: Pan Li <pan2.li@intel.com>
> >
> > The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
> > when bitfield like below will be recog as .SAT_TRUNC.
> >
> > struct e
> > {
> >   unsigned pre : 12;
> >   unsigned a : 4;
> > };
> >
> > __attribute__((noipa))
> > void bug (e * v, unsigned def, unsigned use) {
> >   e & defE = *v;
> >   defE.a = min_u (use + 1, 0xf);
> > }
> >
> > This patch would like to add type_has_mode_precision_p for the
> > .SAT_TRUNC matching to get rid of this.
> >
> > The below test suites are passed for this patch:
> > 1. The rv64gcv fully regression tests.
> > 2. The x86 bootstrap tests.
> > 3. The x86 fully regression tests.
>
> Hmm, rather than restricting the matching the issue is the optab query or
> in this case how *_optab_supported_p blindly uses TYPE_MODE without
> either asserting the type has mode precision or failing the query in this case.
>
> I think it would be simplest to adjust direct_optab_supported_p
> (and convert_optab_supported_p) to reject such operations?  Richard, do
> you agree or should callers check this instead?

I was thinking it should be in
direct_optab_supported_p/convert_optab_supported_p/direct_internal_fn_optab
too when I did my initial analysis of the bug report. I tried to see
if there was another use of direct_optab_supported_p where this could
happen but I didn't find one.

Thanks,
Andrew

>
> So, instead of match.pd the check would need to be in vector pattern matching
> and SSA math opts.  Or alternatively in internal-fn.cc as laid out above.
>
> Richard.
>
> >         PR target/115961
> >
> > gcc/ChangeLog:
> >
> >         * match.pd: Add type_has_mode_precision_p check for .SAT_TRUNC.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * g++.target/i386/pr115961-run-1.C: New test.
> >         * g++.target/riscv/rvv/base/pr115961-run-1.C: New test.
> >
> > Signed-off-by: Pan Li <pan2.li@intel.com>
> > ---
> >  gcc/match.pd                                  |  4 +--
> >  .../g++.target/i386/pr115961-run-1.C          | 34 +++++++++++++++++++
> >  .../riscv/rvv/base/pr115961-run-1.C           | 34 +++++++++++++++++++
> >  3 files changed, 70 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C
> >  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 24a0bbead3e..8121ec09f53 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -3240,7 +3240,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >   (bit_ior:c (negate (convert (gt @0 INTEGER_CST@1)))
> >     (convert @0))
> >   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
> > -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
> > +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p (type))
> >   (with
> >    {
> >     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
> > @@ -3255,7 +3255,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >  (match (unsigned_integer_sat_trunc @0)
> >   (convert (min @0 INTEGER_CST@1))
> >   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
> > -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
> > +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p (type))
> >   (with
> >    {
> >     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
> > diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> > new file mode 100644
> > index 00000000000..b8c8aef3b17
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> > @@ -0,0 +1,34 @@
> > +/* PR target/115961 */
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> > +
> > +struct e
> > +{
> > +  unsigned pre : 12;
> > +  unsigned a : 4;
> > +};
> > +
> > +static unsigned min_u (unsigned a, unsigned b)
> > +{
> > +  return (b < a) ? b : a;
> > +}
> > +
> > +__attribute__((noipa))
> > +void bug (e * v, unsigned def, unsigned use) {
> > +  e & defE = *v;
> > +  defE.a = min_u (use + 1, 0xf);
> > +}
> > +
> > +__attribute__((noipa, optimize(0)))
> > +int main(void)
> > +{
> > +  e v = { 0xded, 3 };
> > +
> > +  bug(&v, 32, 33);
> > +
> > +  if (v.a != 0xf)
> > +    __builtin_abort ();
> > +
> > +  return 0;
> > +}
> > +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> > diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> > new file mode 100644
> > index 00000000000..b8c8aef3b17
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> > @@ -0,0 +1,34 @@
> > +/* PR target/115961 */
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> > +
> > +struct e
> > +{
> > +  unsigned pre : 12;
> > +  unsigned a : 4;
> > +};
> > +
> > +static unsigned min_u (unsigned a, unsigned b)
> > +{
> > +  return (b < a) ? b : a;
> > +}
> > +
> > +__attribute__((noipa))
> > +void bug (e * v, unsigned def, unsigned use) {
> > +  e & defE = *v;
> > +  defE.a = min_u (use + 1, 0xf);
> > +}
> > +
> > +__attribute__((noipa, optimize(0)))
> > +int main(void)
> > +{
> > +  e v = { 0xded, 3 };
> > +
> > +  bug(&v, 32, 33);
> > +
> > +  if (v.a != 0xf)
> > +    __builtin_abort ();
> > +
> > +  return 0;
> > +}
> > +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> > --
> > 2.34.1
> >
Richard Sandiford July 17, 2024, 7:55 p.m. UTC | #3
Richard Biener <richard.guenther@gmail.com> writes:
> On Wed, Jul 17, 2024 at 11:48 AM <pan2.li@intel.com> wrote:
>>
>> From: Pan Li <pan2.li@intel.com>
>>
>> The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
>> when bitfield like below will be recog as .SAT_TRUNC.
>>
>> struct e
>> {
>>   unsigned pre : 12;
>>   unsigned a : 4;
>> };
>>
>> __attribute__((noipa))
>> void bug (e * v, unsigned def, unsigned use) {
>>   e & defE = *v;
>>   defE.a = min_u (use + 1, 0xf);
>> }
>>
>> This patch would like to add type_has_mode_precision_p for the
>> .SAT_TRUNC matching to get rid of this.
>>
>> The below test suites are passed for this patch:
>> 1. The rv64gcv fully regression tests.
>> 2. The x86 bootstrap tests.
>> 3. The x86 fully regression tests.
>
> Hmm, rather than restricting the matching the issue is the optab query or
> in this case how *_optab_supported_p blindly uses TYPE_MODE without
> either asserting the type has mode precision or failing the query in this case.
>
> I think it would be simplest to adjust direct_optab_supported_p
> (and convert_optab_supported_p) to reject such operations?  Richard, do
> you agree or should callers check this instead?

Sounds good to me, although I suppose it should go:

bool
direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
				optimization_type opt_type)
{
  // <--- Here
  switch (fn)
    {

    }
}

until we know of a specific case where that's wrong.

Is type_has_mode_precision_p meaningful for all types?

Richard


>
> So, instead of match.pd the check would need to be in vector pattern matching
> and SSA math opts.  Or alternatively in internal-fn.cc as laid out above.
>
> Richard.
>
>>         PR target/115961
>>
>> gcc/ChangeLog:
>>
>>         * match.pd: Add type_has_mode_precision_p check for .SAT_TRUNC.
>>
>> gcc/testsuite/ChangeLog:
>>
>>         * g++.target/i386/pr115961-run-1.C: New test.
>>         * g++.target/riscv/rvv/base/pr115961-run-1.C: New test.
>>
>> Signed-off-by: Pan Li <pan2.li@intel.com>
>> ---
>>  gcc/match.pd                                  |  4 +--
>>  .../g++.target/i386/pr115961-run-1.C          | 34 +++++++++++++++++++
>>  .../riscv/rvv/base/pr115961-run-1.C           | 34 +++++++++++++++++++
>>  3 files changed, 70 insertions(+), 2 deletions(-)
>>  create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C
>>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
>>
>> diff --git a/gcc/match.pd b/gcc/match.pd
>> index 24a0bbead3e..8121ec09f53 100644
>> --- a/gcc/match.pd
>> +++ b/gcc/match.pd
>> @@ -3240,7 +3240,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>>   (bit_ior:c (negate (convert (gt @0 INTEGER_CST@1)))
>>     (convert @0))
>>   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
>> -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
>> +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p (type))
>>   (with
>>    {
>>     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
>> @@ -3255,7 +3255,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>>  (match (unsigned_integer_sat_trunc @0)
>>   (convert (min @0 INTEGER_CST@1))
>>   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
>> -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
>> +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p (type))
>>   (with
>>    {
>>     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
>> diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
>> new file mode 100644
>> index 00000000000..b8c8aef3b17
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
>> @@ -0,0 +1,34 @@
>> +/* PR target/115961 */
>> +/* { dg-do run } */
>> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
>> +
>> +struct e
>> +{
>> +  unsigned pre : 12;
>> +  unsigned a : 4;
>> +};
>> +
>> +static unsigned min_u (unsigned a, unsigned b)
>> +{
>> +  return (b < a) ? b : a;
>> +}
>> +
>> +__attribute__((noipa))
>> +void bug (e * v, unsigned def, unsigned use) {
>> +  e & defE = *v;
>> +  defE.a = min_u (use + 1, 0xf);
>> +}
>> +
>> +__attribute__((noipa, optimize(0)))
>> +int main(void)
>> +{
>> +  e v = { 0xded, 3 };
>> +
>> +  bug(&v, 32, 33);
>> +
>> +  if (v.a != 0xf)
>> +    __builtin_abort ();
>> +
>> +  return 0;
>> +}
>> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
>> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
>> new file mode 100644
>> index 00000000000..b8c8aef3b17
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
>> @@ -0,0 +1,34 @@
>> +/* PR target/115961 */
>> +/* { dg-do run } */
>> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
>> +
>> +struct e
>> +{
>> +  unsigned pre : 12;
>> +  unsigned a : 4;
>> +};
>> +
>> +static unsigned min_u (unsigned a, unsigned b)
>> +{
>> +  return (b < a) ? b : a;
>> +}
>> +
>> +__attribute__((noipa))
>> +void bug (e * v, unsigned def, unsigned use) {
>> +  e & defE = *v;
>> +  defE.a = min_u (use + 1, 0xf);
>> +}
>> +
>> +__attribute__((noipa, optimize(0)))
>> +int main(void)
>> +{
>> +  e v = { 0xded, 3 };
>> +
>> +  bug(&v, 32, 33);
>> +
>> +  if (v.a != 0xf)
>> +    __builtin_abort ();
>> +
>> +  return 0;
>> +}
>> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
>> --
>> 2.34.1
>>
Tamar Christina July 17, 2024, 8:02 p.m. UTC | #4
> -----Original Message-----
> From: Richard Sandiford <richard.sandiford@arm.com>
> Sent: Wednesday, July 17, 2024 8:55 PM
> To: Richard Biener <richard.guenther@gmail.com>
> Cc: pan2.li@intel.com; gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai;
> kito.cheng@gmail.com; Tamar Christina <Tamar.Christina@arm.com>;
> jeffreyalaw@gmail.com; rdapp.gcc@gmail.com; hongtao.liu@intel.com
> Subject: Re: [PATCH v1] Match: Bugfix .SAT_TRUNC honor types has no mode
> precision [PR115961]
> 
> Richard Biener <richard.guenther@gmail.com> writes:
> > On Wed, Jul 17, 2024 at 11:48 AM <pan2.li@intel.com> wrote:
> >>
> >> From: Pan Li <pan2.li@intel.com>
> >>
> >> The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
> >> when bitfield like below will be recog as .SAT_TRUNC.
> >>
> >> struct e
> >> {
> >>   unsigned pre : 12;
> >>   unsigned a : 4;
> >> };
> >>
> >> __attribute__((noipa))
> >> void bug (e * v, unsigned def, unsigned use) {
> >>   e & defE = *v;
> >>   defE.a = min_u (use + 1, 0xf);
> >> }
> >>
> >> This patch would like to add type_has_mode_precision_p for the
> >> .SAT_TRUNC matching to get rid of this.
> >>
> >> The below test suites are passed for this patch:
> >> 1. The rv64gcv fully regression tests.
> >> 2. The x86 bootstrap tests.
> >> 3. The x86 fully regression tests.
> >
> > Hmm, rather than restricting the matching the issue is the optab query or
> > in this case how *_optab_supported_p blindly uses TYPE_MODE without
> > either asserting the type has mode precision or failing the query in this case.
> >
> > I think it would be simplest to adjust direct_optab_supported_p
> > (and convert_optab_supported_p) to reject such operations?  Richard, do
> > you agree or should callers check this instead?
> 
> Sounds good to me, although I suppose it should go:
> 
> bool
> direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
> 				optimization_type opt_type)
> {
>   // <--- Here
>   switch (fn)
>     {
> 
>     }
> }
> 
> until we know of a specific case where that's wrong.
> 
> Is type_has_mode_precision_p meaningful for all types?
> 

I was wondering about that, wouldn't VECTOR_BOOLEAN_TYPE_P types fail?
e.g. on AVX where the type precision is 1 but the mode precision QImode?

Unless I misunderstood the predicate.

Regards,
Tamar

> Richard
> 
> 
> >
> > So, instead of match.pd the check would need to be in vector pattern matching
> > and SSA math opts.  Or alternatively in internal-fn.cc as laid out above.
> >
> > Richard.
> >
> >>         PR target/115961
> >>
> >> gcc/ChangeLog:
> >>
> >>         * match.pd: Add type_has_mode_precision_p check for .SAT_TRUNC.
> >>
> >> gcc/testsuite/ChangeLog:
> >>
> >>         * g++.target/i386/pr115961-run-1.C: New test.
> >>         * g++.target/riscv/rvv/base/pr115961-run-1.C: New test.
> >>
> >> Signed-off-by: Pan Li <pan2.li@intel.com>
> >> ---
> >>  gcc/match.pd                                  |  4 +--
> >>  .../g++.target/i386/pr115961-run-1.C          | 34 +++++++++++++++++++
> >>  .../riscv/rvv/base/pr115961-run-1.C           | 34 +++++++++++++++++++
> >>  3 files changed, 70 insertions(+), 2 deletions(-)
> >>  create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C
> >>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-
> 1.C
> >>
> >> diff --git a/gcc/match.pd b/gcc/match.pd
> >> index 24a0bbead3e..8121ec09f53 100644
> >> --- a/gcc/match.pd
> >> +++ b/gcc/match.pd
> >> @@ -3240,7 +3240,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >>   (bit_ior:c (negate (convert (gt @0 INTEGER_CST@1)))
> >>     (convert @0))
> >>   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
> >> -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
> >> +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p
> (type))
> >>   (with
> >>    {
> >>     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
> >> @@ -3255,7 +3255,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >>  (match (unsigned_integer_sat_trunc @0)
> >>   (convert (min @0 INTEGER_CST@1))
> >>   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
> >> -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
> >> +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p
> (type))
> >>   (with
> >>    {
> >>     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
> >> diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> >> new file mode 100644
> >> index 00000000000..b8c8aef3b17
> >> --- /dev/null
> >> +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> >> @@ -0,0 +1,34 @@
> >> +/* PR target/115961 */
> >> +/* { dg-do run } */
> >> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> >> +
> >> +struct e
> >> +{
> >> +  unsigned pre : 12;
> >> +  unsigned a : 4;
> >> +};
> >> +
> >> +static unsigned min_u (unsigned a, unsigned b)
> >> +{
> >> +  return (b < a) ? b : a;
> >> +}
> >> +
> >> +__attribute__((noipa))
> >> +void bug (e * v, unsigned def, unsigned use) {
> >> +  e & defE = *v;
> >> +  defE.a = min_u (use + 1, 0xf);
> >> +}
> >> +
> >> +__attribute__((noipa, optimize(0)))
> >> +int main(void)
> >> +{
> >> +  e v = { 0xded, 3 };
> >> +
> >> +  bug(&v, 32, 33);
> >> +
> >> +  if (v.a != 0xf)
> >> +    __builtin_abort ();
> >> +
> >> +  return 0;
> >> +}
> >> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> >> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> >> new file mode 100644
> >> index 00000000000..b8c8aef3b17
> >> --- /dev/null
> >> +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> >> @@ -0,0 +1,34 @@
> >> +/* PR target/115961 */
> >> +/* { dg-do run } */
> >> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> >> +
> >> +struct e
> >> +{
> >> +  unsigned pre : 12;
> >> +  unsigned a : 4;
> >> +};
> >> +
> >> +static unsigned min_u (unsigned a, unsigned b)
> >> +{
> >> +  return (b < a) ? b : a;
> >> +}
> >> +
> >> +__attribute__((noipa))
> >> +void bug (e * v, unsigned def, unsigned use) {
> >> +  e & defE = *v;
> >> +  defE.a = min_u (use + 1, 0xf);
> >> +}
> >> +
> >> +__attribute__((noipa, optimize(0)))
> >> +int main(void)
> >> +{
> >> +  e v = { 0xded, 3 };
> >> +
> >> +  bug(&v, 32, 33);
> >> +
> >> +  if (v.a != 0xf)
> >> +    __builtin_abort ();
> >> +
> >> +  return 0;
> >> +}
> >> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> >> --
> >> 2.34.1
> >>
Andrew Pinski July 17, 2024, 9:03 p.m. UTC | #5
On Wed, Jul 17, 2024 at 1:03 PM Tamar Christina <Tamar.Christina@arm.com> wrote:
>
> > -----Original Message-----
> > From: Richard Sandiford <richard.sandiford@arm.com>
> > Sent: Wednesday, July 17, 2024 8:55 PM
> > To: Richard Biener <richard.guenther@gmail.com>
> > Cc: pan2.li@intel.com; gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai;
> > kito.cheng@gmail.com; Tamar Christina <Tamar.Christina@arm.com>;
> > jeffreyalaw@gmail.com; rdapp.gcc@gmail.com; hongtao.liu@intel.com
> > Subject: Re: [PATCH v1] Match: Bugfix .SAT_TRUNC honor types has no mode
> > precision [PR115961]
> >
> > Richard Biener <richard.guenther@gmail.com> writes:
> > > On Wed, Jul 17, 2024 at 11:48 AM <pan2.li@intel.com> wrote:
> > >>
> > >> From: Pan Li <pan2.li@intel.com>
> > >>
> > >> The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
> > >> when bitfield like below will be recog as .SAT_TRUNC.
> > >>
> > >> struct e
> > >> {
> > >>   unsigned pre : 12;
> > >>   unsigned a : 4;
> > >> };
> > >>
> > >> __attribute__((noipa))
> > >> void bug (e * v, unsigned def, unsigned use) {
> > >>   e & defE = *v;
> > >>   defE.a = min_u (use + 1, 0xf);
> > >> }
> > >>
> > >> This patch would like to add type_has_mode_precision_p for the
> > >> .SAT_TRUNC matching to get rid of this.
> > >>
> > >> The below test suites are passed for this patch:
> > >> 1. The rv64gcv fully regression tests.
> > >> 2. The x86 bootstrap tests.
> > >> 3. The x86 fully regression tests.
> > >
> > > Hmm, rather than restricting the matching the issue is the optab query or
> > > in this case how *_optab_supported_p blindly uses TYPE_MODE without
> > > either asserting the type has mode precision or failing the query in this case.
> > >
> > > I think it would be simplest to adjust direct_optab_supported_p
> > > (and convert_optab_supported_p) to reject such operations?  Richard, do
> > > you agree or should callers check this instead?
> >
> > Sounds good to me, although I suppose it should go:
> >
> > bool
> > direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
> >                               optimization_type opt_type)
> > {
> >   // <--- Here
> >   switch (fn)
> >     {
> >
> >     }
> > }
> >
> > until we know of a specific case where that's wrong.
> >
> > Is type_has_mode_precision_p meaningful for all types?
> >
>
> I was wondering about that, wouldn't VECTOR_BOOLEAN_TYPE_P types fail?
> e.g. on AVX where the type precision is 1 but the mode precision QImode?
>
> Unless I misunderstood the predicate.

So type_has_mode_precision_p only works with scalar integral types
(maybe scalar real types too) since it uses TYPE_PRECISION directly
and not element_precision (the precision field is overloaded for
vectors for the number of elements and TYPE_PRECISION on a vector type
will cause an ICE since r14-2150-gfe48f2651334bc).
So I suspect you need to check !VECTOR_TYPE_P (type) before calling
type_has_mode_precision_p .


Thanks,
Andrew Pinski

>
> Regards,
> Tamar
>
> > Richard
> >
> >
> > >
> > > So, instead of match.pd the check would need to be in vector pattern matching
> > > and SSA math opts.  Or alternatively in internal-fn.cc as laid out above.
> > >
> > > Richard.
> > >
> > >>         PR target/115961
> > >>
> > >> gcc/ChangeLog:
> > >>
> > >>         * match.pd: Add type_has_mode_precision_p check for .SAT_TRUNC.
> > >>
> > >> gcc/testsuite/ChangeLog:
> > >>
> > >>         * g++.target/i386/pr115961-run-1.C: New test.
> > >>         * g++.target/riscv/rvv/base/pr115961-run-1.C: New test.
> > >>
> > >> Signed-off-by: Pan Li <pan2.li@intel.com>
> > >> ---
> > >>  gcc/match.pd                                  |  4 +--
> > >>  .../g++.target/i386/pr115961-run-1.C          | 34 +++++++++++++++++++
> > >>  .../riscv/rvv/base/pr115961-run-1.C           | 34 +++++++++++++++++++
> > >>  3 files changed, 70 insertions(+), 2 deletions(-)
> > >>  create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C
> > >>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-
> > 1.C
> > >>
> > >> diff --git a/gcc/match.pd b/gcc/match.pd
> > >> index 24a0bbead3e..8121ec09f53 100644
> > >> --- a/gcc/match.pd
> > >> +++ b/gcc/match.pd
> > >> @@ -3240,7 +3240,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > >>   (bit_ior:c (negate (convert (gt @0 INTEGER_CST@1)))
> > >>     (convert @0))
> > >>   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
> > >> -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
> > >> +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p
> > (type))
> > >>   (with
> > >>    {
> > >>     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
> > >> @@ -3255,7 +3255,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > >>  (match (unsigned_integer_sat_trunc @0)
> > >>   (convert (min @0 INTEGER_CST@1))
> > >>   (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
> > >> -      && TYPE_UNSIGNED (TREE_TYPE (@0)))
> > >> +      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p
> > (type))
> > >>   (with
> > >>    {
> > >>     unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
> > >> diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> > b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> > >> new file mode 100644
> > >> index 00000000000..b8c8aef3b17
> > >> --- /dev/null
> > >> +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
> > >> @@ -0,0 +1,34 @@
> > >> +/* PR target/115961 */
> > >> +/* { dg-do run } */
> > >> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> > >> +
> > >> +struct e
> > >> +{
> > >> +  unsigned pre : 12;
> > >> +  unsigned a : 4;
> > >> +};
> > >> +
> > >> +static unsigned min_u (unsigned a, unsigned b)
> > >> +{
> > >> +  return (b < a) ? b : a;
> > >> +}
> > >> +
> > >> +__attribute__((noipa))
> > >> +void bug (e * v, unsigned def, unsigned use) {
> > >> +  e & defE = *v;
> > >> +  defE.a = min_u (use + 1, 0xf);
> > >> +}
> > >> +
> > >> +__attribute__((noipa, optimize(0)))
> > >> +int main(void)
> > >> +{
> > >> +  e v = { 0xded, 3 };
> > >> +
> > >> +  bug(&v, 32, 33);
> > >> +
> > >> +  if (v.a != 0xf)
> > >> +    __builtin_abort ();
> > >> +
> > >> +  return 0;
> > >> +}
> > >> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> > >> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> > b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> > >> new file mode 100644
> > >> index 00000000000..b8c8aef3b17
> > >> --- /dev/null
> > >> +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
> > >> @@ -0,0 +1,34 @@
> > >> +/* PR target/115961 */
> > >> +/* { dg-do run } */
> > >> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */
> > >> +
> > >> +struct e
> > >> +{
> > >> +  unsigned pre : 12;
> > >> +  unsigned a : 4;
> > >> +};
> > >> +
> > >> +static unsigned min_u (unsigned a, unsigned b)
> > >> +{
> > >> +  return (b < a) ? b : a;
> > >> +}
> > >> +
> > >> +__attribute__((noipa))
> > >> +void bug (e * v, unsigned def, unsigned use) {
> > >> +  e & defE = *v;
> > >> +  defE.a = min_u (use + 1, 0xf);
> > >> +}
> > >> +
> > >> +__attribute__((noipa, optimize(0)))
> > >> +int main(void)
> > >> +{
> > >> +  e v = { 0xded, 3 };
> > >> +
> > >> +  bug(&v, 32, 33);
> > >> +
> > >> +  if (v.a != 0xf)
> > >> +    __builtin_abort ();
> > >> +
> > >> +  return 0;
> > >> +}
> > >> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
> > >> --
> > >> 2.34.1
> > >>
Richard Sandiford July 17, 2024, 9:13 p.m. UTC | #6
Andrew Pinski <pinskia@gmail.com> writes:
> On Wed, Jul 17, 2024 at 1:03 PM Tamar Christina <Tamar.Christina@arm.com> wrote:
>>
>> > -----Original Message-----
>> > From: Richard Sandiford <richard.sandiford@arm.com>
>> > Sent: Wednesday, July 17, 2024 8:55 PM
>> > To: Richard Biener <richard.guenther@gmail.com>
>> > Cc: pan2.li@intel.com; gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai;
>> > kito.cheng@gmail.com; Tamar Christina <Tamar.Christina@arm.com>;
>> > jeffreyalaw@gmail.com; rdapp.gcc@gmail.com; hongtao.liu@intel.com
>> > Subject: Re: [PATCH v1] Match: Bugfix .SAT_TRUNC honor types has no mode
>> > precision [PR115961]
>> >
>> > Richard Biener <richard.guenther@gmail.com> writes:
>> > > On Wed, Jul 17, 2024 at 11:48 AM <pan2.li@intel.com> wrote:
>> > >>
>> > >> From: Pan Li <pan2.li@intel.com>
>> > >>
>> > >> The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
>> > >> when bitfield like below will be recog as .SAT_TRUNC.
>> > >>
>> > >> struct e
>> > >> {
>> > >>   unsigned pre : 12;
>> > >>   unsigned a : 4;
>> > >> };
>> > >>
>> > >> __attribute__((noipa))
>> > >> void bug (e * v, unsigned def, unsigned use) {
>> > >>   e & defE = *v;
>> > >>   defE.a = min_u (use + 1, 0xf);
>> > >> }
>> > >>
>> > >> This patch would like to add type_has_mode_precision_p for the
>> > >> .SAT_TRUNC matching to get rid of this.
>> > >>
>> > >> The below test suites are passed for this patch:
>> > >> 1. The rv64gcv fully regression tests.
>> > >> 2. The x86 bootstrap tests.
>> > >> 3. The x86 fully regression tests.
>> > >
>> > > Hmm, rather than restricting the matching the issue is the optab query or
>> > > in this case how *_optab_supported_p blindly uses TYPE_MODE without
>> > > either asserting the type has mode precision or failing the query in this case.
>> > >
>> > > I think it would be simplest to adjust direct_optab_supported_p
>> > > (and convert_optab_supported_p) to reject such operations?  Richard, do
>> > > you agree or should callers check this instead?
>> >
>> > Sounds good to me, although I suppose it should go:
>> >
>> > bool
>> > direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
>> >                               optimization_type opt_type)
>> > {
>> >   // <--- Here
>> >   switch (fn)
>> >     {
>> >
>> >     }
>> > }
>> >
>> > until we know of a specific case where that's wrong.
>> >
>> > Is type_has_mode_precision_p meaningful for all types?
>> >
>>
>> I was wondering about that, wouldn't VECTOR_BOOLEAN_TYPE_P types fail?
>> e.g. on AVX where the type precision is 1 but the mode precision QImode?
>>
>> Unless I misunderstood the predicate.
>
> So type_has_mode_precision_p only works with scalar integral types
> (maybe scalar real types too) since it uses TYPE_PRECISION directly
> and not element_precision (the precision field is overloaded for
> vectors for the number of elements and TYPE_PRECISION on a vector type
> will cause an ICE since r14-2150-gfe48f2651334bc).
> So I suspect you need to check !VECTOR_TYPE_P (type) before calling
> type_has_mode_precision_p .

I think for VECTOR_TYPE_P it would be worth checking VECTOR_MODE_P instead,
if we're not requiring callers to check this kind of thing.

So something like:

bool
mode_describes_type_p (const_tree type)
{
  if (VECTOR_TYPE_P (type))
    return VECTOR_MODE_P (TREE_TYPE (type));

  if (INTEGRAL_TYPE_P (type))
    return type_has_mode_precision_p (type);

  if (SCALAR_FLOAT_TYPE_P (type))
    return true;

  return false;
}

?  Possibly also with complex handling if we need that.

Richard
Li, Pan2 July 18, 2024, 1:21 a.m. UTC | #7
Thanks all, will have a try in v2.

Pan

-----Original Message-----
From: Richard Sandiford <richard.sandiford@arm.com> 
Sent: Thursday, July 18, 2024 5:14 AM
To: Andrew Pinski <pinskia@gmail.com>
Cc: Tamar Christina <Tamar.Christina@arm.com>; Richard Biener <richard.guenther@gmail.com>; Li, Pan2 <pan2.li@intel.com>; gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai; kito.cheng@gmail.com; jeffreyalaw@gmail.com; rdapp.gcc@gmail.com; Liu, Hongtao <hongtao.liu@intel.com>
Subject: Re: [PATCH v1] Match: Bugfix .SAT_TRUNC honor types has no mode precision [PR115961]

Andrew Pinski <pinskia@gmail.com> writes:
> On Wed, Jul 17, 2024 at 1:03 PM Tamar Christina <Tamar.Christina@arm.com> wrote:
>>
>> > -----Original Message-----
>> > From: Richard Sandiford <richard.sandiford@arm.com>
>> > Sent: Wednesday, July 17, 2024 8:55 PM
>> > To: Richard Biener <richard.guenther@gmail.com>
>> > Cc: pan2.li@intel.com; gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai;
>> > kito.cheng@gmail.com; Tamar Christina <Tamar.Christina@arm.com>;
>> > jeffreyalaw@gmail.com; rdapp.gcc@gmail.com; hongtao.liu@intel.com
>> > Subject: Re: [PATCH v1] Match: Bugfix .SAT_TRUNC honor types has no mode
>> > precision [PR115961]
>> >
>> > Richard Biener <richard.guenther@gmail.com> writes:
>> > > On Wed, Jul 17, 2024 at 11:48 AM <pan2.li@intel.com> wrote:
>> > >>
>> > >> From: Pan Li <pan2.li@intel.com>
>> > >>
>> > >> The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
>> > >> when bitfield like below will be recog as .SAT_TRUNC.
>> > >>
>> > >> struct e
>> > >> {
>> > >>   unsigned pre : 12;
>> > >>   unsigned a : 4;
>> > >> };
>> > >>
>> > >> __attribute__((noipa))
>> > >> void bug (e * v, unsigned def, unsigned use) {
>> > >>   e & defE = *v;
>> > >>   defE.a = min_u (use + 1, 0xf);
>> > >> }
>> > >>
>> > >> This patch would like to add type_has_mode_precision_p for the
>> > >> .SAT_TRUNC matching to get rid of this.
>> > >>
>> > >> The below test suites are passed for this patch:
>> > >> 1. The rv64gcv fully regression tests.
>> > >> 2. The x86 bootstrap tests.
>> > >> 3. The x86 fully regression tests.
>> > >
>> > > Hmm, rather than restricting the matching the issue is the optab query or
>> > > in this case how *_optab_supported_p blindly uses TYPE_MODE without
>> > > either asserting the type has mode precision or failing the query in this case.
>> > >
>> > > I think it would be simplest to adjust direct_optab_supported_p
>> > > (and convert_optab_supported_p) to reject such operations?  Richard, do
>> > > you agree or should callers check this instead?
>> >
>> > Sounds good to me, although I suppose it should go:
>> >
>> > bool
>> > direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
>> >                               optimization_type opt_type)
>> > {
>> >   // <--- Here
>> >   switch (fn)
>> >     {
>> >
>> >     }
>> > }
>> >
>> > until we know of a specific case where that's wrong.
>> >
>> > Is type_has_mode_precision_p meaningful for all types?
>> >
>>
>> I was wondering about that, wouldn't VECTOR_BOOLEAN_TYPE_P types fail?
>> e.g. on AVX where the type precision is 1 but the mode precision QImode?
>>
>> Unless I misunderstood the predicate.
>
> So type_has_mode_precision_p only works with scalar integral types
> (maybe scalar real types too) since it uses TYPE_PRECISION directly
> and not element_precision (the precision field is overloaded for
> vectors for the number of elements and TYPE_PRECISION on a vector type
> will cause an ICE since r14-2150-gfe48f2651334bc).
> So I suspect you need to check !VECTOR_TYPE_P (type) before calling
> type_has_mode_precision_p .

I think for VECTOR_TYPE_P it would be worth checking VECTOR_MODE_P instead,
if we're not requiring callers to check this kind of thing.

So something like:

bool
mode_describes_type_p (const_tree type)
{
  if (VECTOR_TYPE_P (type))
    return VECTOR_MODE_P (TREE_TYPE (type));

  if (INTEGRAL_TYPE_P (type))
    return type_has_mode_precision_p (type);

  if (SCALAR_FLOAT_TYPE_P (type))
    return true;

  return false;
}

?  Possibly also with complex handling if we need that.

Richard
Richard Biener July 18, 2024, 5:44 a.m. UTC | #8
> Am 17.07.2024 um 23:13 schrieb Richard Sandiford <richard.sandiford@arm.com>:
> 
> Andrew Pinski <pinskia@gmail.com> writes:
>>> On Wed, Jul 17, 2024 at 1:03 PM Tamar Christina <Tamar.Christina@arm.com> wrote:
>>> 
>>>> -----Original Message-----
>>>> From: Richard Sandiford <richard.sandiford@arm.com>
>>>> Sent: Wednesday, July 17, 2024 8:55 PM
>>>> To: Richard Biener <richard.guenther@gmail.com>
>>>> Cc: pan2.li@intel.com; gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai;
>>>> kito.cheng@gmail.com; Tamar Christina <Tamar.Christina@arm.com>;
>>>> jeffreyalaw@gmail.com; rdapp.gcc@gmail.com; hongtao.liu@intel.com
>>>> Subject: Re: [PATCH v1] Match: Bugfix .SAT_TRUNC honor types has no mode
>>>> precision [PR115961]
>>>> 
>>>> Richard Biener <richard.guenther@gmail.com> writes:
>>>>> On Wed, Jul 17, 2024 at 11:48 AM <pan2.li@intel.com> wrote:
>>>>>> 
>>>>>> From: Pan Li <pan2.li@intel.com>
>>>>>> 
>>>>>> The .SAT_TRUNC matching doesn't check the type has mode precision.  Thus
>>>>>> when bitfield like below will be recog as .SAT_TRUNC.
>>>>>> 
>>>>>> struct e
>>>>>> {
>>>>>>  unsigned pre : 12;
>>>>>>  unsigned a : 4;
>>>>>> };
>>>>>> 
>>>>>> __attribute__((noipa))
>>>>>> void bug (e * v, unsigned def, unsigned use) {
>>>>>>  e & defE = *v;
>>>>>>  defE.a = min_u (use + 1, 0xf);
>>>>>> }
>>>>>> 
>>>>>> This patch would like to add type_has_mode_precision_p for the
>>>>>> .SAT_TRUNC matching to get rid of this.
>>>>>> 
>>>>>> The below test suites are passed for this patch:
>>>>>> 1. The rv64gcv fully regression tests.
>>>>>> 2. The x86 bootstrap tests.
>>>>>> 3. The x86 fully regression tests.
>>>>> 
>>>>> Hmm, rather than restricting the matching the issue is the optab query or
>>>>> in this case how *_optab_supported_p blindly uses TYPE_MODE without
>>>>> either asserting the type has mode precision or failing the query in this case.
>>>>> 
>>>>> I think it would be simplest to adjust direct_optab_supported_p
>>>>> (and convert_optab_supported_p) to reject such operations?  Richard, do
>>>>> you agree or should callers check this instead?
>>>> 
>>>> Sounds good to me, although I suppose it should go:
>>>> 
>>>> bool
>>>> direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
>>>>                              optimization_type opt_type)
>>>> {
>>>>  // <--- Here
>>>>  switch (fn)
>>>>    {
>>>> 
>>>>    }
>>>> }
>>>> 
>>>> until we know of a specific case where that's wrong.
>>>> 
>>>> Is type_has_mode_precision_p meaningful for all types?
>>>> 
>>> 
>>> I was wondering about that, wouldn't VECTOR_BOOLEAN_TYPE_P types fail?
>>> e.g. on AVX where the type precision is 1 but the mode precision QImode?
>>> 
>>> Unless I misunderstood the predicate.
>> 
>> So type_has_mode_precision_p only works with scalar integral types
>> (maybe scalar real types too) since it uses TYPE_PRECISION directly
>> and not element_precision (the precision field is overloaded for
>> vectors for the number of elements and TYPE_PRECISION on a vector type
>> will cause an ICE since r14-2150-gfe48f2651334bc).
>> So I suspect you need to check !VECTOR_TYPE_P (type) before calling
>> type_has_mode_precision_p .
> 
> I think for VECTOR_TYPE_P it would be worth checking VECTOR_MODE_P instead,
> if we're not requiring callers to check this kind of thing.
> 
> So something like:
> 
> bool
> mode_describes_type_p (const_tree type)
> {
>  if (VECTOR_TYPE_P (type))
>    return VECTOR_MODE_P (TREE_TYPE (type));

That’s a good point and another mistake that keeps popping up.  I hope the generic vector support passes in a scalar type when checking for support on the underlying integer mode…

> 
>  if (INTEGRAL_TYPE_P (type))
>    return type_has_mode_precision_p (type);
> 
>  if (SCALAR_FLOAT_TYPE_P (type))
>    return true;
> 
>  return false;
> }
> 
> ?  Possibly also with complex handling if we need that.
> 
> Richard
diff mbox series

Patch

diff --git a/gcc/match.pd b/gcc/match.pd
index 24a0bbead3e..8121ec09f53 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3240,7 +3240,7 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (bit_ior:c (negate (convert (gt @0 INTEGER_CST@1)))
    (convert @0))
  (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
-      && TYPE_UNSIGNED (TREE_TYPE (@0)))
+      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p (type))
  (with
   {
    unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
@@ -3255,7 +3255,7 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (match (unsigned_integer_sat_trunc @0)
  (convert (min @0 INTEGER_CST@1))
  (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
-      && TYPE_UNSIGNED (TREE_TYPE (@0)))
+      && TYPE_UNSIGNED (TREE_TYPE (@0)) && type_has_mode_precision_p (type))
  (with
   {
    unsigned itype_precision = TYPE_PRECISION (TREE_TYPE (@0));
diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
new file mode 100644
index 00000000000..b8c8aef3b17
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C
@@ -0,0 +1,34 @@ 
+/* PR target/115961 */
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-rtl-expand-details" } */
+
+struct e
+{
+  unsigned pre : 12;
+  unsigned a : 4;
+};
+
+static unsigned min_u (unsigned a, unsigned b)
+{
+  return (b < a) ? b : a;
+}
+
+__attribute__((noipa))
+void bug (e * v, unsigned def, unsigned use) {
+  e & defE = *v;
+  defE.a = min_u (use + 1, 0xf);
+}
+
+__attribute__((noipa, optimize(0)))
+int main(void)
+{
+  e v = { 0xded, 3 };
+
+  bug(&v, 32, 33);
+
+  if (v.a != 0xf)
+    __builtin_abort ();
+
+  return 0;
+}
+/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */
diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
new file mode 100644
index 00000000000..b8c8aef3b17
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C
@@ -0,0 +1,34 @@ 
+/* PR target/115961 */
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-rtl-expand-details" } */
+
+struct e
+{
+  unsigned pre : 12;
+  unsigned a : 4;
+};
+
+static unsigned min_u (unsigned a, unsigned b)
+{
+  return (b < a) ? b : a;
+}
+
+__attribute__((noipa))
+void bug (e * v, unsigned def, unsigned use) {
+  e & defE = *v;
+  defE.a = min_u (use + 1, 0xf);
+}
+
+__attribute__((noipa, optimize(0)))
+int main(void)
+{
+  e v = { 0xded, 3 };
+
+  bug(&v, 32, 33);
+
+  if (v.a != 0xf)
+    __builtin_abort ();
+
+  return 0;
+}
+/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */