public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jeff Law <jlaw@ventanamicro.com>
To: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Subject: [committed] [v2] More logical op simplifications in simplify-rtx.cc
Date: Sat, 25 May 2024 12:42:00 -0600	[thread overview]
Message-ID: <d94eba4d-11bc-4502-8048-b5e571df0268@ventanamicro.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1206 bytes --]

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


[-- Attachment #2: P --]
[-- Type: text/plain, Size: 6622 bytes --]

commit 05daf617ea22e1d818295ed2d037456937e23530
Author: Jeff Law <jlaw@ventanamicro.com>
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,
+							XEXP (op1, 0),
+							mode));
+      /* (and (ior/xor (Y X) (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, 0)))
+	return simplify_gen_binary (AND, mode, XEXP (op0, 1),
+				    simplify_gen_unary (NOT, mode,
+							XEXP (op1, 0),
+							mode));
+
       /* Convert (and (ior A C) (ior B C)) into (ior (and A B) C).  */
       if (GET_CODE (op0) == GET_CODE (op1)
 	  && (GET_CODE (op0) == AND
diff --git a/gcc/testsuite/g++.target/riscv/redundant-bitmap-1.C b/gcc/testsuite/g++.target/riscv/redundant-bitmap-1.C
new file mode 100644
index 00000000000..37066f10eea
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/redundant-bitmap-1.C
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zba_zbb_zbs -mabi=lp64" } */
+
+void setBit(char &a, int b) {
+    char c = 0x1UL << b;
+    a &= ~c;
+    a |= c;
+}
+
+/* { dg-final { scan-assembler-not "bclr\t" } } */
+/* { dg-final { scan-assembler-not "andn\t" } } */
+/* { dg-final { scan-assembler-not "or\t" } } */
+/* { dg-final { scan-assembler-times "bset\t" 1 } } */
+
diff --git a/gcc/testsuite/g++.target/riscv/redundant-bitmap-2.C b/gcc/testsuite/g++.target/riscv/redundant-bitmap-2.C
new file mode 100644
index 00000000000..86acaba298f
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/redundant-bitmap-2.C
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zba_zbb_zbs -mabi=lp64" } */
+
+void setBit(char &a, int b) {
+    char c = 0x1UL << b;
+    a &= ~c;
+    a ^= c;
+}
+
+/* { dg-final { scan-assembler-not "bclr\t" } } */
+/* { dg-final { scan-assembler-not "xor\t" } } */
+/* { dg-final { scan-assembler-not "andn\t" } } */
+/* { dg-final { scan-assembler-times "bset\t" 1 } } */
+
diff --git a/gcc/testsuite/g++.target/riscv/redundant-bitmap-3.C b/gcc/testsuite/g++.target/riscv/redundant-bitmap-3.C
new file mode 100644
index 00000000000..16bd7c1785e
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/redundant-bitmap-3.C
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zba_zbb_zbs -mabi=lp64" } */
+
+void setBit(char &a, int b) {
+    char c = 0x1UL << b;
+    a |= c;
+    a &= ~c;
+}
+
+/* { dg-final { scan-assembler-not "bset\t" } } */
+/* { dg-final { scan-assembler-not "or\t" } } */
+/* { dg-final { scan-assembler-not "andn\t" } } */
+/* { dg-final { scan-assembler-times "bclr\t" 1 } } */
+
diff --git a/gcc/testsuite/g++.target/riscv/redundant-bitmap-4.C b/gcc/testsuite/g++.target/riscv/redundant-bitmap-4.C
new file mode 100644
index 00000000000..f664ee01a01
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/redundant-bitmap-4.C
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zba_zbb_zbs -mabi=lp64" } */
+
+void setBit(char &a, int b) {
+    char c = 0x1UL << b;
+    a ^= c;
+    a &= ~c;
+}
+
+/* { dg-final { scan-assembler-not "binv\t" } } */
+/* { dg-final { scan-assembler-not "xor\t" } } */
+/* { dg-final { scan-assembler-not "andn\t" } } */
+/* { dg-final { scan-assembler-times "bclr\t" 1 } } */
+

             reply	other threads:[~2024-05-25 18:42 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-25 18:42 Jeff Law [this message]
2024-06-11 22:38 ` Andrew Pinski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d94eba4d-11bc-4502-8048-b5e571df0268@ventanamicro.com \
    --to=jlaw@ventanamicro.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).