https://gcc.gnu.org/g:d17b09c07a1da0e3950718aabc2cbdb90cae402b

commit r15-6307-gd17b09c07a1da0e3950718aabc2cbdb90cae402b
Author: Oliver Kozul <oliver.ko...@rt-rk.com>
Date:   Tue Dec 17 07:44:33 2024 -0700

    [PATCH] RISC-V: optimization on checking certain bits set ((x & mask) == 
val)
    
    The patch optimizes code generation for comparisons of the form
    X & C1 == C2 by converting them to (X | ~C1) == (C2 | ~C1).
    C1 is a constant that requires li and addi to be loaded,
    while ~C1 requires a single lui instruction.
    As the values of C1 and C2 are not visible within
    the equality expression, a plus pattern is matched instead.
    
          PR target/114087
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.md (*lui_constraint<ANYI:mode>_and_to_or): New 
pattern
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/pr114087-1.c: New test.

Diff:
---
 gcc/config/riscv/riscv.md                   | 28 ++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/pr114087-1.c | 16 ++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 1eec51c117a7..6c6155ceeb83 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -858,6 +858,34 @@
   [(set_attr "type" "arith")
    (set_attr "mode" "SI")])
 
+;; Transform (X & C1) + C2 into (X | ~C1) - (-C2 | ~C1)
+;; Where C1 is not a LUI operand, but ~C1 is a LUI operand
+
+(define_insn_and_split "*lui_constraint<ANYI:mode>_and_to_or"
+       [(set (match_operand:ANYI 0 "register_operand" "=r")
+       (plus:ANYI (and:ANYI (match_operand:ANYI 1 "register_operand" "r")
+                        (match_operand 2 "const_int_operand"))
+                (match_operand 3 "const_int_operand")))
+   (clobber (match_scratch:X 4 "=&r"))]
+  "LUI_OPERAND (~INTVAL (operands[2]))
+   && ((INTVAL (operands[2]) & (-INTVAL (operands[3])))
+   == (-INTVAL (operands[3])))
+   && riscv_const_insns (operands[3], false)
+   && (riscv_const_insns
+   (GEN_INT (~INTVAL (operands[2]) | -INTVAL (operands[3])), false)
+   <= riscv_const_insns (operands[3], false))"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 4) (match_dup 5))
+   (set (match_dup 0) (ior:X (match_dup 1) (match_dup 4)))
+   (set (match_dup 4) (match_dup 6))
+   (set (match_dup 0) (minus:X (match_dup 0) (match_dup 4)))]
+  {
+    operands[5] = GEN_INT (~INTVAL (operands[2]));
+    operands[6] = GEN_INT ((~INTVAL (operands[2])) | (-INTVAL (operands[3])));
+  }
+  [(set_attr "type" "arith")])
+
 ;;
 ;;  ....................
 ;;
diff --git a/gcc/testsuite/gcc.target/riscv/pr114087-1.c 
b/gcc/testsuite/gcc.target/riscv/pr114087-1.c
new file mode 100644
index 000000000000..9df02db6d5df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr114087-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d" } */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+static uint32_t mask1 = 0x55555FFF;
+static uint32_t val1  = 0x14501DEF;
+
+bool pred1a(uint32_t x) {
+  return ((x & mask1) == val1);
+}
+
+/* { dg-final { scan-assembler  {or\s*[a-x0-9]+,\s*[a-x0-9]+,\s*[a-x0-9]+} } } 
*/

Reply via email to