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)))
{