@@ -181,9 +181,6 @@ int aarch64_asm_preferred_eh_data_format (int, int);
int aarch64_hard_regno_mode_ok (unsigned, enum machine_mode);
int aarch64_hard_regno_nregs (unsigned, enum machine_mode);
int aarch64_simd_attr_length_move (rtx);
-int aarch64_simd_immediate_valid_for_move (rtx, enum machine_mode, rtx *,
- int *, unsigned char *, int *,
- int *);
int aarch64_uxt_size (int, HOST_WIDE_INT);
rtx aarch64_final_eh_return_addr (void);
rtx aarch64_legitimize_reload_address (rtx *, enum machine_mode, int, int, int);
@@ -93,6 +93,7 @@ struct simd_immediate_info
int shift;
int element_width;
bool mvn;
+ bool msl;
};
/* The current code model. */
@@ -6319,16 +6320,16 @@ aarch64_simd_valid_immediate (rtx op, enum machine_mode mode, bool inverse,
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, 0, 0);
+ && 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, 0, 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, 0, 0);
+ && 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, 0, 1);
+ && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0);
@@ -6337,12 +6338,7 @@ aarch64_simd_valid_immediate (rtx op, enum machine_mode mode, bool inverse,
}
while (0);
- /* TODO: Currently the assembler cannot handle types 12 to 15.
- And there is no way to specify cmode through the compiler.
- Disable them till there is support in the assembler. */
- if (immtype == -1
- || (immtype >= 12 && immtype <= 15)
- || immtype == 18)
+ if (immtype == -1)
return false;
if (info)
@@ -6353,6 +6349,9 @@ aarch64_simd_valid_immediate (rtx op, enum machine_mode mode, bool inverse,
unsigned HOST_WIDE_INT imm = 0;
+ if (immtype >= 12 && immtype <= 15)
+ info->msl = true;
+
/* Un-invert bytes of recognized vector, if necessary. */
if (invmask != 0)
for (i = 0; i < idx; i++)
@@ -7285,10 +7284,11 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
bool is_valid;
static char templ[40];
const char *mnemonic;
+ const char *shift_op;
unsigned int lane_count = 0;
char element_char;
- struct simd_immediate_info info;
+ 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
@@ -7324,14 +7324,15 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
}
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
- ", lsl %d", mnemonic, lane_count, element_char,
- UINTVAL (info.value), info.shift);
+ ", %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));
new file mode 100644
@@ -0,0 +1,74 @@
+/* { dg-do run } */
+/* { dg-options "-O3 --save-temps -fno-inline" } */
+
+extern void abort (void);
+
+#define N 16
+
+static void
+movi_msl8 (int *__restrict a)
+{
+ int i;
+
+ /* { dg-final { scan-assembler "movi\\tv\[0-9\]+\.4s, 0xab, msl 8" } } */
+ for (i = 0; i < N; i++)
+ a[i] = 0xabff;
+}
+
+static void
+movi_msl16 (int *__restrict a)
+{
+ int i;
+
+ /* { dg-final { scan-assembler "movi\\tv\[0-9\]+\.4s, 0xab, msl 16" } } */
+ for (i = 0; i < N; i++)
+ a[i] = 0xabffff;
+}
+
+static void
+mvni_msl8 (int *__restrict a)
+{
+ int i;
+
+ /* { dg-final { scan-assembler "mvni\\tv\[0-9\]+\.4s, 0xab, msl 8" } } */
+ for (i = 0; i < N; i++)
+ a[i] = 0xffff5400;
+}
+
+static void
+mvni_msl16 (int *__restrict a)
+{
+ int i;
+
+ /* { dg-final { scan-assembler "mvni\\tv\[0-9\]+\.4s, 0xab, msl 16" } } */
+ for (i = 0; i < N; i++)
+ a[i] = 0xff540000;
+}
+
+int
+main (void)
+{
+ int a[N] = { 0 };
+ int i;
+
+#define CHECK_ARRAY(a, val) \
+ for (i = 0; i < N; i++) \
+ if (a[i] != val) \
+ abort ();
+
+ movi_msl8 (a);
+ CHECK_ARRAY (a, 0xabff);
+
+ movi_msl16 (a);
+ CHECK_ARRAY (a, 0xabffff);
+
+ mvni_msl8 (a);
+ CHECK_ARRAY (a, 0xffff5400);
+
+ mvni_msl16 (a);
+ CHECK_ARRAY (a, 0xff540000);
+
+ return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */