123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- From d3bc6ead74d78d367c0d6cc53efc57c05d8133e9 Mon Sep 17 00:00:00 2001
- From: "yilun.xie" <yilun.xie@starfivetech.com>
- Date: Thu, 18 Nov 2021 16:08:45 +0800
- Subject: [PATCH 22/26] Implement instruction patterns for ZBS extension
- ---
- gcc/config/riscv/predicates.md | 22 +++++++++++
- gcc/config/riscv/riscv.c | 37 ++++++++++++++++++-
- 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 +++++++++++++++++++++
- 8 files changed, 168 insertions(+), 4 deletions(-)
- create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bclr.c
- create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bext.c
- create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-binv.c
- create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bset.c
- diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
- index 23211513554..7a079ebd175 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")))
- \ No newline at end of file
- diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
- index 9e45c1ff9be..0978666a366 100644
- --- a/gcc/config/riscv/riscv.c
- +++ b/gcc/config/riscv/riscv.c
- @@ -388,6 +388,14 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
- 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
- XORI case below will handle those remaining HImode constants. */
- @@ -2199,7 +2207,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";
- @@ -3543,7 +3561,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)
- @@ -3583,6 +3603,19 @@ 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 d17096e1dfa..ff6729aedac 100644
- --- a/gcc/config/riscv/riscv.h
- +++ b/gcc/config/riscv/riscv.h
- @@ -521,6 +521,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 55ebc1c81ce..2c86e446272 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" } } */
- \ No newline at end of file
- +/* { dg-final { scan-assembler "slli.uw" } } */
- \ No newline at end of file
- 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..fdf75b039b9
- --- /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" } } */
- \ No newline at end of file
- 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..766a7c4423a
- --- /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" } } */
- \ No newline at end of file
- 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..d90a6301103
- --- /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" } } */
- \ No newline at end of file
- 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..c3107270153
- --- /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" } } */
- \ No newline at end of file
- --
- 2.33.1
|