@@ -805,7 +805,6 @@ rtx_is_swappable_p (rtx op, unsigned int *special)
case UNSPEC_VUPKLU_V4SF:
return 0;
case UNSPEC_VSPLT_DIRECT:
- case UNSPEC_VSX_XXSPLTD:
*special = SH_SPLAT;
return 1;
case UNSPEC_REDUC_PLUS:
@@ -296,7 +296,6 @@ (define_c_enum "unspec"
UNSPEC_VSX_XXPERM
UNSPEC_VSX_XXSPLTW
- UNSPEC_VSX_XXSPLTD
UNSPEC_VSX_DIVSD
UNSPEC_VSX_DIVUD
UNSPEC_VSX_DIVSQ
@@ -4676,16 +4675,18 @@ (define_insn "vsx_vsplt<VSX_SPLAT_SUFFIX>_di"
;; V2DF/V2DI splat for use by vec_splat builtin
(define_insn "vsx_xxspltd_<mode>"
[(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
- (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wa")
- (match_operand:QI 2 "u5bit_cint_operand" "i")]
- UNSPEC_VSX_XXSPLTD))]
+ (vec_duplicate:VSX_D
+ (vec_select:<VS_scalar>
+ (match_operand:VSX_D 1 "gpc_reg_operand" "wa")
+ (parallel [(match_operand:QI 2 "const_0_to_1_operand" "i")]))))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
{
- if ((BYTES_BIG_ENDIAN && INTVAL (operands[2]) == 0)
- || (!BYTES_BIG_ENDIAN && INTVAL (operands[2]) == 1))
- return "xxpermdi %x0,%x1,%x1,0";
- else
- return "xxpermdi %x0,%x1,%x1,3";
+ HOST_WIDE_INT dword = INTVAL (operands[2]);
+ if (!BYTES_BIG_ENDIAN)
+ dword = !dword;
+
+ operands[3] = GEN_INT (3*dword);
+ return "xxpermdi %x0,%x1,%x1,%3";
}
[(set_attr "type" "vecperm")])
@@ -1035,4 +1035,4 @@ foo156 (vector unsigned short usa)
/* { dg-final { scan-assembler-times {\mvmrglb\M} 3 } } */
/* { dg-final { scan-assembler-times {\mvmrgew\M} 4 } } */
/* { dg-final { scan-assembler-times {\mvsplth|xxsplth\M} 4 } } */
-/* { dg-final { scan-assembler-times {\mxxpermdi\M} 44 } } */
+/* { dg-final { scan-assembler-times {\mxxpermdi\M} 42 } } */
new file mode 100644
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx" } */
+
+/* Test for PR 99263, which wants to do:
+ __builtin_vec_splats (__builtin_vec_extract (v, n))
+
+ where v is a V2DF or V2DI vector and n is either 0 or 1. Previously the
+ compiler would do a direct move to the GPR registers to select the item and
+ a direct move from the GPR registers to do the splat. */
+
+vector long long
+splat_dup_ll_0 (vector long long v)
+{
+ return __builtin_vec_splats (__builtin_vec_extract (v, 0));
+}
+
+vector long long
+splat_dup_ll_1 (vector long long v)
+{
+ return __builtin_vec_splats (__builtin_vec_extract (v, 1));
+}
+
+vector double
+splat_dup_d_0 (vector double v)
+{
+ return __builtin_vec_splats (__builtin_vec_extract (v, 0));
+}
+
+vector double
+splat_dup_d_1 (vector double v)
+{
+ return __builtin_vec_splats (__builtin_vec_extract (v, 1));
+}
+
+/* { dg-final { scan-assembler-times {\mxxpermdi\M} 4 } } */