public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-1363] RISC-V: Use extension instructions instead of bitwise "and"
@ 2023-05-29 13:57 Jeff Law
  0 siblings, 0 replies; only message in thread
From: Jeff Law @ 2023-05-29 13:57 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:10680bc36aca7bfaee542a653a78813cf0d4fb1f

commit r14-1363-g10680bc36aca7bfaee542a653a78813cf0d4fb1f
Author: Jivan Hakobyan <jivanhakobyan9@gmail.com>
Date:   Mon May 29 07:55:29 2023 -0600

    RISC-V: Use extension instructions instead of bitwise "and"
    
    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

Diff:
---
 gcc/config/riscv/predicates.md                |  6 ++++
 gcc/config/riscv/riscv.md                     | 41 ++++++++++++++++++++++++++-
 gcc/testsuite/gcc.target/riscv/and-extend-1.c | 30 ++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/and-extend-2.c | 28 ++++++++++++++++++
 4 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index ffcbb9a7589..f7c4a3f030f 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..aba203318a7 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1342,9 +1342,48 @@
 ;; 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 the second operand is a mode mask, emit an extension
+     insn instead.  */
+  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" } } */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-05-29 13:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-29 13:57 [gcc r14-1363] RISC-V: Use extension instructions instead of bitwise "and" Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).