This is the same cleanup as the previous patch, but for the cases where
the operand is a lane mask of the form 1 << lane rather than a lane
number.

Some Advanced SIMD insert patterns receive an integer mask in which the
single set bit encodes the lane.  For example, lane 3 is represented as
1 << 3.  The assembler still wants the lane number in architectural lane
order, so the old templates had to compute:

  ENDIAN_LANE_N (nunits, exact_log2 (mask))

in C before returning the final instruction text.

This patch adds an internal print operand for that:

  %[ENDIAN_LANE_MASK<nunits>]2

The print hook checks that the operand is a valid single-bit constant, turns
it back into a lane number, applies the endian adjustment, and prints the
result.  The machine description can then express the instruction directly,
for example:

  ins\t%0.<Vetype>[%[ENDIAN_LANE_MASK<nunits>]2], 
%3.<Vetype>[%[ENDIAN_LANE<nunits>]4]

Keeping this separate from ENDIAN_LANE makes the expected operand form
clear: one modifier takes a lane number, the other takes a mask of the form
1 << lane.

Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.

OK for master?

Thanks,
Tamar

gcc/ChangeLog:

        * config/aarch64/aarch64.cc (A64_PRINT_endian_lane_mask): New print
        code.
        (operands_cache_initializer): Register ENDIAN_LANE_MASK* operands.
        (aarch64_print_operand): Handle them.
        * config/aarch64/aarch64-simd.md
        (@aarch64_simd_vec_copy_lane<mode>): Use ENDIAN_LANE_MASK* print
        operands.
        (@aarch64_simd_vec_copy_lane_<vswap_width_name><mode>): Likewise.

---
diff --git a/gcc/config/aarch64/aarch64-simd.md 
b/gcc/config/aarch64/aarch64-simd.md
index 
bf8e38a131ef6416b3623e2e66e2f4d4673e5152..2b7f6651f13c63227709ac728b951eabe4503890
 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -1504,13 +1504,7 @@ (define_insn "@aarch64_simd_vec_copy_lane<mode>"
            (match_operand:VALL_F16 1 "register_operand" "0")
            (match_operand:SI 2 "immediate_operand" "i")))]
   "TARGET_SIMD && exact_log2 (INTVAL (operands[2])) >= 0"
-  {
-    int elt = ENDIAN_LANE_N (<nunits>, exact_log2 (INTVAL (operands[2])));
-    operands[2] = GEN_INT (HOST_WIDE_INT_1 << elt);
-    operands[4] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[4]));
-
-    return "ins\t%0.<Vetype>[%p2], %3.<Vetype>[%4]";
-  }
+  "ins\t%0.<Vetype>[%[ENDIAN_LANE_MASK<nunits>:2]], 
%3.<Vetype>[%[ENDIAN_LANE<nunits>:4]]"
   [(set_attr "type" "neon_ins<q>")]
 )
 
@@ -1525,14 +1519,7 @@ (define_insn 
"@aarch64_simd_vec_copy_lane_<vswap_width_name><mode>"
            (match_operand:VALL_F16_NO_V2Q 1 "register_operand" "0")
            (match_operand:SI 2 "immediate_operand" "i")))]
   "TARGET_SIMD && exact_log2 (INTVAL (operands[2])) >= 0"
-  {
-    int elt = ENDIAN_LANE_N (<nunits>, exact_log2 (INTVAL (operands[2])));
-    operands[2] = GEN_INT (HOST_WIDE_INT_1 << elt);
-    operands[4] = aarch64_endian_lane_rtx (<VSWAP_WIDTH>mode,
-                                          INTVAL (operands[4]));
-
-    return "ins\t%0.<Vetype>[%p2], %3.<Vetype>[%4]";
-  }
+  "ins\t%0.<Vetype>[%[ENDIAN_LANE_MASK<nunits>:2]], 
%3.<Vetype>[%[ENDIAN_LANE<vswap_width_nunits>:4]]"
   [(set_attr "type" "neon_ins<q>")]
 )
 
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 
48c1310a586e27c8406a826847685af43a315ef0..cd28a2825b906f7fe4b07c5f6dfca1297d7a49af
 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -13265,6 +13265,9 @@ typedef enum aarch64_print_operands {
   A64_PRINT_addr_ldp_stp,
   /* Print an Advanced SIMD lane number in architectural lane order.  */
   A64_PRINT_endian_lane,
+  /* Print an Advanced SIMD lane mask of the form 1 << lane in architectural
+     lane order.  */
+  A64_PRINT_endian_lane_mask,
   /* Print the final element offset for an SME vector group.  */
   A64_PRINT_sme_vg_end,
   /* Print the inclusive end of an SME slice range.  */
@@ -13336,6 +13339,12 @@ struct operands_cache_initializer
     DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE4, A64_PRINT_endian_lane, 4);
     DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE8, A64_PRINT_endian_lane, 8);
     DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE16, A64_PRINT_endian_lane, 16);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK1, A64_PRINT_endian_lane_mask, 1);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK2, A64_PRINT_endian_lane_mask, 2);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK4, A64_PRINT_endian_lane_mask, 4);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK8, A64_PRINT_endian_lane_mask, 8);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK16, A64_PRINT_endian_lane_mask,
+                            16);
     DEF_PRIVATE_OPERAND (SME_VG_END, A64_PRINT_sme_vg_end);
     DEF_PRIVATE_OPERAND_EXT (SME_RANGE_END1, A64_PRINT_sme_range_end, 1);
     DEF_PRIVATE_OPERAND_EXT (SME_RANGE_END3, A64_PRINT_sme_range_end, 3);
@@ -13917,6 +13926,24 @@ aarch64_print_operand (FILE *f, rtx x, int code)
       }
       break;
 
+    case A64_PRINT_endian_lane_mask:
+      {
+       uintptr_t nunits = (uintptr_t) print_info.extra;
+       int elt;
+
+       if (nunits == 0
+           || !CONST_INT_P (x)
+           || (elt = exact_log2 (INTVAL (x))) < 0)
+         {
+           output_operand_lossage ("invalid operand for '%%%s'",
+                                   token.c_str ());
+           return;
+         }
+
+       asm_fprintf (f, "%wd", ENDIAN_LANE_N (nunits, elt));
+      }
+      break;
+
     case A64_PRINT_sme_vg_end:
       if (!REG_P (x) || !FP_REGNUM_P (REGNO (x)))
        {


-- 
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index bf8e38a131ef6416b3623e2e66e2f4d4673e5152..2b7f6651f13c63227709ac728b951eabe4503890 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -1504,13 +1504,7 @@ (define_insn "@aarch64_simd_vec_copy_lane<mode>"
 	    (match_operand:VALL_F16 1 "register_operand" "0")
 	    (match_operand:SI 2 "immediate_operand" "i")))]
   "TARGET_SIMD && exact_log2 (INTVAL (operands[2])) >= 0"
-  {
-    int elt = ENDIAN_LANE_N (<nunits>, exact_log2 (INTVAL (operands[2])));
-    operands[2] = GEN_INT (HOST_WIDE_INT_1 << elt);
-    operands[4] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[4]));
-
-    return "ins\t%0.<Vetype>[%p2], %3.<Vetype>[%4]";
-  }
+  "ins\t%0.<Vetype>[%[ENDIAN_LANE_MASK<nunits>:2]], %3.<Vetype>[%[ENDIAN_LANE<nunits>:4]]"
   [(set_attr "type" "neon_ins<q>")]
 )
 
@@ -1525,14 +1519,7 @@ (define_insn "@aarch64_simd_vec_copy_lane_<vswap_width_name><mode>"
 	    (match_operand:VALL_F16_NO_V2Q 1 "register_operand" "0")
 	    (match_operand:SI 2 "immediate_operand" "i")))]
   "TARGET_SIMD && exact_log2 (INTVAL (operands[2])) >= 0"
-  {
-    int elt = ENDIAN_LANE_N (<nunits>, exact_log2 (INTVAL (operands[2])));
-    operands[2] = GEN_INT (HOST_WIDE_INT_1 << elt);
-    operands[4] = aarch64_endian_lane_rtx (<VSWAP_WIDTH>mode,
-					   INTVAL (operands[4]));
-
-    return "ins\t%0.<Vetype>[%p2], %3.<Vetype>[%4]";
-  }
+  "ins\t%0.<Vetype>[%[ENDIAN_LANE_MASK<nunits>:2]], %3.<Vetype>[%[ENDIAN_LANE<vswap_width_nunits>:4]]"
   [(set_attr "type" "neon_ins<q>")]
 )
 
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 48c1310a586e27c8406a826847685af43a315ef0..cd28a2825b906f7fe4b07c5f6dfca1297d7a49af 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -13265,6 +13265,9 @@ typedef enum aarch64_print_operands {
   A64_PRINT_addr_ldp_stp,
   /* Print an Advanced SIMD lane number in architectural lane order.  */
   A64_PRINT_endian_lane,
+  /* Print an Advanced SIMD lane mask of the form 1 << lane in architectural
+     lane order.  */
+  A64_PRINT_endian_lane_mask,
   /* Print the final element offset for an SME vector group.  */
   A64_PRINT_sme_vg_end,
   /* Print the inclusive end of an SME slice range.  */
@@ -13336,6 +13339,12 @@ struct operands_cache_initializer
     DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE4, A64_PRINT_endian_lane, 4);
     DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE8, A64_PRINT_endian_lane, 8);
     DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE16, A64_PRINT_endian_lane, 16);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK1, A64_PRINT_endian_lane_mask, 1);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK2, A64_PRINT_endian_lane_mask, 2);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK4, A64_PRINT_endian_lane_mask, 4);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK8, A64_PRINT_endian_lane_mask, 8);
+    DEF_PRIVATE_OPERAND_EXT (ENDIAN_LANE_MASK16, A64_PRINT_endian_lane_mask,
+			     16);
     DEF_PRIVATE_OPERAND (SME_VG_END, A64_PRINT_sme_vg_end);
     DEF_PRIVATE_OPERAND_EXT (SME_RANGE_END1, A64_PRINT_sme_range_end, 1);
     DEF_PRIVATE_OPERAND_EXT (SME_RANGE_END3, A64_PRINT_sme_range_end, 3);
@@ -13917,6 +13926,24 @@ aarch64_print_operand (FILE *f, rtx x, int code)
       }
       break;
 
+    case A64_PRINT_endian_lane_mask:
+      {
+	uintptr_t nunits = (uintptr_t) print_info.extra;
+	int elt;
+
+	if (nunits == 0
+	    || !CONST_INT_P (x)
+	    || (elt = exact_log2 (INTVAL (x))) < 0)
+	  {
+	    output_operand_lossage ("invalid operand for '%%%s'",
+				    token.c_str ());
+	    return;
+	  }
+
+	asm_fprintf (f, "%wd", ENDIAN_LANE_N (nunits, elt));
+      }
+      break;
+
     case A64_PRINT_sme_vg_end:
       if (!REG_P (x) || !FP_REGNUM_P (REGNO (x)))
 	{

Reply via email to