diff mbox

Simplify (convert)(X op const) -> (convert)X op (convert)const by match&simplify

Message ID alpine.DEB.2.20.1610112312310.1815@laptop-mg.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse Oct. 11, 2016, 9:34 p.m. UTC
On Tue, 11 Oct 2016, Bin Cheng wrote:

> We missed folding (convert)(X op const) -> (convert)X op (convert)const for unsigned narrowing because of reason reported at https://gcc.gnu.org/ml/gcc/2016-07/msg00126.html
> This patch fixes the issue by adding new match&simplify pattern, it also adds a test case.  This is the prerequisite patch for next patch adding new vectorization pattern.

Some technical comments below. I am sure Jeff and/or Richi will have more 
to say on the approach. I am a bit surprised to see it as adding a new 
transformation, instead of moving an old one.

+/* (convert (X op C)) -> ((convert)X op (convert)C) if it is narrowing
+   conversion and both types wrap when overflow.  */
+(for op (plus minus)
+  (simplify

We used to indent by a single space in this file, but I see that other 
transforms have made it in with double spacing, so I guess it doesn't 
matter.

+    (convert (op @0 @1))
+    (if (INTEGRAL_TYPE_P (type)
+	 && TYPE_OVERFLOW_WRAPS (type)
+	 && TREE_CODE (@1) == INTEGER_CST

You can write (convert (op @0 INTEGER_CST@1)) and skip this line.

+	 && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+	 && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))

This seems quite restrictive, TYPE_OVERFLOW_UNDEFINED should also be fine 
for this type. I guess you are trying to avoid saturating / trapping 
types?

+	 && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0)))
+     (op (convert @0) (convert @1)))))
+
  /* If we have a narrowing conversion to an integral type that is fed by a
     BIT_AND_EXPR, we might be able to remove the BIT_AND_EXPR if it merely
     masks off bits outside the final type (and nothing else).  */

As I understand it, C says that s is promoted to int and added to 65530, 
but int is not TYPE_OVERFLOW_WRAPS so your transformation doesn't apply 
(the test already passes without your patch). It is better to write tests 
for the gimple version of transformations, i.e. don't write everything as 
a single expression, use intermediate variables.

Comments

Richard Biener Oct. 12, 2016, 8:48 a.m. UTC | #1
On Tue, Oct 11, 2016 at 11:34 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> On Tue, 11 Oct 2016, Bin Cheng wrote:
>
>> We missed folding (convert)(X op const) -> (convert)X op (convert)const
>> for unsigned narrowing because of reason reported at
>> https://gcc.gnu.org/ml/gcc/2016-07/msg00126.html
>> This patch fixes the issue by adding new match&simplify pattern, it also
>> adds a test case.  This is the prerequisite patch for next patch adding new
>> vectorization pattern.
>
>
> Some technical comments below. I am sure Jeff and/or Richi will have more to
> say on the approach. I am a bit surprised to see it as adding a new
> transformation, instead of moving an old one.

The "old one" would be c-family/c-common.c:shorten_binary_op.  It's generally
prefered to move stuff, preserving semantics.

We do have a similar transform for MULT_EXPR in fold-const.c which also
applies to non-constant 2nd operand (likewise for shorten_binary_op).
The general issue with these "narrowings" is that it loses overflow information
if the original op was carried out in a TYPE_OVERFLOW_UNDEFINED type.

There is also already a bunch of similar match.pd patterns here:

/* Narrowing of arithmetic and logical operations.

   These are conceptually similar to the transformations performed for
   the C/C++ front-ends by shorten_binary_op and shorten_compare.  Long
   term we want to move all that code out of the front-ends into here.  */

/* If we have a narrowing conversion of an arithmetic operation where
   both operands are widening conversions from the same type as the outer
   narrowing conversion.  Then convert the innermost operands to a suitable
   unsigned type (to avoid introducing undefined behavior), perform the
   operation and convert the result to the desired type.  */
(for op (plus minus)
  (simplify
    (convert (op:s (convert@2 @0) (convert@3 @1)))
...

so it might be possible to amend these or at least move your pattern next
to those.

> +/* (convert (X op C)) -> ((convert)X op (convert)C) if it is narrowing
> +   conversion and both types wrap when overflow.  */
> +(for op (plus minus)
> +  (simplify
>
> We used to indent by a single space in this file, but I see that other
> transforms have made it in with double spacing, so I guess it doesn't
> matter.
>
> +    (convert (op @0 @1))
> +    (if (INTEGRAL_TYPE_P (type)
> +        && TYPE_OVERFLOW_WRAPS (type)
> +        && TREE_CODE (@1) == INTEGER_CST
>
> You can write (convert (op @0 INTEGER_CST@1)) and skip this line.
>
> +        && INTEGRAL_TYPE_P (TREE_TYPE (@0))
> +        && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
>
> This seems quite restrictive, TYPE_OVERFLOW_UNDEFINED should also be fine
> for this type. I guess you are trying to avoid saturating / trapping types?

Maybe he's avoiding the dropping of overflow info ... at least it
warrants a comment.

Richard.

> +        && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0)))
> +     (op (convert @0) (convert @1)))))
> +
>  /* If we have a narrowing conversion to an integral type that is fed by a
>     BIT_AND_EXPR, we might be able to remove the BIT_AND_EXPR if it merely
>     masks off bits outside the final type (and nothing else).  */
> diff --git a/gcc/testsuite/gcc.dg/fold-narrow-unsgn-opcst.c
> b/gcc/testsuite/gcc.dg/fold-narrow-unsgn-opcst.c
> new file mode 100644
> index 0000000..aff96a9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/fold-narrow-unsgn-opcst.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-gimple" } */
> +
> +unsigned char foo (unsigned short s)
> +{
> +  return (unsigned char)(s + 65530);
> +}
> +/* { dg-final { scan-tree-dump-not " 65530" "gimple" } } */
>
> As I understand it, C says that s is promoted to int and added to 65530, but
> int is not TYPE_OVERFLOW_WRAPS so your transformation doesn't apply (the
> test already passes without your patch). It is better to write tests for the
> gimple version of transformations, i.e. don't write everything as a single
> expression, use intermediate variables.
>
> --
> Marc Glisse
Jeff Law Oct. 13, 2016, 3:22 p.m. UTC | #2
On 10/12/2016 02:48 AM, Richard Biener wrote:
> On Tue, Oct 11, 2016 at 11:34 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
>> On Tue, 11 Oct 2016, Bin Cheng wrote:
>>
>>> We missed folding (convert)(X op const) -> (convert)X op (convert)const
>>> for unsigned narrowing because of reason reported at
>>> https://gcc.gnu.org/ml/gcc/2016-07/msg00126.html
>>> This patch fixes the issue by adding new match&simplify pattern, it also
>>> adds a test case.  This is the prerequisite patch for next patch adding new
>>> vectorization pattern.
>>
>>
>> Some technical comments below. I am sure Jeff and/or Richi will have more to
>> say on the approach. I am a bit surprised to see it as adding a new
>> transformation, instead of moving an old one.
>
> The "old one" would be c-family/c-common.c:shorten_binary_op.  It's generally
> prefered to move stuff, preserving semantics.
Right.   Kai and I hadn't looked much at shorten_binary_op (focusing 
more on shorten_compare).  But the same principles apply to both.

Namely that the existing routines should be twiddled to handle warnings 
only, but not modify the underlying IL.  IL modifications 
(canonicalization and optimization) should be moved into the match.pd 
framework.

When Kai left Red Hat, that work stalled.  I've got bits and pieces of 
that work lying around, but I don't think they'd help Bin's work right now.

>
> There is also already a bunch of similar match.pd patterns here:
[ ... ]
Right.   Those were a first start at handling some of the desired 
narrowing, focused primarily on BZs that required narrowing to resolve. 
Like Kai's work, I have some generalizations and improvements in a 
half-completed state here, but haven't had time to work on them.


Jeff
Richard Biener Oct. 14, 2016, 9:34 a.m. UTC | #3
On Thu, Oct 13, 2016 at 5:22 PM, Jeff Law <law@redhat.com> wrote:
> On 10/12/2016 02:48 AM, Richard Biener wrote:
>>
>> On Tue, Oct 11, 2016 at 11:34 PM, Marc Glisse <marc.glisse@inria.fr>
>> wrote:
>>>
>>> On Tue, 11 Oct 2016, Bin Cheng wrote:
>>>
>>>> We missed folding (convert)(X op const) -> (convert)X op (convert)const
>>>> for unsigned narrowing because of reason reported at
>>>> https://gcc.gnu.org/ml/gcc/2016-07/msg00126.html
>>>> This patch fixes the issue by adding new match&simplify pattern, it also
>>>> adds a test case.  This is the prerequisite patch for next patch adding
>>>> new
>>>> vectorization pattern.
>>>
>>>
>>>
>>> Some technical comments below. I am sure Jeff and/or Richi will have more
>>> to
>>> say on the approach. I am a bit surprised to see it as adding a new
>>> transformation, instead of moving an old one.
>>
>>
>> The "old one" would be c-family/c-common.c:shorten_binary_op.  It's
>> generally
>> prefered to move stuff, preserving semantics.
>
> Right.   Kai and I hadn't looked much at shorten_binary_op (focusing more on
> shorten_compare).  But the same principles apply to both.
>
> Namely that the existing routines should be twiddled to handle warnings
> only, but not modify the underlying IL.  IL modifications (canonicalization
> and optimization) should be moved into the match.pd framework.

fortunately shorten_binary_op itself does not emit any warnings!

> When Kai left Red Hat, that work stalled.  I've got bits and pieces of that
> work lying around, but I don't think they'd help Bin's work right now.
>
>>
>> There is also already a bunch of similar match.pd patterns here:
>
> [ ... ]
> Right.   Those were a first start at handling some of the desired narrowing,
> focused primarily on BZs that required narrowing to resolve. Like Kai's
> work, I have some generalizations and improvements in a half-completed state
> here, but haven't had time to work on them.
>
>
> Jeff
diff mbox

Patch

diff --git a/gcc/testsuite/gcc.dg/fold-narrow-unsgn-opcst.c b/gcc/testsuite/gcc.dg/fold-narrow-unsgn-opcst.c
new file mode 100644
index 0000000..aff96a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-narrow-unsgn-opcst.c
@@ -0,0 +1,8 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-gimple" } */
+
+unsigned char foo (unsigned short s)
+{
+  return (unsigned char)(s + 65530);
+}
+/* { dg-final { scan-tree-dump-not " 65530" "gimple" } } */