[PATCH][AArch64] Add BIC-imm and ORR-imm SIMD pattern
authorSudakshina Das <sudi.das@arm.com>
Wed, 4 Oct 2017 16:59:40 +0000 (16:59 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Wed, 4 Oct 2017 16:59:40 +0000 (16:59 +0000)
This patch adds the support for BIC (vector, immediate) and
ORR (vector, immediate) SIMD patterns to the AArch64 backend.

Committed on behalf of Sudi Das.

Reviewed-by: Richard Earnshaw <Richard.Earnshaw@arm.com>
Reviewed-by: James Greenhalgh <james.greenhalgh@arm.com>
gcc/

* config/aarch64/aarch64-protos.h (enum simd_immediate_check): New
check type for aarch64_simd_valid_immediate.
(aarch64_output_simd_mov_immediate): Update prototype.
(aarch64_simd_valid_immediate): Update prototype.
* config/aarch64/aarch64-simd.md (orr<mode>3): modified pattern to add
support for ORR-immediate.
(and<mode>3): modified pattern to add support for BIC-immediate.
* config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Function
now checks for valid immediate for BIC and ORR based on new enum
argument.
(aarch64_output_simd_mov_immediate): Function now used to output
BIC/ORR imm as well based on new enum argument.
* config/aarch64/constraints.md (Do): New vector immediate constraint.
(Db) : Likewise.
* config/aarch64/predicates.md (aarch64_reg_or_orr_imm): New predicate.
(aarch64_reg_or_bic_imm): Likewise.

gcc/testsuite/

* gcc.target/aarch64/bic_imm_1.c: New test.
* gcc.target/aarch64/orr_imm_1.c: Likewise.

From-SVN: r253422

gcc/ChangeLog
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/constraints.md
gcc/config/aarch64/predicates.md
gcc/testsuite/ChangeLog

index d8a9bc1e75b0c1ec7af6c63f19c60c0cc9eea503..2046e349a80049ae1fd5b13960b870754e229797 100644 (file)
@@ -1,3 +1,22 @@
+2017-10-04  Sudakshina Das  <sudi.das@arm.com>
+
+       * config/aarch64/aarch64-protos.h (enum simd_immediate_check): New
+       check type for aarch64_simd_valid_immediate.
+       (aarch64_output_simd_mov_immediate): Update prototype.
+       (aarch64_simd_valid_immediate): Update prototype.
+       * config/aarch64/aarch64-simd.md (orr<mode>3): modified pattern to add
+       support for ORR-immediate.
+       (and<mode>3): modified pattern to add support for BIC-immediate.
+       * config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Function
+       now checks for valid immediate for BIC and ORR based on new enum
+       argument.
+       (aarch64_output_simd_mov_immediate): Function now used to output
+       BIC/ORR imm as well based on new enum argument.
+       * config/aarch64/constraints.md (Do): New vector immediate constraint.
+       (Db) : Likewise.
+       * config/aarch64/predicates.md (aarch64_reg_or_orr_imm): New predicate.
+       (aarch64_reg_or_bic_imm): Likewise.
+
 2017-10-04  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * config/s390/vx-builtins.md ("vec_mergeh<mode>")
index e67c2ed5e80a2e4f4858cfcd40573efd2a8a4416..5d7c5dfc6902b5e208bb9ebef758e0bd00b60561 100644 (file)
@@ -308,6 +308,16 @@ enum aarch64_parse_opt_result
   AARCH64_PARSE_INVALID_ARG            /* Invalid arch, tune, cpu arg.  */
 };
 
+/* Enum to distinguish which type of check is to be done in
+   aarch64_simd_valid_immediate.  This is used as a bitmask where
+   AARCH64_CHECK_MOV has both bits set.  Thus AARCH64_CHECK_MOV will
+   perform all checks.  Adding new types would require changes accordingly.  */
+enum simd_immediate_check {
+  AARCH64_CHECK_ORR  = 1 << 0,
+  AARCH64_CHECK_BIC  = 1 << 1,
+  AARCH64_CHECK_MOV  = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
+};
+
 extern struct tune_params aarch64_tune_params;
 
 HOST_WIDE_INT aarch64_initial_elimination_offset (unsigned, unsigned);
@@ -345,7 +355,8 @@ bool aarch64_mov_operand_p (rtx, machine_mode);
 rtx aarch64_reverse_mask (machine_mode);
 bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT);
 char *aarch64_output_scalar_simd_mov_immediate (rtx, scalar_int_mode);
-char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
+char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned,
+                       enum simd_immediate_check w = AARCH64_CHECK_MOV);
 bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
 bool aarch64_regno_ok_for_base_p (int, bool);
 bool aarch64_regno_ok_for_index_p (int, bool);
@@ -356,7 +367,8 @@ bool aarch64_simd_imm_zero_p (rtx, machine_mode);
 bool aarch64_simd_scalar_immediate_valid_for_move (rtx, scalar_int_mode);
 bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool);
 bool aarch64_simd_valid_immediate (rtx, machine_mode, bool,
-                                  struct simd_immediate_info *);
+                       struct simd_immediate_info *,
+                       enum simd_immediate_check w = AARCH64_CHECK_MOV);
 bool aarch64_split_dimode_const_store (rtx, rtx);
 bool aarch64_symbolic_address_p (rtx);
 bool aarch64_uimm12_shift (HOST_WIDE_INT);
index 70e9339e2757324630b7333454169d82389c61d5..12da8be73e83d0325879c23a86a28ad3f9c84e77 100644 (file)
   [(set_attr "type" "neon_fp_abd_<stype><q>")]
 )
 
+;; For AND (vector, register) and BIC (vector, immediate)
 (define_insn "and<mode>3"
-  [(set (match_operand:VDQ_I 0 "register_operand" "=w")
-        (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w")
-                (match_operand:VDQ_I 2 "register_operand" "w")))]
+  [(set (match_operand:VDQ_I 0 "register_operand" "=w,w")
+       (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0")
+                  (match_operand:VDQ_I 2 "aarch64_reg_or_bic_imm" "w,Db")))]
   "TARGET_SIMD"
-  "and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
+  {
+    switch (which_alternative)
+      {
+      case 0:
+       return "and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>";
+      case 1:
+       return aarch64_output_simd_mov_immediate (operands[2],
+          <MODE>mode, GET_MODE_BITSIZE (<MODE>mode), AARCH64_CHECK_BIC);
+      default:
+       gcc_unreachable ();
+      }
+  }
   [(set_attr "type" "neon_logic<q>")]
 )
 
+;; For ORR (vector, register) and ORR (vector, immediate)
 (define_insn "ior<mode>3"
-  [(set (match_operand:VDQ_I 0 "register_operand" "=w")
-        (ior:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w")
-                (match_operand:VDQ_I 2 "register_operand" "w")))]
+  [(set (match_operand:VDQ_I 0 "register_operand" "=w,w")
+       (ior:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0")
+                  (match_operand:VDQ_I 2 "aarch64_reg_or_orr_imm" "w,Do")))]
   "TARGET_SIMD"
-  "orr\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
+  {
+    switch (which_alternative)
+      {
+      case 0:
+       return "orr\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>";
+      case 1:
+       return aarch64_output_simd_mov_immediate (operands[2],
+               <MODE>mode, GET_MODE_BITSIZE (<MODE>mode), AARCH64_CHECK_ORR);
+      default:
+       gcc_unreachable ();
+      }
+  }
   [(set_attr "type" "neon_logic<q>")]
 )
 
index e89c8156976cecf200cd67c1e938c8156c1240c4..ee98a1f822827cec610cc28b17f199b77192785e 100644 (file)
@@ -11483,7 +11483,8 @@ aarch64_vect_float_const_representable_p (rtx x)
 /* Return true for valid and false for invalid.  */
 bool
 aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
-                             struct simd_immediate_info *info)
+                             struct simd_immediate_info *info,
+                             enum simd_immediate_check which)
 {
 #define CHECK(STRIDE, ELSIZE, CLASS, TEST, SHIFT, NEG) \
   matches = 1;                                         \
@@ -11551,54 +11552,65 @@ aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
 
   do
     {
-      CHECK (4, 32, 0, bytes[i] == bytes[0] && bytes[i + 1] == 0
-            && bytes[i + 2] == 0 && bytes[i + 3] == 0, 0, 0);
+      if (which & AARCH64_CHECK_ORR)
+       {
+         CHECK (4, 32, 0, bytes[i] == bytes[0] && bytes[i + 1] == 0
+                && bytes[i + 2] == 0 && bytes[i + 3] == 0, 0, 0);
 
-      CHECK (4, 32, 1, bytes[i] == 0 && bytes[i + 1] == bytes[1]
-            && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
+         CHECK (4, 32, 1, bytes[i] == 0 && bytes[i + 1] == bytes[1]
+                && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
 
-      CHECK (4, 32, 2, bytes[i] == 0 && bytes[i + 1] == 0
-            && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
+         CHECK (4, 32, 2, bytes[i] == 0 && bytes[i + 1] == 0
+                && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
 
-      CHECK (4, 32, 3, bytes[i] == 0 && bytes[i + 1] == 0
-            && bytes[i + 2] == 0 && bytes[i + 3] == bytes[3], 24, 0);
+         CHECK (4, 32, 3, bytes[i] == 0 && bytes[i + 1] == 0
+                && bytes[i + 2] == 0 && bytes[i + 3] == bytes[3], 24, 0);
 
-      CHECK (2, 16, 4, bytes[i] == bytes[0] && bytes[i + 1] == 0, 0, 0);
+         CHECK (2, 16, 4, bytes[i] == bytes[0] && bytes[i + 1] == 0, 0, 0);
 
-      CHECK (2, 16, 5, bytes[i] == 0 && bytes[i + 1] == bytes[1], 8, 0);
+         CHECK (2, 16, 5, bytes[i] == 0 && bytes[i + 1] == bytes[1], 8, 0);
+       }
 
-      CHECK (4, 32, 6, bytes[i] == bytes[0] && bytes[i + 1] == 0xff
-            && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 0, 1);
+      if (which & AARCH64_CHECK_BIC)
+       {
+         CHECK (4, 32, 6, bytes[i] == bytes[0] && bytes[i + 1] == 0xff
+                && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 0, 1);
 
-      CHECK (4, 32, 7, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
-            && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
+         CHECK (4, 32, 7, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
+                && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
 
-      CHECK (4, 32, 8, bytes[i] == 0xff && bytes[i + 1] == 0xff
-            && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
+         CHECK (4, 32, 8, bytes[i] == 0xff && bytes[i + 1] == 0xff
+                && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
 
-      CHECK (4, 32, 9, bytes[i] == 0xff && bytes[i + 1] == 0xff
-            && bytes[i + 2] == 0xff && bytes[i + 3] == bytes[3], 24, 1);
+         CHECK (4, 32, 9, bytes[i] == 0xff && bytes[i + 1] == 0xff
+                && bytes[i + 2] == 0xff && bytes[i + 3] == bytes[3], 24, 1);
 
-      CHECK (2, 16, 10, bytes[i] == bytes[0] && bytes[i + 1] == 0xff, 0, 1);
+         CHECK (2, 16, 10, bytes[i] == bytes[0] && bytes[i + 1] == 0xff, 0, 1);
 
-      CHECK (2, 16, 11, bytes[i] == 0xff && bytes[i + 1] == bytes[1], 8, 1);
+         CHECK (2, 16, 11, bytes[i] == 0xff && bytes[i + 1] == bytes[1], 8, 1);
+       }
 
-      CHECK (4, 32, 12, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
-            && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
+      /* Shifting ones / 8-bit / 64-bit variants only checked
+        for 'ALL' (MOVI/MVNI).  */
+      if (which == AARCH64_CHECK_MOV)
+       {
+         CHECK (4, 32, 12, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
+                && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
 
-      CHECK (4, 32, 13, bytes[i] == 0 && bytes[i + 1] == bytes[1]
-            && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
+         CHECK (4, 32, 13, bytes[i] == 0 && bytes[i + 1] == bytes[1]
+                && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
 
-      CHECK (4, 32, 14, bytes[i] == 0xff && bytes[i + 1] == 0xff
-            && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
+         CHECK (4, 32, 14, bytes[i] == 0xff && bytes[i + 1] == 0xff
+                && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
 
-      CHECK (4, 32, 15, bytes[i] == 0 && bytes[i + 1] == 0
-            && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
+         CHECK (4, 32, 15, bytes[i] == 0 && bytes[i + 1] == 0
+                && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
 
-      CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0);
+         CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0);
 
-      CHECK (1, 64, 17, (bytes[i] == 0 || bytes[i] == 0xff)
-            && bytes[i] == bytes[(i + 8) % idx], 0, 0);
+         CHECK (1, 64, 17, (bytes[i] == 0 || bytes[i] == 0xff)
+                && bytes[i] == bytes[(i + 8) % idx], 0, 0);
+       }
     }
   while (0);
 
@@ -13000,10 +13012,14 @@ aarch64_float_const_representable_p (rtx x)
   return (exponent >= 0 && exponent <= 7);
 }
 
+/* Returns the string with the instruction for AdvSIMD MOVI, MVNI, ORR or BIC
+   immediate with a CONST_VECTOR of MODE and WIDTH.  WHICH selects whether to
+   output MOVI/MVNI, ORR or BIC immediate.  */
 char*
 aarch64_output_simd_mov_immediate (rtx const_vector,
                                   machine_mode mode,
-                                  unsigned width)
+                                  unsigned width,
+                                  enum simd_immediate_check which)
 {
   bool is_valid;
   static char templ[40];
@@ -13015,9 +13031,11 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
   struct simd_immediate_info info = { NULL_RTX, 0, 0, false, false };
 
   /* This will return true to show const_vector is legal for use as either
-     a AdvSIMD MOVI instruction (or, implicitly, MVNI) immediate.  It will
-     also update INFO to show how the immediate should be generated.  */
-  is_valid = aarch64_simd_valid_immediate (const_vector, mode, false, &info);
+     a AdvSIMD MOVI instruction (or, implicitly, MVNI), ORR or BIC immediate.
+     It will also update INFO to show how the immediate should be generated.
+     WHICH selects whether to check for MOVI/MVNI, ORR or BIC.  */
+  is_valid = aarch64_simd_valid_immediate (const_vector, mode, false,
+                                          &info, which);
   gcc_assert (is_valid);
 
   element_char = sizetochar (info.element_width);
@@ -13048,20 +13066,37 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
        }
     }
 
-  mnemonic = info.mvn ? "mvni" : "movi";
-  shift_op = info.msl ? "msl" : "lsl";
-
   gcc_assert (CONST_INT_P (info.value));
-  if (lane_count == 1)
-    snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX,
-             mnemonic, UINTVAL (info.value));
-  else if (info.shift)
-    snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX
-             ", %s %d", mnemonic, lane_count, element_char,
-             UINTVAL (info.value), shift_op, info.shift);
+
+  if (which == AARCH64_CHECK_MOV)
+    {
+      mnemonic = info.mvn ? "mvni" : "movi";
+      shift_op = info.msl ? "msl" : "lsl";
+      if (lane_count == 1)
+       snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX,
+                 mnemonic, UINTVAL (info.value));
+      else if (info.shift)
+       snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, "
+                 HOST_WIDE_INT_PRINT_HEX ", %s %d", mnemonic, lane_count,
+                 element_char, UINTVAL (info.value), shift_op, info.shift);
+      else
+       snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, "
+                 HOST_WIDE_INT_PRINT_HEX, mnemonic, lane_count,
+                 element_char, UINTVAL (info.value));
+    }
   else
-    snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX,
-             mnemonic, lane_count, element_char, UINTVAL (info.value));
+    {
+      /* For AARCH64_CHECK_BIC and AARCH64_CHECK_ORR.  */
+      mnemonic = info.mvn ? "bic" : "orr";
+      if (info.shift)
+       snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #"
+                 HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count,
+                 element_char, UINTVAL (info.value), "lsl", info.shift);
+      else
+       snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #"
+                 HOST_WIDE_INT_PRINT_DEC, mnemonic, lane_count,
+                 element_char, UINTVAL (info.value));
+    }
   return templ;
 }
 
index 3649fb48a33454c208a6b81e051fdd316c495710..77c510cea0d9da7cbce2e5d42823de6b288a153f 100644 (file)
   (and (match_code "const_double")
        (match_test "aarch64_can_const_movi_rtx_p (op, GET_MODE (op))")))
 
+(define_constraint "Do"
+  "@internal
+   A constraint that matches vector of immediates for orr."
+ (and (match_code "const_vector")
+      (match_test "aarch64_simd_valid_immediate (op, mode, false,
+                                                NULL, AARCH64_CHECK_ORR)")))
+
+(define_constraint "Db"
+  "@internal
+   A constraint that matches vector of immediates for bic."
+ (and (match_code "const_vector")
+      (match_test "aarch64_simd_valid_immediate (op, mode, false,
+                                                NULL, AARCH64_CHECK_BIC)")))
+
 (define_constraint "Dn"
   "@internal
  A constraint that matches vector of immediates."
index 11243c4ce00aa7d16a886bb24b01180801c68f4e..887a13ee4f1be504317c0857d8ad135523cbaec0 100644 (file)
                 (ior (match_test "op == constm1_rtx")
                      (match_test "op == const1_rtx"))))))
 
+(define_predicate "aarch64_reg_or_orr_imm"
+   (ior (match_operand 0 "register_operand")
+       (match_test "aarch64_simd_valid_immediate (op, mode, false,
+                                                  NULL, AARCH64_CHECK_ORR)")))
+
+(define_predicate "aarch64_reg_or_bic_imm"
+   (ior (match_operand 0 "register_operand")
+       (match_test "aarch64_simd_valid_immediate (op, mode, false,
+                                                  NULL, AARCH64_CHECK_BIC)")))
+
 (define_predicate "aarch64_fp_compare_operand"
   (ior (match_operand 0 "register_operand")
        (and (match_code "const_double")
index 26ca5563af4278b07916d0a7805820faae5a5292..da8358ced9e17463defa6288669328a9be500136 100644 (file)
@@ -1,3 +1,8 @@
+2017-10-04  Sudakshina Das  <sudi.das@arm.com>
+
+       * gcc.target/aarch64/bic_imm_1.c: New.
+       * gcc.target/aarch64/orr_imm_1.c: Likewise.
+
 2017-10-04  Nathan Sidwell  <nathan@acm.org>
 
        * g++.dg/abi/mangle41.C: Adjust diagnostics.