re PR tree-optimization/69848 (poor vectorization of a loop from SPEC2006 464.h264ref)
authorBin Cheng <bin.cheng@arm.com>
Tue, 16 Aug 2016 13:09:40 +0000 (13:09 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Tue, 16 Aug 2016 13:09:40 +0000 (13:09 +0000)
PR tree-optimization/69848
* config/aarch64/aarch64-simd.md (vcond<mode><mode>): Invert NE
and swtich operands to avoid additional NOT instruction.
(vcond<v_cmp_mixed><mode>): Ditto.
(vcondu<mode><mode>, vcondu<mode><v_cmp_mixed>): Ditto.

gcc/testsuite
* gcc.target/aarch64/simd/vcond-ne-bit.c: New test.

From-SVN: r239502

gcc/ChangeLog
gcc/config/aarch64/aarch64-simd.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/simd/vcond-ne-bit.c [new file with mode: 0644]

index 93a12f3fb086beb5827c521426a4fc606f5e1272..e2d39a8792d156d0f4926058d898f583e658ea4a 100644 (file)
@@ -1,3 +1,11 @@
+2016-08-16  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/69848
+       * config/aarch64/aarch64-simd.md (vcond<mode><mode>): Invert NE
+       and swtich operands to avoid additional NOT instruction.
+       (vcond<v_cmp_mixed><mode>): Ditto.
+       (vcondu<mode><mode>, vcondu<mode><v_cmp_mixed>): Ditto.
+
 2016-08-16  Eric Botcazou  <ebotcazou@adacore.com>
 
        * doc/install.texi (*-*-solaris2*): Adjust latest change.
index feb5e96b46f329980eb910f8666a208ab58fb050..70140744bb5a7b6dded304c16291cfdce4375c10 100644 (file)
   "TARGET_SIMD"
 {
   rtx mask = gen_reg_rtx (<V_cmp_result>mode);
+  enum rtx_code code = GET_CODE (operands[3]);
 
+  /* NE is handled as !EQ in vec_cmp patterns, we can explicitly invert
+     it as well as switch operands 1/2 in order to avoid the additional
+     NOT instruction.  */
+  if (code == NE)
+    {
+      operands[3] = gen_rtx_fmt_ee (EQ, GET_MODE (operands[3]),
+                                   operands[4], operands[5]);
+      std::swap (operands[1], operands[2]);
+    }
   emit_insn (gen_vec_cmp<mode><v_cmp_result> (mask, operands[3],
                                              operands[4], operands[5]));
   emit_insn (gen_vcond_mask_<mode><v_cmp_result> (operands[0], operands[1],
   "TARGET_SIMD"
 {
   rtx mask = gen_reg_rtx (<V_cmp_result>mode);
+  enum rtx_code code = GET_CODE (operands[3]);
 
+  /* NE is handled as !EQ in vec_cmp patterns, we can explicitly invert
+     it as well as switch operands 1/2 in order to avoid the additional
+     NOT instruction.  */
+  if (code == NE)
+    {
+      operands[3] = gen_rtx_fmt_ee (EQ, GET_MODE (operands[3]),
+                                   operands[4], operands[5]);
+      std::swap (operands[1], operands[2]);
+    }
   emit_insn (gen_vec_cmp<mode><v_cmp_result> (mask, operands[3],
                                              operands[4], operands[5]));
   emit_insn (gen_vcond_mask_<v_cmp_mixed><v_cmp_result> (
   "TARGET_SIMD"
 {
   rtx mask = gen_reg_rtx (<MODE>mode);
+  enum rtx_code code = GET_CODE (operands[3]);
 
+  /* NE is handled as !EQ in vec_cmp patterns, we can explicitly invert
+     it as well as switch operands 1/2 in order to avoid the additional
+     NOT instruction.  */
+  if (code == NE)
+    {
+      operands[3] = gen_rtx_fmt_ee (EQ, GET_MODE (operands[3]),
+                                   operands[4], operands[5]);
+      std::swap (operands[1], operands[2]);
+    }
   emit_insn (gen_vec_cmp<mode><mode> (mask, operands[3],
                                      operands[4], operands[5]));
   emit_insn (gen_vcond_mask_<mode><v_cmp_result> (operands[0], operands[1],
   "TARGET_SIMD"
 {
   rtx mask = gen_reg_rtx (<V_cmp_result>mode);
+  enum rtx_code code = GET_CODE (operands[3]);
 
+  /* NE is handled as !EQ in vec_cmp patterns, we can explicitly invert
+     it as well as switch operands 1/2 in order to avoid the additional
+     NOT instruction.  */
+  if (code == NE)
+    {
+      operands[3] = gen_rtx_fmt_ee (EQ, GET_MODE (operands[3]),
+                                   operands[4], operands[5]);
+      std::swap (operands[1], operands[2]);
+    }
   emit_insn (gen_vec_cmp<v_cmp_mixed><v_cmp_mixed> (
                                                  mask, operands[3],
                                                  operands[4], operands[5]));
index bd2a2d92d431e3fe1f69dd696308f7ddb9e6aff6..764ff69f8bf07067aa6f2dfd670b5d9a535c01a5 100644 (file)
@@ -1,3 +1,8 @@
+2016-08-16  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/69848
+       * gcc.target/aarch64/simd/vcond-ne-bit.c: New test.
+
 2016-08-16  Martin Liska  <mliska@suse.cz>
 
        * gcc.dg/tree-prof/val-prof-7.c (int main): Change size
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vcond-ne-bit.c b/gcc/testsuite/gcc.target/aarch64/simd/vcond-ne-bit.c
new file mode 100644 (file)
index 0000000..25170c2
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-save-temps" } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_condition } */
+#include <stdlib.h>
+
+int fn1 (int) __attribute__ ((noinline));
+
+int a[128];
+int fn1(int d) {
+  int b, c = 1;
+  for (b = 0; b < 128; b++)
+    if (a[b])
+      c = 0;
+  return c;
+}
+
+int
+main (void)
+{
+  int i;
+  for (i = 0; i < 128; i++)
+    a[i] = 0;
+  if (fn1(10) != 1)
+    abort ();
+  a[3] = 2;
+  a[24] = 1;
+  if (fn1(10) != 0)
+    abort ();
+  return 0;
+}
+/* { dg-final { scan-assembler-not "\[ \t\]not\[ \t\]" } } */