avoid splitting small constants in bcrli_nottwobits patterns
I have noticed that in the case when we try to clear two bits through a small constant, and ZBS is enabled then GCC split it into two "andi" instructions. For example for the following C code: int foo(int a) { return a & ~ 0x101; } GCC generates the following: foo: andi a0,a0,-2 andi a0,a0,-257 ret but should be this one: foo: andi a0,a0,-258 ret This patch solves the mentioned issue. gcc/ChangeLog * config/riscv/bitmanip.md: Updated predicates of bclri<mode>_nottwobits and bclridisi_nottwobits patterns. * config/riscv/predicates.md: (not_uimm_extra_bit_or_nottwobits): Adjust predicate to avoid splitting arith constants. (const_nottwobits_not_arith_operand): New predicate. gcc/testsuite * gcc.target/riscv/zbs-bclri-nottwobits.c: New test.
This commit is contained in:
parent
68201409bc
commit
392200f807
3 changed files with 22 additions and 3 deletions
|
@ -508,7 +508,7 @@
|
|||
(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")))]
|
||||
(match_operand:X 2 "const_nottwobits_not_arith_operand" "i")))]
|
||||
"TARGET_ZBS && !paradoxical_subreg_p (operands[1])"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
|
@ -527,7 +527,7 @@
|
|||
(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")))]
|
||||
(match_operand:DI 2 "const_nottwobits_not_arith_operand" "i")))]
|
||||
"TARGET_64BIT && TARGET_ZBS
|
||||
&& clz_hwi (~UINTVAL (operands[2])) > 33"
|
||||
"#"
|
||||
|
|
|
@ -366,6 +366,11 @@
|
|||
(and (match_code "const_int")
|
||||
(match_test "popcount_hwi (~UINTVAL (op)) == 2")))
|
||||
|
||||
(define_predicate "const_nottwobits_not_arith_operand"
|
||||
(and (match_code "const_int")
|
||||
(and (not (match_operand 0 "arith_operand"))
|
||||
(match_operand 0 "const_nottwobits_operand"))))
|
||||
|
||||
;; A CONST_INT operand that consists of a single run of 32 consecutive
|
||||
;; set bits.
|
||||
(define_predicate "consecutive_bits32_operand"
|
||||
|
@ -411,4 +416,4 @@
|
|||
(define_predicate "not_uimm_extra_bit_or_nottwobits"
|
||||
(and (match_code "const_int")
|
||||
(ior (match_operand 0 "not_uimm_extra_bit_operand")
|
||||
(match_operand 0 "const_nottwobits_operand"))))
|
||||
(match_operand 0 "const_nottwobits_not_arith_operand"))))
|
||||
|
|
14
gcc/testsuite/gcc.target/riscv/zbs-bclri-nottwobits.c
Normal file
14
gcc/testsuite/gcc.target/riscv/zbs-bclri-nottwobits.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv64gc_zbs -mabi=lp64" } */
|
||||
/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
|
||||
|
||||
int and_two_bit(int idx) {
|
||||
return idx & ~3;
|
||||
}
|
||||
|
||||
int and_bclr_two_bit(int idx) {
|
||||
return idx & ~(0x4001);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "\tandi\t" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "\tbclri\t" 1 } } */
|
Loading…
Add table
Reference in a new issue