diff options
author | Philipp Tomsich <philipp.tomsich@vrull.eu> | 2022-10-13 10:55:41 +0200 |
---|---|---|
committer | Philipp Tomsich <philipp.tomsich@vrull.eu> | 2022-11-17 16:27:17 +0100 |
commit | 0045d254c010bf5eac55903780c67f725192cfb3 (patch) | |
tree | 67addffd02a3858cd110e2527eafebe9484320b3 /gcc | |
parent | 1957bedf29a1b2cc231972aba680fe80199d5498 (diff) | |
download | gcc-0045d254c010bf5eac55903780c67f725192cfb3.zip gcc-0045d254c010bf5eac55903780c67f725192cfb3.tar.gz gcc-0045d254c010bf5eac55903780c67f725192cfb3.tar.bz2 |
RISC-V: Optimize masking with two clear bits not a SMALL_OPERAND
Add a split for cases where we can use two bclri (or one bclri and an
andi) to clear two bits.
gcc/ChangeLog:
* config/riscv/bitmanip.md (*bclri<mode>_nottwobits): New pattern.
(*bclridisi_nottwobits): New pattern, handling the sign-bit.
* config/riscv/predicates.md (const_nottwobits_operand):
New predicate.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zbs-bclri.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/riscv/bitmanip.md | 38 | ||||
-rw-r--r-- | gcc/config/riscv/predicates.md | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/zbs-bclri.c | 12 |
3 files changed, 55 insertions, 0 deletions
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index 0dd6ebb..2175c62 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -367,6 +367,44 @@ "bclri\t%0,%1,%T2" [(set_attr "type" "bitmanip")]) +;; In case we have "val & ~IMM" where ~IMM has 2 bits set. +(define_insn_and_split "*bclri<mode>_nottwobits" + [(set (match_operand:X 0 "register_operand" "=r") + (and:X (match_operand:X 1 "register_operand" "r") + (match_operand:X 2 "const_nottwobits_operand" "i")))] + "TARGET_ZBS && !paradoxical_subreg_p (operands[1])" + "#" + "&& reload_completed" + [(set (match_dup 0) (and:X (match_dup 1) (match_dup 3))) + (set (match_dup 0) (and:X (match_dup 0) (match_dup 4)))] +{ + unsigned HOST_WIDE_INT bits = ~UINTVAL (operands[2]); + unsigned HOST_WIDE_INT topbit = HOST_WIDE_INT_1U << floor_log2 (bits); + + operands[3] = GEN_INT (~bits | topbit); + operands[4] = GEN_INT (~topbit); +}) + +;; In case of a paradoxical subreg, the sign bit and the high bits are +;; not allowed to be changed +(define_insn_and_split "*bclridisi_nottwobits" + [(set (match_operand:DI 0 "register_operand" "=r") + (and:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "const_nottwobits_operand" "i")))] + "TARGET_64BIT && TARGET_ZBS + && clz_hwi (~UINTVAL (operands[2])) > 33" + "#" + "&& reload_completed" + [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (and:DI (match_dup 0) (match_dup 4)))] +{ + unsigned HOST_WIDE_INT bits = ~UINTVAL (operands[2]); + unsigned HOST_WIDE_INT topbit = HOST_WIDE_INT_1U << floor_log2 (bits); + + operands[3] = GEN_INT (~bits | topbit); + operands[4] = GEN_INT (~topbit); +}) + (define_insn "*binv<mode>" [(set (match_operand:X 0 "register_operand" "=r") (xor:X (ashift:X (const_int 1) diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index c2ff41b..ffb3fca 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -285,3 +285,8 @@ (ior (match_operand 0 "register_operand") (match_test "GET_CODE (op) == UNSPEC && (XINT (op, 1) == UNSPEC_VUNDEF)")))) + +;; A CONST_INT operand that has exactly two bits cleared. +(define_predicate "const_nottwobits_operand" + (and (match_code "const_int") + (match_test "popcount_hwi (~UINTVAL (op)) == 2"))) diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bclri.c b/gcc/testsuite/gcc.target/riscv/zbs-bclri.c new file mode 100644 index 0000000..12e2063 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zbs-bclri.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zbs -mabi=lp64" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ + +/* bclri + bclri */ +long long f5 (long long a) +{ + return a & ~0x11000; +} + +/* { dg-final { scan-assembler-times "bclri\t" 2 } } */ + |