public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-4658] RISC-V: Implement instruction patterns for ZBS extension.
@ 2021-10-25  9:12 Kito Cheng
  0 siblings, 0 replies; only message in thread
From: Kito Cheng @ 2021-10-25  9:12 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:4e1e0d79ecbe8727cb69d4cd97b20c71caaefafc

commit r12-4658-g4e1e0d79ecbe8727cb69d4cd97b20c71caaefafc
Author: Jim Wilson <jimw@sifive.com>
Date:   Thu Sep 2 00:28:47 2021 +0800

    RISC-V: Implement instruction patterns for ZBS extension.
    
    2021-10-25  Jim Wilson  <jimw@sifive.com>
                Kito Cheng  <kito.cheng@sifive.com>
    
    gcc/ChangeLog:
    
            * config/riscv/bitmanip.md (shiftm1): New.
            (*bset<mode>): Ditto.
            (*bset<mode>_mask): Ditto.
            (*bset<mode>_1): Ditto.
            (*bset<mode>_1_mask): Ditto.
            (*bseti<mode>): Ditto.
            (*bclr<mode>): Ditto.
            (*bclri<mode>): Ditto.
            (*binv<mode>): Ditto.
            (*binvi<mode>): Ditto.
            (*bext<mode>): Ditto.
            (*bexti): Ditto.
            * config/riscv/predicates.md (splittable_const_int_operand):
            Handle bseti.
            (single_bit_mask_operand): New.
            (not_single_bit_mask_operand): Ditto.
            (const31_operand): Ditto.
            (const63_operand): Ditto.
            * config/riscv/riscv.c (riscv_build_integer_1): Handle bseti.
            (riscv_output_move): Ditto.
            (riscv_print_operand): Handle new operand type: T and S.
            * config/riscv/riscv.h (SINGLE_BIT_MASK_OPERAND): New.
    
    2021-10-25  Jia-Wei Chen  <jiawei@iscas.ac.cn>
                Shi-Hua Liao  <shihua@iscas.ac.cn>
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/zba-slliuw.c: Apply zbs to this testcase.
            * gcc.target/riscv/zbs-bclr.c: New.
            * gcc.target/riscv/zbs-bext.c: Ditto.
            * gcc.target/riscv/zbs-binv.c: Ditto.
            * gcc.target/riscv/zbs-bset.c: Ditto.
    
    Co-authored-by: Kito Cheng <kito.cheng@sifive.com>
    Co-authored-by: Jia-Wei Chen <jiawei@iscas.ac.cn>
    Co-authored-by: Shi-Hua Liao <shihua@iscas.ac.cn>

Diff:
---
 gcc/config/riscv/bitmanip.md                | 102 ++++++++++++++++++++++++++++
 gcc/config/riscv/predicates.md              |  22 ++++++
 gcc/config/riscv/riscv.c                    |  35 +++++++++-
 gcc/config/riscv/riscv.h                    |   8 +++
 gcc/testsuite/gcc.target/riscv/zba-slliuw.c |   4 +-
 gcc/testsuite/gcc.target/riscv/zbs-bclr.c   |  20 ++++++
 gcc/testsuite/gcc.target/riscv/zbs-bext.c   |  20 ++++++
 gcc/testsuite/gcc.target/riscv/zbs-binv.c   |  20 ++++++
 gcc/testsuite/gcc.target/riscv/zbs-bset.c   |  41 +++++++++++
 9 files changed, 268 insertions(+), 4 deletions(-)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 4d624514049..59779b48f27 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -40,6 +40,7 @@
 				 (ctz "ctz")
 				 (popcount "cpop")])
 
+(define_mode_attr shiftm1 [(SI "const31_operand") (DI "const63_operand")])
 
 ;; ZBA extension.
 
@@ -238,3 +239,104 @@
   "TARGET_ZBB"
   "<bitmanip_insn>\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
+
+;; ZBS extension.
+
+(define_insn "*bset<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(ior:X (ashift:X (const_int 1)
+			 (match_operand:QI 2 "register_operand" "r"))
+	       (match_operand:X 1 "register_operand" "r")))]
+  "TARGET_ZBS"
+  "bset\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*bset<mode>_mask"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(ior:X (ashift:X (const_int 1)
+			 (subreg:QI
+			  (and:X (match_operand:X 2 "register_operand" "r")
+				 (match_operand 3 "<X:shiftm1>" "i")) 0))
+	       (match_operand:X 1 "register_operand" "r")))]
+  "TARGET_ZBS"
+  "bset\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*bset<mode>_1"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(ashift:X (const_int 1)
+		  (match_operand:QI 1 "register_operand" "r")))]
+  "TARGET_ZBS"
+  "bset\t%0,x0,%1"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*bset<mode>_1_mask"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(ashift:X (const_int 1)
+		  (subreg:QI
+		   (and:X (match_operand:X 1 "register_operand" "r")
+			  (match_operand 2 "<X:shiftm1>" "i")) 0)))]
+  "TARGET_ZBS"
+  "bset\t%0,x0,%1"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*bseti<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(ior:X (match_operand:X 1 "register_operand" "r")
+	       (match_operand 2 "single_bit_mask_operand" "i")))]
+  "TARGET_ZBS"
+  "bseti\t%0,%1,%S2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*bclr<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(and:X (rotate:X (const_int -2)
+			 (match_operand:QI 2 "register_operand" "r"))
+	       (match_operand:X 1 "register_operand" "r")))]
+  "TARGET_ZBS"
+  "bclr\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*bclri<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(and:X (match_operand:X 1 "register_operand" "r")
+	       (match_operand 2 "not_single_bit_mask_operand" "i")))]
+  "TARGET_ZBS"
+  "bclri\t%0,%1,%T2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*binv<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(xor:X (ashift:X (const_int 1)
+			 (match_operand:QI 2 "register_operand" "r"))
+	       (match_operand:X 1 "register_operand" "r")))]
+  "TARGET_ZBS"
+  "binv\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*binvi<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(xor:X (match_operand:X 1 "register_operand" "r")
+	       (match_operand 2 "single_bit_mask_operand" "i")))]
+  "TARGET_ZBS"
+  "binvi\t%0,%1,%S2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*bext<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(zero_extract:X (match_operand:X 1 "register_operand" "r")
+			(const_int 1)
+			(zero_extend:X
+			 (match_operand:QI 2 "register_operand" "r"))))]
+  "TARGET_ZBS"
+  "bext\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*bexti"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(zero_extract:X (match_operand:X 1 "register_operand" "r")
+			(const_int 1)
+			(match_operand 2 "immediate_operand" "i")))]
+  "TARGET_ZBS"
+  "bexti\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 23211513554..3da6fd4c049 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -74,6 +74,11 @@
   if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
     return false;
 
+  /* Check whether the constant can be loaded in a single
+     instruction with zbs extensions.  */
+  if (TARGET_64BIT && TARGET_ZBS && SINGLE_BIT_MASK_OPERAND (INTVAL (op)))
+    return false;
+
   /* Otherwise check whether the constant can be loaded in a single
      instruction.  */
   return !LUI_OPERAND (INTVAL (op)) && !SMALL_OPERAND (INTVAL (op));
@@ -217,3 +222,20 @@
 {
   return riscv_gpr_save_operation_p (op);
 })
+
+;; Predicates for the ZBS extension.
+(define_predicate "single_bit_mask_operand"
+  (and (match_code "const_int")
+       (match_test "pow2p_hwi (INTVAL (op))")))
+
+(define_predicate "not_single_bit_mask_operand"
+  (and (match_code "const_int")
+       (match_test "pow2p_hwi (~INTVAL (op))")))
+
+(define_predicate "const31_operand"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) == 31")))
+
+(define_predicate "const63_operand"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) == 63")))
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 3ed34f234e5..3943eb4636d 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -410,6 +410,13 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
       codes[0].value = value;
       return 1;
     }
+  if (TARGET_ZBS && SINGLE_BIT_MASK_OPERAND (value))
+    {
+      /* Simply BSETI.  */
+      codes[0].code = UNKNOWN;
+      codes[0].value = value;
+      return 1;
+    }
 
   /* End with ADDI.  When constructing HImode constants, do not generate any
      intermediate value that is not itself a valid HImode constant.  The
@@ -2220,7 +2227,17 @@ riscv_output_move (rtx dest, rtx src)
 	  }
 
       if (src_code == CONST_INT)
-	return "li\t%0,%1";
+	{
+	  if (SMALL_OPERAND (INTVAL (src)) || LUI_OPERAND (INTVAL (src)))
+	    return "li\t%0,%1";
+
+	  if (TARGET_ZBS
+	      && SINGLE_BIT_MASK_OPERAND (INTVAL (src)))
+	    return "bseti\t%0,zero,%S1";
+
+	  /* Should never reach here.  */
+	  abort ();
+	}
 
       if (src_code == HIGH)
 	return "lui\t%0,%h1";
@@ -3561,7 +3578,9 @@ riscv_memmodel_needs_release_fence (enum memmodel model)
    'A'	Print the atomic operation suffix for memory model OP.
    'F'	Print a FENCE if the memory model requires a release.
    'z'	Print x0 if OP is zero, otherwise print OP normally.
-   'i'	Print i if the operand is not a register.  */
+   'i'	Print i if the operand is not a register.
+   'S'	Print shift-index of single-bit mask OP.
+   'T'	Print shift-index of inverted single-bit mask OP.  */
 
 static void
 riscv_print_operand (FILE *file, rtx op, int letter)
@@ -3601,6 +3620,18 @@ riscv_print_operand (FILE *file, rtx op, int letter)
         fputs ("i", file);
       break;
 
+    case 'S':
+      {
+	rtx newop = GEN_INT (ctz_hwi (INTVAL (op)));
+	output_addr_const (file, newop);
+	break;
+      }
+    case 'T':
+      {
+	rtx newop = GEN_INT (ctz_hwi (~INTVAL (op)));
+	output_addr_const (file, newop);
+	break;
+      }
     default:
       switch (code)
 	{
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index f47d5b40a66..64287124735 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -526,6 +526,14 @@ enum reg_class
   (((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH)	\
    || ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0)
 
+/* If this is a single bit mask, then we can load it with bseti.  But this
+   is not useful for any of the low 31 bits because we can use addi or lui
+   to load them.  It is wrong for loading SImode 0x80000000 on rv64 because it
+   needs to be sign-extended.  So we restrict this to the upper 32-bits
+   only.  */
+#define SINGLE_BIT_MASK_OPERAND(VALUE) \
+  (pow2p_hwi (VALUE) && (ctz_hwi (VALUE) >= 32))
+
 /* Stack layout; function entry, exit and calling.  */
 
 #define STACK_GROWS_DOWNWARD 1
diff --git a/gcc/testsuite/gcc.target/riscv/zba-slliuw.c b/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
index 50399f68e08..a7a3dc77d53 100644
--- a/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
+++ b/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-march=rv64gc_zba -mabi=lp64 -O2" } */
+/* { dg-options "-march=rv64gc_zba_zbs -mabi=lp64 -O2" } */
 
 long
 foo (long i)
@@ -8,4 +8,4 @@ foo (long i)
 }
 /* XXX: This pattern need combine improvement or intermediate instruction
  *      from zbs.   */
-/* { dg-final { scan-assembler-not "slli.uw" } } */
+/* { dg-final { scan-assembler "slli.uw" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bclr.c b/gcc/testsuite/gcc.target/riscv/zbs-bclr.c
new file mode 100644
index 00000000000..4a3c2f1cdaf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-bclr.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
+
+/* bclr */
+long
+foo0 (long i, long j)
+{
+  return i & ~(1L << j);
+}
+
+/* bclri */
+long
+foo1 (long i)
+{
+  return i & ~(1L << 20);
+}
+
+/* { dg-final { scan-assembler-times "bclr\t" 1 } } */
+/* { dg-final { scan-assembler-times "bclri\t" 1 } } */
+/* { dg-final { scan-assembler-not "andi" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bext.c b/gcc/testsuite/gcc.target/riscv/zbs-bext.c
new file mode 100644
index 00000000000..a093cdc8d1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-bext.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
+
+/* bext */
+long
+foo0 (long i, long j)
+{
+  return 1L & (i >> j);
+}
+
+/* bexti */
+long
+foo1 (long i)
+{
+  return 1L & (i >> 20);
+}
+
+/* { dg-final { scan-assembler-times "bexti\t" 1 } } */
+/* { dg-final { scan-assembler-times "bext\t" 1 } } */
+/* { dg-final { scan-assembler-not "andi" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-binv.c b/gcc/testsuite/gcc.target/riscv/zbs-binv.c
new file mode 100644
index 00000000000..e4e48b9cdfd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-binv.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
+
+/* binv */
+long
+foo0 (long i, long j)
+{
+  return i ^ (1L << j);
+}
+
+/* binvi */
+long
+foo1 (long i)
+{
+  return i ^ (1L << 20);
+}
+
+/* { dg-final { scan-assembler-times "binv\t" 1 } } */
+/* { dg-final { scan-assembler-times "binvi\t" 1 } } */
+/* { dg-final { scan-assembler-not "andi" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bset.c b/gcc/testsuite/gcc.target/riscv/zbs-bset.c
new file mode 100644
index 00000000000..733d4279d3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-bset.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
+
+/* bset */
+long
+sub0 (long i, long j)
+{
+  return i | (1L << j);
+}
+
+/* bset_mask */
+long
+sub1 (long i, long j)
+{
+  return i | (1L << (j & 0x3f));
+}
+
+/* bset_1 */
+long
+sub2 (long i)
+{
+  return 1L << i;
+}
+
+/* bset_1_mask */
+long
+sub3 (long i)
+{
+  return 1L << (i & 0x3f);
+}
+
+/* bseti */
+long
+sub4 (long i)
+{
+  return i | (1L << 20);
+}
+
+/* { dg-final { scan-assembler-times "bset\t" 4 } } */
+/* { dg-final { scan-assembler-times "bseti\t" 1 } } */
+/* { dg-final { scan-assembler-not "andi" } } */


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

only message in thread, other threads:[~2021-10-25  9:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-25  9:12 [gcc r12-4658] RISC-V: Implement instruction patterns for ZBS extension Kito Cheng

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).