#undef O_U16
#undef O_U32
+#undef O_M5
+#undef O_M12
+
#undef O_S2
#undef O_S3
#undef O_S4
#undef O_S12
#undef O_S16
#undef O_S32
+
#undef O_ELEM
#undef O_LIT
#undef O3_U32
#undef O4_U32
+#undef O1_M5
+#undef O2_M5
+#undef O3_M5
+#undef O4_M5
+
+#undef O1_M12
+#undef O2_M12
+#undef O3_M12
+#undef O4_M12
+
#undef O1_S2
#undef O2_S2
#undef O3_S2
#undef O_UIMM_P
#undef O_SIMM_P
-#define O_U1 1 /* unsigned 1 bit literal */
-#define O_U2 2 /* unsigned 2 bit literal */
-#define O_U3 3 /* unsigned 3 bit literal */
-#define O_U4 4 /* unsigned 4 bit literal */
-#define O_U5 5 /* unsigned 5 bit literal */
-#define O_U8 6 /* unsigned 8 bit literal */
-#define O_U12 7 /* unsigned 16 bit literal */
-#define O_U16 8 /* unsigned 16 bit literal */
-#define O_U32 9 /* unsigned 32 bit literal */
-
-#define O_S2 10 /* signed 2 bit literal */
-#define O_S3 11 /* signed 3 bit literal */
-#define O_S4 12 /* signed 4 bit literal */
-#define O_S5 13 /* signed 5 bit literal */
-#define O_S8 14 /* signed 8 bit literal */
-#define O_S12 15 /* signed 12 bit literal */
-#define O_S16 16 /* signed 16 bit literal */
-#define O_S32 17 /* signed 32 bit literal */
-
-#define O_ELEM 18 /* Element selector requiring modulo arithmetic. */
-#define O_LIT 19 /* Operand must be a literal fitting the target type. */
+#define O_U1 1 /* unsigned 1 bit literal */
+#define O_U2 2 /* unsigned 2 bit literal */
+#define O_U3 3 /* unsigned 3 bit literal */
+#define O_U4 4 /* unsigned 4 bit literal */
+#define O_U5 5 /* unsigned 5 bit literal */
+#define O_U8 6 /* unsigned 8 bit literal */
+#define O_U12 7 /* unsigned 16 bit literal */
+#define O_U16 8 /* unsigned 16 bit literal */
+#define O_U32 9 /* unsigned 32 bit literal */
+
+#define O_M5 10 /* matches bitmask of 5 */
+#define O_M12 11 /* matches bitmask of 12 */
+
+#define O_S2 12 /* signed 2 bit literal */
+#define O_S3 13 /* signed 3 bit literal */
+#define O_S4 14 /* signed 4 bit literal */
+#define O_S5 15 /* signed 5 bit literal */
+#define O_S8 16 /* signed 8 bit literal */
+#define O_S12 17 /* signed 12 bit literal */
+#define O_S16 18 /* signed 16 bit literal */
+#define O_S32 19 /* signed 32 bit literal */
+
+#define O_ELEM 20 /* Element selector requiring modulo arithmetic. */
+#define O_LIT 21 /* Operand must be a literal fitting the target type. */
#define O_SHIFT 5
-#define O_UIMM_P(X) ((X) >= O_U1 && (X) <= O_U32)
+#define O_UIMM_P(X) ((X) >= O_U1 && (X) <= O_M12)
#define O_SIMM_P(X) ((X) >= O_S2 && (X) <= O_S32)
#define O_IMM_P(X) ((X) == O_LIT || ((X) >= O_U1 && (X) <= O_S32))
#define O3_U32 (O_U32 << (2 * O_SHIFT))
#define O4_U32 (O_U32 << (3 * O_SHIFT))
+#define O1_M5 O_M5
+#define O2_M5 (O_M5 << O_SHIFT)
+#define O3_M5 (O_M5 << (2 * O_SHIFT))
+#define O4_M5 (O_M5 << (3 * O_SHIFT))
+
+#define O1_M12 O_M12
+#define O2_M12 (O_M12 << O_SHIFT)
+#define O3_M12 (O_M12 << (2 * O_SHIFT))
+#define O4_M12 (O_M12 << (3 * O_SHIFT))
+
#define O1_S2 O_S2
#define O2_S2 (O_S2 << O_SHIFT)
B_DEF (s390_vperm, vec_permv16qi, 0, B_VX, 0, BT_FN_UV16QI_UV16QI_UV16QI_UV16QI)
OB_DEF (s390_vec_permi, s390_vec_permi_s64, s390_vec_permi_dbl, B_VX, BT_FN_OV4SI_OV4SI_OV4SI_INT)
-OB_DEF_VAR (s390_vec_permi_s64, s390_vpdi, 0, O3_U2, BT_OV_V2DI_V2DI_V2DI_INT)
-OB_DEF_VAR (s390_vec_permi_b64, s390_vpdi, 0, O3_U2, BT_OV_BV2DI_BV2DI_BV2DI_INT)
-OB_DEF_VAR (s390_vec_permi_u64, s390_vpdi, 0, O3_U2, BT_OV_UV2DI_UV2DI_UV2DI_INT)
-OB_DEF_VAR (s390_vec_permi_dbl, s390_vpdi, 0, O3_U2, BT_OV_V2DF_V2DF_V2DF_INT)
+OB_DEF_VAR (s390_vec_permi_s64, s390_vpdi, 0, O3_M5, BT_OV_V2DI_V2DI_V2DI_INT)
+OB_DEF_VAR (s390_vec_permi_b64, s390_vpdi, 0, O3_M5, BT_OV_BV2DI_BV2DI_BV2DI_INT)
+OB_DEF_VAR (s390_vec_permi_u64, s390_vpdi, 0, O3_M5, BT_OV_UV2DI_UV2DI_UV2DI_INT)
+OB_DEF_VAR (s390_vec_permi_dbl, s390_vpdi, 0, O3_M5, BT_OV_V2DF_V2DF_V2DF_INT)
-B_DEF (s390_vpdi, vec_permiv2di, 0, B_VX, O3_U2, BT_FN_UV2DI_UV2DI_UV2DI_INT)
+B_DEF (s390_vpdi, vec_permiv2di, 0, B_VX, O3_M5, BT_FN_UV2DI_UV2DI_UV2DI_INT)
OB_DEF (s390_vec_splat, s390_vec_splat2_s8, s390_vec_splat2_dbl,B_VX, BT_FN_OV4SI_OV4SI_UCHAR)
OB_DEF_VAR (s390_vec_splat2_s8, s390_vrepb, 0, O2_U4, BT_OV_V16QI_V16QI_UCHAR)
B_DEF (s390_vtm, vec_test_mask_intv16qi,0, B_VX, 0, BT_FN_INT_UV16QI_UV16QI)
-B_DEF (s390_vec_msum_u128, vec_msumv2di, 0, B_VXE, O4_U2, BT_FN_UV16QI_UV2DI_UV2DI_UV16QI_INT)
-B_DEF (s390_vmslg, vmslg, 0, B_VXE, O4_U4, BT_FN_INT128_UV2DI_UV2DI_INT128_INT)
+B_DEF (s390_vec_msum_u128, vec_msumv2di, 0, B_VXE, O4_M12, BT_FN_UV16QI_UV2DI_UV2DI_UV16QI_INT)
+B_DEF (s390_vmslg, vmslg, 0, B_VXE, O4_M12, BT_FN_INT128_UV2DI_UV2DI_INT128_INT)
OB_DEF (s390_vec_eqv, s390_vec_eqv_b8, s390_vec_eqv_dbl_c, B_VXE, BT_FN_OV4SI_OV4SI_OV4SI)
OB_DEF_VAR (s390_vec_eqv_b8, s390_vnx, 0, 0, BT_OV_BV16QI_BV16QI_BV16QI)
{
if (O_UIMM_P (op_flags))
{
- int bitwidths[] = { 1, 2, 3, 4, 5, 8, 12, 16, 32 };
- int bitwidth = bitwidths[op_flags - O_U1];
+ unsigned HOST_WIDE_INT bitwidths[] = { 1, 2, 3, 4, 5, 8, 12, 16, 32, 4, 4 };
+ unsigned HOST_WIDE_INT bitmasks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 12 };
+ unsigned HOST_WIDE_INT bitwidth = bitwidths[op_flags - O_U1];
+ unsigned HOST_WIDE_INT bitmask = bitmasks[op_flags - O_U1];
if (!tree_fits_uhwi_p (arg)
- || tree_to_uhwi (arg) > (HOST_WIDE_INT_1U << bitwidth) - 1)
+ || tree_to_uhwi (arg) > (HOST_WIDE_INT_1U << bitwidth) - 1
+ || (bitmask && tree_to_uhwi (arg) & ~bitmask))
{
- error ("constant argument %d for builtin %qF is out of range "
- "(0..%wu)", argnum, decl,
- (HOST_WIDE_INT_1U << bitwidth) - 1);
+ if (bitmask)
+ {
+ gcc_assert (bitmask < 16);
+ char values[120] = "";
+
+ for (unsigned HOST_WIDE_INT i = 0; i <= bitmask; i++)
+ {
+ char buf[5];
+ if (i & ~bitmask)
+ continue;
+ int ret = snprintf (buf, 5, HOST_WIDE_INT_PRINT_UNSIGNED, i & bitmask);
+ gcc_assert (ret < 5);
+ strcat (values, buf);
+ if (i < bitmask)
+ strcat (values, ", ");
+ }
+ error ("constant argument %d for builtin %qF is invalid (%s)",
+ argnum, decl, values);
+ }
+ else
+ error ("constant argument %d for builtin %qF is out of range (0..%wu)",
+ argnum, decl, (HOST_WIDE_INT_1U << bitwidth) - 1);
+
return false;
}
}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -march=z14 -mzvector" } */
+
+#include <vecintrin.h>
+
+__vector unsigned char q;
+__vector unsigned short int h;
+__vector unsigned int s;
+__vector unsigned long long d;
+
+int
+main ()
+{
+ vec_msum_u128 (d, d, q, 5); /* { dg-error "constant argument 4 for builtin '__builtin_s390_vec_msum_u128' is invalid \\(0, 4, 8, 12\\)" } */
+
+ /* Using the resolved low-level builtins here makes the errors to be
+ triggered from s390_expand_builtin. Otherwise they would come
+ from the parser already preventing other errors from showing
+ up. */
+ __builtin_s390_vrepb (q, 17); /* { dg-error "constant argument 2 for builtin '__builtin_s390_vrepb' is out of range \\(0..15\\)" } */
+ __builtin_s390_vreph (h, 8); /* { dg-error "constant argument 2 for builtin '__builtin_s390_vreph' is out of range \\(0..7\\)" } */
+ __builtin_s390_vrepf (s, 4); /* { dg-error "constant argument 2 for builtin '__builtin_s390_vrepf' is out of range \\(0..3\\)" } */
+ __builtin_s390_vrepg (d, 2); /* { dg-error "constant argument 2 for builtin '__builtin_s390_vrepg' is out of range \\(0..1\\)" } */
+
+ __builtin_s390_vpdi (d, d, 2); /* { dg-error "constant argument 3 for builtin '__builtin_s390_vpdi' is invalid \\(0, 1, 4, 5\\)" } */
+}
--- /dev/null
+/* { dg-do run } */
+/* { dg-require-effective-target s390_vxe } */
+/* { dg-options "-O3 -mzarch -march=z14 -mzvector --save-temps" } */
+
+#include <vecintrin.h>
+
+typedef vector unsigned char uv16qi;
+typedef vector unsigned long long uv2di;
+
+uv2di a = (uv2di){ 12, 42 };
+uv2di b = (uv2di){ 54, 120 };
+uv2di c = (uv2di){ 0, 200 };
+
+int
+main ()
+{
+ uv2di result;
+
+ result = (uv2di)vec_msum_u128 (a, b, (uv16qi)c, 0);
+
+ if (result[1] != a[0] * b[0] + a[1] * b[1] + c[1])
+ __builtin_abort();
+
+ result = (uv2di)vec_msum_u128 (a, b, (uv16qi)c, 4);
+
+ if (result[1] != a[0] * b[0] + a[1] * b[1] * 2 + c[1])
+ __builtin_abort();
+
+ result = (uv2di)vec_msum_u128 (a, b, (uv16qi)c, 8);
+
+ if (result[1] != a[0] * b[0] * 2 + a[1] * b[1] + c[1])
+ __builtin_abort();
+
+ result = (uv2di)vec_msum_u128 (a, b, (uv16qi)c, 12);
+
+ if (result[1] != a[0] * b[0] * 2 + a[1] * b[1] * 2 + c[1])
+ __builtin_abort();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vmslg\t.*0" 1 } } */
+/* { dg-final { scan-assembler-times "vmslg\t.*4" 1 } } */
+/* { dg-final { scan-assembler-times "vmslg\t.*8" 1 } } */
+/* { dg-final { scan-assembler-times "vmslg\t.*12" 1 } } */