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