]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Restore bfxil optimization [PR100028]
authorJakub Jelinek <jakub@redhat.com>
Tue, 13 Apr 2021 10:43:39 +0000 (12:43 +0200)
committerJakub Jelinek <jakub@redhat.com>
Tue, 13 Apr 2021 10:43:39 +0000 (12:43 +0200)
Similarly to PR87763 for bfi, the GCC 9 combiner changes to not combine
moves from hard registers regressed the following testcase where we no
longer recognize bfxil and emit 3 instructions instead.

The following patch adds define_insn patterns that match what the combiner
is trying to match in these cases.  I haven't been able to see patterns
with the other order of the IOR operands, seems the IL is canonicalized this
way no matter what is written in the source.

2021-04-13  Jakub Jelinek  <jakub@redhat.com>

PR target/100028
* config/aarch64/aarch64.md (*aarch64_bfxil<mode>_extr,
*aarch64_bfxilsi_extrdi): New define_insn patterns.

* gcc.target/aarch64/pr100028.c: New test.

gcc/config/aarch64/aarch64.md
gcc/testsuite/gcc.target/aarch64/pr100028.c [new file with mode: 0644]

index a149748045f836e3914379610a3a8cf42275c634..9a7ed7866b1fbd67180b7da021503d0714013ed9 100644 (file)
   [(set_attr "type" "bfm")]
 )
 
+(define_insn "*aarch64_bfxil<mode>_extr"
+  [(set (match_operand:GPI 0 "register_operand" "=r")
+        (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
+                         (match_operand:GPI 2 "const_int_operand" "n"))
+                (zero_extract:GPI
+                  (match_operand:GPI 3 "register_operand" "r")
+                  (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n")
+                  (match_operand:GPI 5 "aarch64_simd_shift_imm_<mode>" "n"))))]
+  "UINTVAL (operands[2]) == HOST_WIDE_INT_M1U << INTVAL (operands[4])
+   && INTVAL (operands[4])
+   && (UINTVAL (operands[4]) + UINTVAL (operands[5])
+       <= GET_MODE_BITSIZE (<MODE>mode))"
+  "bfxil\t%<GPI:w>0, %<GPI:w>3, %5, %4"
+  [(set_attr "type" "bfm")]
+)
+
+(define_insn "*aarch64_bfxilsi_extrdi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0")
+                       (match_operand:SI 2 "const_int_operand" "n"))
+               (match_operator:SI 6 "subreg_lowpart_operator"
+                 [(zero_extract:DI
+                    (match_operand:DI 3 "register_operand" "r")
+                    (match_operand:SI 4 "aarch64_simd_shift_imm_si" "n")
+                    (match_operand:SI 5 "aarch64_simd_shift_imm_si" "n"))])))]
+  "UINTVAL (operands[2]) == HOST_WIDE_INT_M1U << INTVAL (operands[4])
+   && INTVAL (operands[4])
+   && UINTVAL (operands[4]) + UINTVAL (operands[5]) <= 32"
+  "bfxil\t%w0, %w3, %5, %4"
+  [(set_attr "type" "bfm")]
+)
+
 (define_insn "*extr_insv_lower_reg<mode>"
   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
                          (match_operand 1 "const_int_operand" "n")
diff --git a/gcc/testsuite/gcc.target/aarch64/pr100028.c b/gcc/testsuite/gcc.target/aarch64/pr100028.c
new file mode 100644 (file)
index 0000000..a25b929
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR target/100028 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#define W      3
+#define L      11
+
+int
+foo (int d, int s)
+{
+  int wmask = (1 << W) - 1;
+  return (d & ~wmask) | ((s >> L) & wmask);
+}
+
+long long int
+bar (long long int d, long long int s)
+{
+  long long int wmask = (1LL << W) - 1;
+  return (d & ~wmask) | ((s >> L) & wmask);
+}
+
+/* { dg-final { scan-assembler-times {\tbfxil\t} 2 } } */