On 5/28/25 4:23 AM, Jiawei wrote:
This patch adds a peephole2 optimization that combines a 'bclr' followed by
a 'binv' into a single 'bset' instruction when the Zbs extension is enabled.

The motivation for this patch is that PR116398 limits 2→2 RTL combinations,
which prevents certain simplifications in the combiner pass. As a result,
combining 'bclr' and 'binv' through standard RTL combination is not feasible
when Zbs is enabled. An example is the testcase
g++.target/riscv/redundant-bitmap-2.C[1] from Jeff Law's patch[2].

PR116398: 
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=4d7a634f6d41029811cdcbd5f7282b5b07890094
[1] https://godbolt.org/z/dhYoTMY1v
[2] 
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=05daf617ea22e1d818295ed2d037456937e23530

gcc/ChangeLog:

        * config/riscv/bitmanip.md (*bset<mode>_2): New pattern.
        * config/riscv/peephole.md: Ditto.

Signed-off-by: Jiawei <jia...@iscas.ac.cn>
---
  gcc/config/riscv/bitmanip.md |  9 +++++++++
  gcc/config/riscv/peephole.md | 16 ++++++++++++++++
  2 files changed, 25 insertions(+)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 21426f49679..1bd66c4aa19 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -615,6 +615,15 @@
    "bset\t%0,x0,%1"
    [(set_attr "type" "bitmanip")])
+(define_insn "*bset<mode>_2"
+  [(set (match_operand:X 0 "register_operand" "=r")
+       (ior:X (match_operand:X 1 "register_operand" "r")
+              (ashift:X (const_int 1)
+                        (match_operand:QI 2 "register_operand" "r"))))]
+  "TARGET_ZBS"
+  "bset\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
Isn't this case handled by this pattern:

(define_insn "*<bit_optab><mode>"
  [(set (match_operand:X 0 "register_operand" "=r")
        (any_or:X (ashift:X (const_int 1)
                            (match_operand:QI 2 "register_operand" "r"))
                  (match_operand:X 1 "register_operand" "r")))]
  "TARGET_ZBS"
  "<bit_optab>\t%0,%1,%2"
  [(set_attr "type" "bitmanip")])
Oh, it's the operand order. Your pattern isn't canonical. If something generated that form, it needs to be fixed. Here's the relevant passage that covers canonicalization of associative operators:


For associative operators, a sequence of operators will always chain
to the left; for instance, only the left operand of an integer @code{plus}
can itself be a @code{plus}.  @code{and}, @code{ior}, @code{xor},
@code{plus}, @code{mult}, @code{smin}, @code{smax}, @code{umin}, and
@code{umax} are associative when applied to integers, and sometimes to
floating-point.






+
  ;; The result will always have bits 32..63 clear, so the zero-extend
  ;; is redundant.  We could split it to bset<mode>_1, but it seems
  ;; unnecessary.
diff --git a/gcc/config/riscv/peephole.md b/gcc/config/riscv/peephole.md
index b5cc1924c76..1d5d15e9005 100644
--- a/gcc/config/riscv/peephole.md
+++ b/gcc/config/riscv/peephole.md
@@ -39,6 +39,22 @@
    operands[5] = GEN_INT (INTVAL (operands[2]) - INTVAL (operands[5]));
  })
+;; ZBS
+(define_peephole2
+  [(set (match_operand:X 1 "register_operand")
+       (and:X (rotate:X (const_int -2)
+                        (match_operand:QI 3 "register_operand"))
+              (match_operand:X 2 "register_operand")))
+   (set (match_operand:X 0 "register_operand")
+       (xor:X (ashift:X (const_int 1)
+                        (match_dup 3))
+              (match_dup 1)))]
+  "TARGET_ZBS"
+  [(set (match_dup 0)
+       (ior:X (match_dup 2)
+              (ashift:X (const_int 1)
+                        (match_dup 3))))])
This seems like it would be much better as a combine pattern. In fact, I'm a bit surprised that combine didn't simplify this series of operations into a IOR. So I'd really like to see the .combine dump with and without this hunk for the relevant testcase.

Also this patch should include a testcase or an addition/adjustment to an existing testcase.


jeff

Reply via email to