On 11/13/22 13:48, Philipp Tomsich wrote:
Use Zbs when generating a sequence for "if ((a & twobits) == singlebit) ..."
that can be expressed as bexti + bexti + andn.

gcc/ChangeLog:

        * config/riscv/bitmanip.md 
(*branch<X:mode>_mask_twobits_equals_singlebit):
        Handle "if ((a & T) == C)" using Zbs, when T has 2 bits set and C has 
one
        of these tow bits set.
        * config/riscv/predicates.md (const_twobits_operand): New predicate.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/zbs-if_then_else-01.c: New test.

s/tow/two/ in the ChangeLog.






Signed-off-by: Philipp Tomsich <philipp.toms...@vrull.eu>
---

  gcc/config/riscv/bitmanip.md                  | 42 +++++++++++++++++++
  gcc/config/riscv/predicates.md                |  5 +++
  .../gcc.target/riscv/zbs-if_then_else-01.c    | 20 +++++++++
  3 files changed, 67 insertions(+)
  create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-if_then_else-01.c

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 7a8f4e35880..2cea394671f 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -690,3 +690,45 @@
    "TARGET_ZBS"
    [(set (match_dup 0) (zero_extract:X (match_dup 1) (const_int 1) (match_dup 
2)))
     (set (match_dup 0) (xor:X (match_dup 0) (const_int 1)))])
+
+;; IF_THEN_ELSE: test for 2 bits of opposite polarity
+(define_insn_and_split "*branch<X:mode>_mask_twobits_equals_singlebit"
+  [(set (pc)
+       (if_then_else (match_operator 1 "equality_operator"
+                      [(and:X (match_operand:X 2 "register_operand" "r")
+                              (match_operand:X 3 "const_twobits_operand" "i"))
+                       (match_operand:X 4 "single_bit_mask_operand" "i")])
+        (label_ref (match_operand 0 "" ""))
+        (pc)))
+   (clobber (match_scratch:X 5 "=&r"))
+   (clobber (match_scratch:X 6 "=&r"))]
+  "TARGET_ZBS && TARGET_ZBB && !SMALL_OPERAND (INTVAL (operands[3]))"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 5) (zero_extract:X (match_dup 2)
+                                     (const_int 1)
+                                     (match_dup 8)))
+   (set (match_dup 6) (zero_extract:X (match_dup 2)
+                                     (const_int 1)
+                                     (match_dup 9)))
+   (set (match_dup 6) (and:X (not:X (match_dup 6)) (match_dup 5)))
+   (set (pc) (if_then_else (match_op_dup 1 [(match_dup 6) (const_int 0)])
+                          (label_ref (match_dup 0))
+                          (pc)))]
+{
+   unsigned HOST_WIDE_INT twobits_mask = UINTVAL (operands[3]);
+   unsigned HOST_WIDE_INT singlebit_mask = UINTVAL (operands[4]);
+
+   /* Make sure that the reference value has one of the bits of the mask set */
+   if ((twobits_mask & singlebit_mask) == 0)
+      FAIL;

This fails the split, but in the event this scenario occurs we still would up with an ICE as the output template requires splitting.  Don't we need to have this be part of the pattern's condition instead so that it never matches in that case?


ISTM we should probably have a test to cover this scenario.



jeff


Reply via email to