Re: [committed] [v2] More logical op simplifications in simplify-rtx.cc

2024-06-11 Thread Andrew Pinski
On Sat, May 25, 2024 at 11:42 AM Jeff Law  wrote:
>
> This is a revamp of what started as a target specific patch.
>
> Basically xalan (corrected, I originally thought it was perlbench) has a
> bitset implementation with a bit of an oddity.  Specifically setBit will
> clear the bit before it is set:
>
> > if (bitToSet < 32)
> > {
> > fBits1 &= ~mask;
> > fBits1 |= mask;
> > }
> >  else
> > {
> > fBits2 &= ~mask;
> > fBits2 |= mask;
> > }
>
> We can clean this up pretty easily in RTL with a small bit of code in
> simplify-rtx.  While xalan doesn't have other cases, we can synthesize
> tests pretty easily and handle them as well.
>
>
> It turns out we don't actually have to recognize this stuff at the bit
> level, just standard logical identities are sufficient.  For example
>
> (X | Y) & ~Y -> X & ~Y
>
>
>
> Andrew P. might poke at this at the gimple level.  The type changes
> kindof get in the way in gimple but he's much better at match.pd than I
> am, so if he wants to chase it from the gimple side, I'll fully support
> that.

So we already have this pattern (without the type change) in gimple:
 /* (~x | y) & x -> x & y */
 /* (~x & y) | x -> x | y */
 (simplify
  (bitop:c (rbitop:c @2 @1) @0)
  (with { bool wascmp; }
   (if (bitwise_inverted_equal_p (@0, @2, wascmp)
&& (!wascmp || element_precision (type) == 1))
(bitop @0 @1

The problem is bitwise_inverted_equal_p does not see that:
  c.0_4 = (signed char) _1;
  _5 = ~c.0_4;
  _16 = (charD.11) _5;

and
  c_11 = (charD.11) _1;

are bitwise inversions of each other.

I filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115449 to keep
track of this.

Thanks,
Andrew Pinski




>
> Bootstrapped and regression tested on x86.  Also run through my tester
> on its embedded targets.
>
> Pushing to the trunk.
>
> jeff
>


[committed] [v2] More logical op simplifications in simplify-rtx.cc

2024-05-25 Thread Jeff Law

This is a revamp of what started as a target specific patch.

Basically xalan (corrected, I originally thought it was perlbench) has a 
bitset implementation with a bit of an oddity.  Specifically setBit will 
clear the bit before it is set:



if (bitToSet < 32)
{
fBits1 &= ~mask;
fBits1 |= mask;
}
 else
{
fBits2 &= ~mask;
fBits2 |= mask;
}


We can clean this up pretty easily in RTL with a small bit of code in 
simplify-rtx.  While xalan doesn't have other cases, we can synthesize 
tests pretty easily and handle them as well.



It turns out we don't actually have to recognize this stuff at the bit 
level, just standard logical identities are sufficient.  For example


(X | Y) & ~Y -> X & ~Y



Andrew P. might poke at this at the gimple level.  The type changes 
kindof get in the way in gimple but he's much better at match.pd than I 
am, so if he wants to chase it from the gimple side, I'll fully support 
that.


Bootstrapped and regression tested on x86.  Also run through my tester 
on its embedded targets.


Pushing to the trunk.

jeff

commit 05daf617ea22e1d818295ed2d037456937e23530
Author: Jeff Law 
Date:   Sat May 25 12:39:05 2024 -0600

    [committed] [v2] More logical op simplifications in simplify-rtx.cc

This is a revamp of what started as a target specific patch.

Basically xalan (corrected, I originally thought it was perlbench) has a 
bitset
implementation with a bit of an oddity.  Specifically setBit will clear the 
bit
before it is set:

> if (bitToSet < 32)
> {
> fBits1 &= ~mask;
> fBits1 |= mask;
> }
>  else
> {
> fBits2 &= ~mask;
> fBits2 |= mask;
> }
We can clean this up pretty easily in RTL with a small bit of code in
simplify-rtx.  While xalan doesn't have other cases, we can synthesize tests
pretty easily and handle them as well.

It turns out we don't actually have to recognize this stuff at the bit 
level,
just standard logical identities are sufficient.  For example

(X | Y) & ~Y -> X & ~Y

Andrew P. might poke at this at the gimple level.  The type changes kindof 
get
in the way in gimple but he's much better at match.pd than I am, so if he 
wants
to chase it from the gimple side, I'll fully support that.

Bootstrapped and regression tested on x86.  Also run through my tester on 
its
embedded targets.

Pushing to the trunk.

gcc/

* simplify-rtx.cc (simplify_context::simplify_binary_operation_1): 
Handle
more logical simplifications.

gcc/testsuite/

* g++.target/riscv/redundant-bitmap-1.C: New test.
* g++.target/riscv/redundant-bitmap-2.C: New test.
* g++.target/riscv/redundant-bitmap-3.C: New test.
* g++.target/riscv/redundant-bitmap-4.C: New test.

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 53f54d1d392..5caf1dfd957 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -3549,6 +3549,12 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
return tem;
}
 
+  /* Convert (ior (and (not A) B) A) into A | B.  */
+  if (GET_CODE (op0) == AND
+ && GET_CODE (XEXP (op0, 0)) == NOT
+ && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1))
+   return simplify_gen_binary (IOR, mode, XEXP (op0, 1), op1);
+
   tem = simplify_byte_swapping_operation (code, mode, op0, op1);
   if (tem)
return tem;
@@ -3801,6 +3807,12 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
return tem;
}
 
+  /* Convert (xor (and (not A) B) A) into A | B.  */
+  if (GET_CODE (op0) == AND
+ && GET_CODE (XEXP (op0, 0)) == NOT
+ && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1))
+   return simplify_gen_binary (IOR, mode, XEXP (op0, 1), op1);
+
   tem = simplify_byte_swapping_operation (code, mode, op0, op1);
   if (tem)
return tem;
@@ -4006,6 +4018,23 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
  && rtx_equal_p (op1, XEXP (XEXP (op0, 1), 0)))
return simplify_gen_binary (AND, mode, op1, XEXP (op0, 0));
 
+  /* (and (ior/xor (X Y) (not Y)) -> X & ~Y */
+  if ((GET_CODE (op0) == IOR || GET_CODE (op0) == XOR)
+ && GET_CODE (op1) == NOT
+ && rtx_equal_p (XEXP (op1, 0), XEXP (op0, 1)))
+   return simplify_gen_binary (AND, mode, XEXP (op0, 0),
+   simplify_gen_unary (NOT, mode,
+