aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJivan Hakobyan <jivanhakobyan9@gmail.com>2023-04-25 20:41:02 -0600
committerJeff Law <jlaw@ventanamicro>2023-04-25 20:44:56 -0600
commit392200f807fe2ee377ecc451ff75894b89335c33 (patch)
tree312da4789ee25e602d0ddb01328abea0e75a7276
parent68201409bc2867da45791331e385198826fa4576 (diff)
downloadgcc-392200f807fe2ee377ecc451ff75894b89335c33.zip
gcc-392200f807fe2ee377ecc451ff75894b89335c33.tar.gz
gcc-392200f807fe2ee377ecc451ff75894b89335c33.tar.bz2
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.
-rw-r--r--gcc/config/riscv/bitmanip.md4
-rw-r--r--gcc/config/riscv/predicates.md7
-rw-r--r--gcc/testsuite/gcc.target/riscv/zbs-bclri-nottwobits.c14
3 files changed, 22 insertions, 3 deletions
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 44ad350..c21247a 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -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"
"#"
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 8654dbc..e5adf06 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -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"))))
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bclri-nottwobits.c b/gcc/testsuite/gcc.target/riscv/zbs-bclri-nottwobits.c
new file mode 100644
index 0000000..5a58e0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-bclri-nottwobits.c
@@ -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 } } */