diff mbox

Canonicalize X u< X to UNORDERED_EXPR

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

Commit Message

Marc Glisse May 3, 2016, 6:36 a.m. UTC
This removes the duplication. I also removed the case (A&B)&(A&C) which is 
handled by reassoc. And I need 2 NOP checks, for the case where @0 is a 
constant (that couldn't happen before my patch because canonicalization 
would put the constant as second operand).

Bootstrap+regtest on powerpc64le-unknown-linux-gnu.

2016-05-03  Marc Glisse  <marc.glisse@inria.fr>

 	* match.pd ((A | B) & (A | C)): Generalize to BIT_XOR_EXPR.  Mark
 	as commutative.  Check both conversions are NOP.
 	((A & B) OP (C & B)): Remove.

Comments

Richard Biener May 3, 2016, 11:03 a.m. UTC | #1
On Tue, May 3, 2016 at 8:36 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> This removes the duplication. I also removed the case (A&B)&(A&C) which is
> handled by reassoc. And I need 2 NOP checks, for the case where @0 is a
> constant (that couldn't happen before my patch because canonicalization
> would put the constant as second operand).

Nicely spotted.  Not sure we want to delay (A&B)&(A&C) until re-assoc.  We have
many patterns that reassoc would also catch, like (A + CST) + CST or (A + B)- A,
albeit reassoc only handles the unsigned cases.

> Bootstrap+regtest on powerpc64le-unknown-linux-gnu.

Ok.

Thanks,
Richard.

> 2016-05-03  Marc Glisse  <marc.glisse@inria.fr>
>
>         * match.pd ((A | B) & (A | C)): Generalize to BIT_XOR_EXPR.  Mark
>         as commutative.  Check both conversions are NOP.
>         ((A & B) OP (C & B)): Remove.
>
> --
> Marc Glisse
> Index: gcc/match.pd
> ===================================================================
> --- gcc/match.pd        (revision 235764)
> +++ gcc/match.pd        (working copy)
> @@ -678,25 +678,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  (simplify
>   (bit_xor:c (bit_and:c @0 @1) @1)
>   (bit_and (bit_not @0) @1))
>
>  /* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
>     operands are another bit-wise operation with a common input.  If so,
>     distribute the bit operations to save an operation and possibly two if
>     constants are involved.  For example, convert
>       (A | B) & (A | C) into A | (B & C)
>     Further simplification will occur if B and C are constants.  */
> -(for op (bit_and bit_ior)
> -     rop (bit_ior bit_and)
> +(for op (bit_and bit_ior bit_xor)
> +     rop (bit_ior bit_and bit_and)
>   (simplify
> -  (op (convert? (rop:c @0 @1)) (convert? (rop @0 @2)))
> -  (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
> +  (op (convert? (rop:c @0 @1)) (convert? (rop:c @0 @2)))
> +  (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
> +       && tree_nop_conversion_p (type, TREE_TYPE (@2)))
>     (rop (convert @0) (op (convert @1) (convert @2))))))
>
>
>  (simplify
>   (abs (abs@1 @0))
>   @1)
>  (simplify
>   (abs (negate @0))
>   (abs @0))
>  (simplify
> @@ -780,26 +781,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>    /* (x & y) | x -> x */
>   (simplify
>    (bitop:c (rbitop:c @0 @1) @0)
>    @0)
>   /* (~x | y) & x -> x & y */
>   /* (~x & y) | x -> x | y */
>   (simplify
>    (bitop:c (rbitop:c (bit_not @0) @1) @0)
>    (bitop @0 @1)))
>
> -/* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
> -(for bitop (bit_and bit_ior bit_xor)
> - (simplify
> -  (bitop (bit_and:c @0 @1) (bit_and @2 @1))
> -  (bit_and (bitop @0 @2) @1)))
> -
>  /* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */
>  (simplify
>    (bit_and (bit_ior @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
>    (bit_ior (bit_and @0 @2) (bit_and @1 @2)))
>
>  /* Combine successive equal operations with constants.  */
>  (for bitop (bit_and bit_ior bit_xor)
>   (simplify
>    (bitop (bitop @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
>    (bitop @0 (bitop @1 @2))))
>
Marc Glisse May 3, 2016, 1:26 p.m. UTC | #2
On Tue, 3 May 2016, Richard Biener wrote:

> On Tue, May 3, 2016 at 8:36 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
>> This removes the duplication. I also removed the case (A&B)&(A&C) which is
>> handled by reassoc. And I need 2 NOP checks, for the case where @0 is a
>> constant (that couldn't happen before my patch because canonicalization
>> would put the constant as second operand).
>
> Nicely spotted.  Not sure we want to delay (A&B)&(A&C) until re-assoc.  We have
> many patterns that reassoc would also catch, like (A + CST) + CST or (A + B)- A,
> albeit reassoc only handles the unsigned cases.

(A&B)&A seems simple enough for match.pd, I thought (A&B)&(A&C) was 
starting to be a bit specialized. I could easily add it back (making it 
work with | at the same time), but then I am not convinced A&(B&C) is the 
best output. If A&B or A&C have several uses, then (A&B)&C or B&(A&C) seem 
preferable (and we would still have a transformation for (A&cst1)&cst2 so 
we wouldn't lose in the case where B and C are constants). We may still 
end up having to add some :s to the transformation I just touched.
Richard Biener May 3, 2016, 1:34 p.m. UTC | #3
On Tue, May 3, 2016 at 3:26 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> On Tue, 3 May 2016, Richard Biener wrote:
>
>> On Tue, May 3, 2016 at 8:36 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
>>>
>>> This removes the duplication. I also removed the case (A&B)&(A&C) which
>>> is
>>> handled by reassoc. And I need 2 NOP checks, for the case where @0 is a
>>> constant (that couldn't happen before my patch because canonicalization
>>> would put the constant as second operand).
>>
>>
>> Nicely spotted.  Not sure we want to delay (A&B)&(A&C) until re-assoc.  We
>> have
>> many patterns that reassoc would also catch, like (A + CST) + CST or (A +
>> B)- A,
>> albeit reassoc only handles the unsigned cases.
>
>
> (A&B)&A seems simple enough for match.pd, I thought (A&B)&(A&C) was starting
> to be a bit specialized. I could easily add it back (making it work with |
> at the same time), but then I am not convinced A&(B&C) is the best output.
> If A&B or A&C have several uses, then (A&B)&C or B&(A&C) seem preferable
> (and we would still have a transformation for (A&cst1)&cst2 so we wouldn't
> lose in the case where B and C are constants). We may still end up having to
> add some :s to the transformation I just touched.

Yeah, these are always tricky questions.  Note that re-assoc won't
handle the case
with multi-use A&C or A&B.  The only reason to care for the single-use case is
when we change operations for the mixed operand cases.  For the all-&| case
there is only the (usual) consideration about SSA lifetime extension.

So maybe it makes sense to split out the all-&| cases.

Richard.

> --
> Marc Glisse
diff mbox

Patch

Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 235764)
+++ gcc/match.pd	(working copy)
@@ -678,25 +678,26 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (simplify
  (bit_xor:c (bit_and:c @0 @1) @1)
  (bit_and (bit_not @0) @1))
 
 /* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
    operands are another bit-wise operation with a common input.  If so,
    distribute the bit operations to save an operation and possibly two if
    constants are involved.  For example, convert
      (A | B) & (A | C) into A | (B & C)
    Further simplification will occur if B and C are constants.  */
-(for op (bit_and bit_ior)
-     rop (bit_ior bit_and)
+(for op (bit_and bit_ior bit_xor)
+     rop (bit_ior bit_and bit_and)
  (simplify
-  (op (convert? (rop:c @0 @1)) (convert? (rop @0 @2)))
-  (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+  (op (convert? (rop:c @0 @1)) (convert? (rop:c @0 @2)))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+       && tree_nop_conversion_p (type, TREE_TYPE (@2)))
    (rop (convert @0) (op (convert @1) (convert @2))))))
 
 
 (simplify
  (abs (abs@1 @0))
  @1)
 (simplify
  (abs (negate @0))
  (abs @0))
 (simplify
@@ -780,26 +781,20 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   /* (x & y) | x -> x */
  (simplify
   (bitop:c (rbitop:c @0 @1) @0)
   @0)
  /* (~x | y) & x -> x & y */
  /* (~x & y) | x -> x | y */
  (simplify
   (bitop:c (rbitop:c (bit_not @0) @1) @0)
   (bitop @0 @1)))
 
-/* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
-(for bitop (bit_and bit_ior bit_xor)
- (simplify
-  (bitop (bit_and:c @0 @1) (bit_and @2 @1))
-  (bit_and (bitop @0 @2) @1)))
-
 /* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */
 (simplify
   (bit_and (bit_ior @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
   (bit_ior (bit_and @0 @2) (bit_and @1 @2)))
 
 /* Combine successive equal operations with constants.  */
 (for bitop (bit_and bit_ior bit_xor)
  (simplify
   (bitop (bitop @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
   (bitop @0 (bitop @1 @2))))