]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[committed] [v2] More logical op simplifications in simplify-rtx.cc
authorJeff Law <jlaw@ventanamicro.com>
Sat, 25 May 2024 18:39:05 +0000 (12:39 -0600)
committerJeff Law <jlaw@ventanamicro.com>
Sat, 25 May 2024 18:41:26 +0000 (12:41 -0600)
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.

gcc/simplify-rtx.cc
gcc/testsuite/g++.target/riscv/redundant-bitmap-1.C [new file with mode: 0644]
gcc/testsuite/g++.target/riscv/redundant-bitmap-2.C [new file with mode: 0644]
gcc/testsuite/g++.target/riscv/redundant-bitmap-3.C [new file with mode: 0644]
gcc/testsuite/g++.target/riscv/redundant-bitmap-4.C [new file with mode: 0644]

index 53f54d1d392883f3438cd2d32a4b7bf9c1c6cfc1..5caf1dfd957fe1a5f5d7264d5e69a523a748be2f 100644 (file)
@@ -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 (file)
index 0000000..37066f1
--- /dev/null
@@ -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 (file)
index 0000000..86acaba
--- /dev/null
@@ -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 (file)
index 0000000..16bd7c1
--- /dev/null
@@ -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 (file)
index 0000000..f664ee0
--- /dev/null
@@ -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 } } */
+