]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
avoid splitting small constants in bcrli_nottwobits patterns
authorJivan Hakobyan <jivanhakobyan9@gmail.com>
Wed, 26 Apr 2023 02:41:02 +0000 (20:41 -0600)
committerJeff Law <jlaw@ventanamicro>
Wed, 26 Apr 2023 02:44:56 +0000 (20:44 -0600)
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.

gcc/config/riscv/bitmanip.md
gcc/config/riscv/predicates.md
gcc/testsuite/gcc.target/riscv/zbs-bclri-nottwobits.c [new file with mode: 0644]

index 44ad350c747b0371c45122c1b24cf73d6ea9d471..c21247aa3fa9e8e201451c450b7285a99044a03b 100644 (file)
 (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"
 (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"
   "#"
index 8654dbc5943544a441a6219ddd5b4a118a9fbdad..e5adf06fa254af39f0ded5d1a97b4975a934864e 100644 (file)
   (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"
 (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 (file)
index 0000000..5a58e0a
--- /dev/null
@@ -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 } } */