Index: clang/lib/Headers/altivec.h =================================================================== --- clang/lib/Headers/altivec.h +++ clang/lib/Headers/altivec.h @@ -17094,6 +17094,61 @@ vector unsigned long long __c) { return __builtin_vsx_xxblendvd(__a, __b, __c); } + +/* vec_splati */ + +#define vec_splati(__a) \ + _Generic((__a), signed int \ + : ((vector signed int)__a), unsigned int \ + : ((vector unsigned int)__a), float \ + : ((vector float)__a)) + +/* vec_spatid */ + +static __inline__ vector double __ATTRS_o_ai vec_splatid(const float __a) { + return ((vector double)((double)__a)); +} + +/* vec_splati_ins */ + +static __inline__ vector signed int __ATTRS_o_ai vec_splati_ins( + vector signed int __a, const unsigned int __b, const signed int __c) { + assert((__b == 0 || __b == 1) && "The second argument must be 0 or 1"); +#ifdef __LITTLE_ENDIAN__ + __a[1 - __b] = __c; + __a[3 - __b] = __c; +#else + __a[__b] = __c; + __a[2 + __b] = __c; +#endif + return __a; +} + +static __inline__ vector unsigned int __ATTRS_o_ai vec_splati_ins( + vector unsigned int __a, const unsigned int __b, const unsigned int __c) { + assert((__b == 0 || __b == 1) && "The second argument must be 0 or 1"); +#ifdef __LITTLE_ENDIAN__ + __a[1 - __b] = __c; + __a[3 - __b] = __c; +#else + __a[__b] = __c; + __a[2 + __b] = __c; +#endif + return __a; +} + +static __inline__ vector float __ATTRS_o_ai +vec_splati_ins(vector float __a, const unsigned int __b, const float __c) { + assert((__b == 0 || __b == 1) && "The second argument must be 0 or 1"); +#ifdef __LITTLE_ENDIAN__ + __a[1 - __b] = __c; + __a[3 - __b] = __c; +#else + __a[__b] = __c; + __a[2 + __b] = __c; +#endif + return __a; +} #endif /* __VSX__ */ #endif /* __POWER10_VECTOR__ */ Index: clang/test/CodeGen/builtins-ppc-p10vector.c =================================================================== --- clang/test/CodeGen/builtins-ppc-p10vector.c +++ clang/test/CodeGen/builtins-ppc-p10vector.c @@ -512,3 +512,72 @@ // CHECK-LE-NEXT: ret <4 x i32> return vec_inserth(vuia, vuib, uia); } + +vector signed int test_vec_vec_splati_si(void) { + // CHECK-BE: ret <4 x i32> + // CHECK: ret <4 x i32> + return vec_splati(-17); +} + +vector unsigned int test_vec_vec_splati_ui(void) { + // CHECK-BE: ret <4 x i32> + // CHECK: ret <4 x i32> + return vec_splati(16U); +} + +vector float test_vec_vec_splati_f(void) { + // CHECK-BE: ret <4 x float> + // CHECK: ret <4 x float> + return vec_splati(1.0f); +} + +vector double test_vec_vec_splatid(void) { + // CHECK-BE: [[T1:%.+]] = fpext float %{{.+}} to double + // CHECK-BE-NEXT: [[T2:%.+]] = insertelement <2 x double> undef, double [[T1:%.+]], i32 0 + // CHECK-BE-NEXT: [[T3:%.+]] = shufflevector <2 x double> [[T2:%.+]], <2 x double> undef, <2 x i32> zeroinitialize + // CHECK-BE-NEXT: ret <2 x double> [[T3:%.+]] + // CHECK: [[T1:%.+]] = fpext float %{{.+}} to double + // CHECK-NEXT: [[T2:%.+]] = insertelement <2 x double> undef, double [[T1:%.+]], i32 0 + // CHECK-NEXT: [[T3:%.+]] = shufflevector <2 x double> [[T2:%.+]], <2 x double> undef, <2 x i32> zeroinitialize + // CHECK-NEXT: ret <2 x double> [[T3:%.+]] + return vec_splatid(1.0); +} + +vector signed int test_vec_vec_splati_ins_si(void) { + // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 %{{.+}} + // CHECK-BE: [[T1:%.+]] = add i32 2, %{{.+}} + // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]] + // CHECK-BE: ret <4 x i32> + // CHECK: [[T1:%.+]] = sub i32 1, %{{.+}} + // CHECK: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]] + // CHECK: [[T2:%.+]] = sub i32 3, %{{.+}} + // CHECK: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T2]] + // CHECK: ret <4 x i32> + return vec_splati_ins(vsia, 0, -17); +} + +vector unsigned int test_vec_vec_splati_ins_ui(void) { + // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 %{{.+}} + // CHECK-BE: [[T1:%.+]] = add i32 2, %{{.+}} + // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]] + // CHECK-BE: ret <4 x i32> + // CHECK: [[T1:%.+]] = sub i32 1, %{{.+}} + // CHECK: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]] + // CHECK: [[T2:%.+]] = sub i32 3, %{{.+}} + // CHECK: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T2]] + // CHECK: ret <4 x i32> + return vec_splati_ins(vuia, 1, 16U); +} + +vector float test_vec_vec_splati_ins_f(void) { + // CHECK-BE: insertelement <4 x float> %{{.+}}, float %{{.+}}, i32 %{{.+}} + // CHECK-BE: [[T1:%.+]] = add i32 2, %{{.+}} + // CHECK-BE: insertelement <4 x float> %{{.+}}, float %{{.+}}, i32 [[T1]] + // CHECK-BE: ret <4 x float> + // CHECK: [[T1:%.+]] = sub i32 1, %{{.+}} + // CHECK: insertelement <4 x float> %{{.+}}, float %{{.+}}, i32 [[T1]] + // CHECK: [[T2:%.+]] = sub i32 3, %{{.+}} + // CHECK: insertelement <4 x float> %{{.+}}, float %{{.+}}, i32 [[T2]] + // CHECK: ret <4 x float> + return vec_splati_ins(vfa, 0, 1.0f); +} Index: llvm/test/CodeGen/PowerPC/p10-splatImm.ll =================================================================== --- llvm/test/CodeGen/PowerPC/p10-splatImm.ll +++ llvm/test/CodeGen/PowerPC/p10-splatImm.ll @@ -286,3 +286,21 @@ entry: ret double 0.000000e+00 } + +define dso_local <4 x i32> @vec_splati() local_unnamed_addr { +; CHECK-LABEL: vec_splati: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xxspltiw vs34, -17 +; CHECK-NEXT: blr +entry: + ret <4 x i32> +} + +define dso_local <2 x double> @vec_splatid() local_unnamed_addr { +; CHECK-LABEL: vec_splatid: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xxspltidp vs34, 1065353216 +; CHECK-NEXT: blr +entry: + ret <2 x double> +}