diff mbox series

RISC-V: Use extension instructions instead of bitwise "and"

Message ID CAHso6sMORuCuONZGQEzATJh3T0aqidjoki=gZZLsT7EJMA_KKA@mail.gmail.com
State New
Headers show
Series RISC-V: Use extension instructions instead of bitwise "and" | expand

Commit Message

Jivan Hakobyan May 23, 2023, 7:46 p.m. UTC
In the case where the target supports extension instructions,
it is preferable to use that instead of doing the same in other ways.
For the following case

void foo (unsigned long a, unsigned long* ptr) {
    ptr[0] = a & 0xffffffffUL;
    ptr[1] &= 0xffffffffUL;
}

GCC generates
foo:
        li      a5,-1
        srli    a5,a5,32
        and     a0,a0,a5
        sd      a0,0(a1)
        ld      a4,8(a1)
        and     a5,a4,a5
        sd      a5,8(a1)
        ret

but it will be profitable to generate this one

foo:
  zext.w a0,a0
  sd a0,0(a1)
  lwu a5,8(a1)
  sd a5,8(a1)
  ret

This patch fixes mentioned issue.
It supports HI -> DI, HI->SI and SI -> DI extensions.

gcc/ChangeLog:
        * config/riscv/riscv.md (and<mode>3): New expander.
        (*and<mode>3) New pattern.
        * config/riscv/predicates.md (arith_operand_or_mode_mask): New
        predicate.

gcc/testsuite/ChangeLog:
        * gcc.target/riscv/and-extend-1.c: New test
        * gcc.target/riscv/and-extend-2.c: New test

Comments

Jeff Law May 29, 2023, 1:57 p.m. UTC | #1
On 5/23/23 13:46, Jivan Hakobyan via Gcc-patches wrote:
> In the case where the target supports extension instructions,
> it is preferable to use that instead of doing the same in other ways.
> For the following case
> 
> void foo (unsigned long a, unsigned long* ptr) {
>      ptr[0] = a & 0xffffffffUL;
>      ptr[1] &= 0xffffffffUL;
> }
> 
> GCC generates
> foo:
>          li      a5,-1
>          srli    a5,a5,32
>          and     a0,a0,a5
>          sd      a0,0(a1)
>          ld      a4,8(a1)
>          and     a5,a4,a5
>          sd      a5,8(a1)
>          ret
> 
> but it will be profitable to generate this one
> 
> foo:
>    zext.w a0,a0
>    sd a0,0(a1)
>    lwu a5,8(a1)
>    sd a5,8(a1)
>    ret
> 
> This patch fixes mentioned issue.
> It supports HI -> DI, HI->SI and SI -> DI extensions.
> 
> gcc/ChangeLog:
>          * config/riscv/riscv.md (and<mode>3): New expander.
>          (*and<mode>3) New pattern.
>          * config/riscv/predicates.md (arith_operand_or_mode_mask): New
>          predicate.
> 
> gcc/testsuite/ChangeLog:
>          * gcc.target/riscv/and-extend-1.c: New test
>          * gcc.target/riscv/and-extend-2.c: New test
Thanks.  I made some minor whitespace fixes and pushed this to the trunk.

Jeff
diff mbox series

Patch

diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index ffcbb9a7589..70f570153ae 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -27,6 +27,12 @@ 
   (ior (match_operand 0 "const_arith_operand")
        (match_operand 0 "register_operand")))
 
+(define_predicate "arith_operand_or_mode_mask"
+  (ior (match_operand 0 "arith_operand")
+       (and (match_code "const_int")
+            (match_test "INTVAL (op) == GET_MODE_MASK (HImode)
+                         || INTVAL (op) == GET_MODE_MASK (SImode)"))))
+
 (define_predicate "lui_operand"
   (and (match_code "const_int")
        (match_test "LUI_OPERAND (INTVAL (op))")))
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 124d8c95804..33336492812 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1342,9 +1342,46 @@ 
 ;; For RV64, we don't expose the SImode operations to the rtl expanders,
 ;; but SImode versions exist for combine.
 
+(define_expand "and<mode>3"
+  [(set (match_operand:X                0 "register_operand")
+        (and:X (match_operand:X 1 "register_operand")
+                       (match_operand:X 2 "arith_operand_or_mode_mask")))]
+  ""
+{
+  if (CONST_INT_P (operands[2]))
+  {
+    enum machine_mode tmode = VOIDmode;
+    if (INTVAL (operands[2]) == GET_MODE_MASK (HImode))
+      tmode = HImode;
+    else if (INTVAL (operands[2]) == GET_MODE_MASK (SImode))
+      tmode = SImode;
+
+    if (tmode != VOIDmode)
+    {
+      rtx tmp = gen_lowpart (tmode, operands[1]);
+      emit_insn (gen_extend_insn (operands[0], tmp, <MODE>mode, tmode, 1));
+      DONE;
+    }
+  }
+  else
+  {
+    emit_move_insn (operands[0], gen_rtx_AND (<MODE>mode, operands[1], operands[2]));
+    DONE;
+  }
+})
+
+(define_insn "*and<mode>3"
+  [(set (match_operand:X                0 "register_operand" "=r,r")
+	(and:X (match_operand:X 1 "register_operand" "%r,r")
+		       (match_operand:X 2 "arith_operand"    " r,I")))]
+  ""
+  "and%i2\t%0,%1,%2"
+  [(set_attr "type" "logical")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "<optab><mode>3"
   [(set (match_operand:X                0 "register_operand" "=r,r")
-	(any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
+	(any_or:X (match_operand:X 1 "register_operand" "%r,r")
 		       (match_operand:X 2 "arith_operand"    " r,I")))]
   ""
   "<insn>%i2\t%0,%1,%2"
diff --git a/gcc/testsuite/gcc.target/riscv/and-extend-1.c b/gcc/testsuite/gcc.target/riscv/and-extend-1.c
new file mode 100644
index 00000000000..a270d287374
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/and-extend-1.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zba_zbb -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+void
+foo(unsigned long a, unsigned long* ptr)
+{
+    ptr[0] = a & 0xffffffffUL;
+    ptr[1] &= 0xffffffffUL;
+}
+
+void
+foo2(unsigned long a, unsigned long* ptr)
+{
+    ptr[0] = a & 0xffff;
+    ptr[1] &= 0xffff;
+}
+
+void
+foo3(unsigned int a, unsigned int* ptr)
+{
+    ptr[0] = a & 0xffff;
+    ptr[1] &= 0xffff;
+}
+
+/* { dg-final { scan-assembler-times "zext.w" 1 } } */
+/* { dg-final { scan-assembler-times "zext.h" 2 } } */
+/* { dg-final { scan-assembler-times "lwu" 1 } } */
+/* { dg-final { scan-assembler-times "lhu" 2 } } */
+/* { dg-final { scan-assembler-not "and\t" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/and-extend-2.c b/gcc/testsuite/gcc.target/riscv/and-extend-2.c
new file mode 100644
index 00000000000..fe639cd1e82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/and-extend-2.c
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zba_zbb -mabi=ilp32" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+void
+foo(unsigned long a, unsigned long* ptr)
+{
+    ptr[0] = a & 0xffffffffUL;
+    ptr[1] &= 0xffffffffUL;
+}
+
+void
+foo2(unsigned long a, unsigned long* ptr)
+{
+    ptr[0] = a & 0xffff;
+    ptr[1] &= 0xffff;
+}
+
+void
+foo3(unsigned int a, unsigned int* ptr)
+{
+    ptr[0] = a & 0xffff;
+    ptr[1] &= 0xffff;
+}
+
+/* { dg-final { scan-assembler-times "zext.h" 2 } } */
+/* { dg-final { scan-assembler-times "lhu" 2 } } */
+/* { dg-final { scan-assembler-not "and\t" } } */