diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -333,6 +333,16 @@ BUILTIN(__builtin_altivec_vpdepd, "V2ULLiV2ULLiV2ULLi", "") BUILTIN(__builtin_altivec_vpextd, "V2ULLiV2ULLiV2ULLi", "") +// P10 Vector String Isolate Built-ins. +BUILTIN(__builtin_altivec_vstribr, "V16cV16c", "") +BUILTIN(__builtin_altivec_vstribl, "V16cV16c", "") +BUILTIN(__builtin_altivec_vstrihr, "V8sV8s", "") +BUILTIN(__builtin_altivec_vstrihl, "V8sV8s", "") +BUILTIN(__builtin_altivec_vstribr_p, "iiV16c", "") +BUILTIN(__builtin_altivec_vstribl_p, "iiV16c", "") +BUILTIN(__builtin_altivec_vstrihr_p, "iiV8s", "") +BUILTIN(__builtin_altivec_vstrihl_p, "iiV8s", "") + // P10 Vector Centrifuge built-in. BUILTIN(__builtin_altivec_vcfuged, "V2ULLiV2ULLiV2ULLi", "") diff --git a/clang/lib/Headers/altivec.h b/clang/lib/Headers/altivec.h --- a/clang/lib/Headers/altivec.h +++ b/clang/lib/Headers/altivec.h @@ -17575,6 +17575,150 @@ } #endif /* __VSX__ */ +/* vec_stril */ + +static __inline__ vector unsigned char __ATTRS_o_ai +vec_stril(vector unsigned char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstribr((vector signed char)__a); +#else + return __builtin_altivec_vstribl((vector signed char)__a); +#endif +} + +static __inline__ vector signed char __ATTRS_o_ai +vec_stril(vector signed char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstribr(__a); +#else + return __builtin_altivec_vstribl(__a); +#endif +} + +static __inline__ vector unsigned short __ATTRS_o_ai +vec_stril(vector unsigned short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstrihr((vector signed short)__a); +#else + return __builtin_altivec_vstrihl((vector signed short)__a); +#endif +} + +static __inline__ vector signed short __ATTRS_o_ai +vec_stril(vector signed short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstrihr(__a); +#else + return __builtin_altivec_vstrihl(__a); +#endif +} + +/* vec_stril_p */ + +static __inline__ int __ATTRS_o_ai vec_stril_p(vector unsigned char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstribr_p(__CR6_EQ, (vector signed char) __a); +#else + return __builtin_altivec_vstribl_p(__CR6_EQ, (vector signed char)__a); +#endif +} + +static __inline__ int __ATTRS_o_ai vec_stril_p(vector signed char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstribr_p(__CR6_EQ, __a); +#else + return __builtin_altivec_vstribl_p(__CR6_EQ, __a); +#endif +} + +static __inline__ int __ATTRS_o_ai vec_stril_p(vector unsigned short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstrihr_p(__CR6_EQ, (vector signed short)__a); +#else + return __builtin_altivec_vstrihl_p(__CR6_EQ, (vector signed short)__a); +#endif +} + +static __inline__ int __ATTRS_o_ai vec_stril_p(vector signed short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstrihr_p(__CR6_EQ, __a); +#else + return __builtin_altivec_vstrihl_p(__CR6_EQ, __a); +#endif +} + +/* vec_strir */ + +static __inline__ vector unsigned char __ATTRS_o_ai +vec_strir(vector unsigned char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstribl((vector signed char)__a); +#else + return __builtin_altivec_vstribr((vector signed char)__a); +#endif +} + +static __inline__ vector signed char __ATTRS_o_ai +vec_strir(vector signed char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstribl(__a); +#else + return __builtin_altivec_vstribr(__a); +#endif +} + +static __inline__ vector unsigned short __ATTRS_o_ai +vec_strir(vector unsigned short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstrihl((vector signed short)__a); +#else + return __builtin_altivec_vstrihr((vector signed short)__a); +#endif +} + +static __inline__ vector signed short __ATTRS_o_ai +vec_strir(vector signed short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstrihl(__a); +#else + return __builtin_altivec_vstrihr(__a); +#endif +} + +/* vec_strir_p */ + +static __inline__ int __ATTRS_o_ai vec_strir_p(vector unsigned char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstribl_p(__CR6_EQ, (vector signed char) __a); +#else + return __builtin_altivec_vstribr_p(__CR6_EQ, (vector signed char)__a); +#endif +} + +static __inline__ int __ATTRS_o_ai vec_strir_p(vector signed char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstribl_p(__CR6_EQ, __a); +#else + return __builtin_altivec_vstribr_p(__CR6_EQ, __a); +#endif +} + +static __inline__ int __ATTRS_o_ai vec_strir_p(vector unsigned short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstrihl_p(__CR6_EQ, (vector signed short)__a); +#else + return __builtin_altivec_vstrihr_p(__CR6_EQ, (vector signed short)__a); +#endif +} + +static __inline__ int __ATTRS_o_ai vec_strir_p(vector signed short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vstrihl_p(__CR6_EQ, __a); +#else + return __builtin_altivec_vstrihr_p(__CR6_EQ, __a); +#endif +} + /* vs[l | r | ra] */ static __inline__ vector unsigned __int128 __ATTRS_o_ai diff --git a/clang/test/CodeGen/builtins-ppc-p10vector.c b/clang/test/CodeGen/builtins-ppc-p10vector.c --- a/clang/test/CodeGen/builtins-ppc-p10vector.c +++ b/clang/test/CodeGen/builtins-ppc-p10vector.c @@ -165,6 +165,318 @@ return vec_pext(vulla, vullb); } +vector unsigned char test_vec_stril_uc(void) { + // CHECK-BE: @llvm.ppc.altivec.vstribl(<16 x i8> %{{.+}}) + // CHECK-BE-NEXT: ret <16 x i8> + // CHECK-LE: @llvm.ppc.altivec.vstribr(<16 x i8> %{{.+}}) + // CHECK-LE-NEXT: ret <16 x i8> + return vec_stril(vuca); +} + +vector signed char test_vec_stril_sc(void) { + // CHECK-BE: @llvm.ppc.altivec.vstribl(<16 x i8> %{{.+}}) + // CHECK-BE-NEXT: ret <16 x i8> + // CHECK-LE: @llvm.ppc.altivec.vstribr(<16 x i8> %{{.+}}) + // CHECK-LE-NEXT: ret <16 x i8> + return vec_stril(vsca); +} + +vector unsigned short test_vec_stril_us(void) { + // CHECK-BE: @llvm.ppc.altivec.vstrihl(<8 x i16> %{{.+}}) + // CHECK-BE-NEXT: ret <8 x i16> + // CHECK-LE: @llvm.ppc.altivec.vstrihr(<8 x i16> %{{.+}}) + // CHECK-LE-NEXT: ret <8 x i16> + return vec_stril(vusa); +} + +vector signed short test_vec_stril_ss(void) { + // CHECK-BE: @llvm.ppc.altivec.vstrihl(<8 x i16> %{{.+}}) + // CHECK-BE-NEXT: ret <8 x i16> + // CHECK-LE: @llvm.ppc.altivec.vstrihr(<8 x i16> %{{.+}}) + // CHECK-LE-NEXT: ret <8 x i16> + return vec_stril(vssa); +} + +int test_vec_stril_p_uc(void) { + // CHECK-BE: @llvm.ppc.altivec.vstribl.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-BE-NEXT: ret i32 + // CHECK-LE: @llvm.ppc.altivec.vstribr.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-LE-NEXT: ret i32 + return vec_stril_p(vuca); +} + +int test_vec_stril_p_sc(void) { + // CHECK-BE: @llvm.ppc.altivec.vstribl.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-BE-NEXT: ret i32 + // CHECK-LE: @llvm.ppc.altivec.vstribr.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-LE-NEXT: ret i32 + return vec_stril_p(vsca); +} + +int test_vec_stril_p_us(void) { + // CHECK-BE: @llvm.ppc.altivec.vstrihl.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-BE-NEXT: ret i32 + // CHECK-LE: @llvm.ppc.altivec.vstrihr.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-LE-NEXT: ret i32 + return vec_stril_p(vusa); +} + +int test_vec_stril_p_ss(void) { + // CHECK-BE: @llvm.ppc.altivec.vstrihl.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-BE-NEXT: ret i32 + // CHECK-LE: @llvm.ppc.altivec.vstrihr.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-LE-NEXT: ret i32 + return vec_stril_p(vssa); +} + +vector unsigned char test_vec_stril_p_uc_2(vector unsigned char *ptr, int len) { + // CHECK-BE: icmp slt i32 + // CHECK-BE: br i1 + // CHECK-BE: for.body: + // CHECK-BE: @llvm.ppc.altivec.vstribl.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-BE: if.then: + // CHECK-BE: @llvm.ppc.altivec.vstribl(<16 x i8> %{{.+}}) + // CHECK-BE: ret <16 x i8> + // CHECK-LE: icmp slt i32 + // CHECK-LE: br i1 + // CHECK-LE: for.body: + // CHECK-LE: @llvm.ppc.altivec.vstribr.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-LE: if.then: + // CHECK-LE: @llvm.ppc.altivec.vstribr(<16 x i8> %{{.+}}) + // CHECK-LE: ret <16 x i8> + for (int i = 0; i < len; i++) { + if (vec_stril_p(*(ptr + i))) { + return vec_stril(*(ptr + i)); + } + } + return vec_stril(*(ptr)); +} + +vector signed char test_vec_stril_p_sc_2(vector signed char *ptr, int len) { + // CHECK-BE: icmp slt i32 + // CHECK-BE: br i1 + // CHECK-BE: for.body: + // CHECK-BE: @llvm.ppc.altivec.vstribl.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-BE: if.then: + // CHECK-BE: @llvm.ppc.altivec.vstribl(<16 x i8> %{{.+}}) + // CHECK-BE: ret <16 x i8> + // CHECK-LE: icmp slt i32 + // CHECK-LE: br i1 + // CHECK-LE: for.body: + // CHECK-LE: @llvm.ppc.altivec.vstribr.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-LE: if.then: + // CHECK-LE: @llvm.ppc.altivec.vstribr(<16 x i8> %{{.+}}) + // CHECK-LE: ret <16 x i8> + for (int i = 0; i < len; i++) { + if (vec_stril_p(*(ptr + i))) { + return vec_stril(*(ptr + i)); + } + } + return vec_stril(*(ptr)); +} + +vector unsigned short test_vec_stril_p_us_2(vector unsigned short *ptr, int len) { + // CHECK-BE: icmp slt i32 + // CHECK-BE: br i1 + // CHECK-BE: for.body: + // CHECK-BE: @llvm.ppc.altivec.vstrihl.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-BE: if.then: + // CHECK-BE: @llvm.ppc.altivec.vstrihl(<8 x i16> %{{.+}}) + // CHECK-BE: ret <8 x i16> + // CHECK-LE: icmp slt i32 + // CHECK-LE: br i1 + // CHECK-LE: for.body: + // CHECK-LE: @llvm.ppc.altivec.vstrihr.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-LE: if.then: + // CHECK-LE: @llvm.ppc.altivec.vstrihr(<8 x i16> %{{.+}}) + // CHECK-LE: ret <8 x i16> + for (int i = 0; i < len; i++) { + if (vec_stril_p(*(ptr + i))) { + return vec_stril(*(ptr + i)); + } + } + return vec_stril(*(ptr)); +} + +vector signed short test_vec_stril_p_ss_2(vector signed short *ptr, int len) { + // CHECK-BE: icmp slt i32 + // CHECK-BE: br i1 + // CHECK-BE: for.body: + // CHECK-BE: @llvm.ppc.altivec.vstrihl.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-BE: if.then: + // CHECK-BE: @llvm.ppc.altivec.vstrihl(<8 x i16> %{{.+}}) + // CHECK-BE: ret <8 x i16> + // CHECK-LE: icmp slt i32 + // CHECK-LE: br i1 + // CHECK-LE: for.body: + // CHECK-LE: @llvm.ppc.altivec.vstrihr.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-LE: if.then: + // CHECK-LE: @llvm.ppc.altivec.vstrihr(<8 x i16> %{{.+}}) + // CHECK-LE: ret <8 x i16> + for (int i = 0; i < len; i++) { + if (vec_stril_p(*(ptr + i))) { + return vec_stril(*(ptr + i)); + } + } + return vec_stril(*(ptr)); +} + +vector unsigned char test_vec_strir_uc(void) { + // CHECK-BE: @llvm.ppc.altivec.vstribr(<16 x i8> %{{.+}}) + // CHECK-BE-NEXT: ret <16 x i8> + // CHECK-LE: @llvm.ppc.altivec.vstribl(<16 x i8> %{{.+}}) + // CHECK-LE-NEXT: ret <16 x i8> + return vec_strir(vuca); +} + +vector signed char test_vec_strir_sc(void) { + // CHECK-BE: @llvm.ppc.altivec.vstribr(<16 x i8> %{{.+}}) + // CHECK-BE-NEXT: ret <16 x i8> + // CHECK-LE: @llvm.ppc.altivec.vstribl(<16 x i8> %{{.+}}) + // CHECK-LE-NEXT: ret <16 x i8> + return vec_strir(vsca); +} + +vector unsigned short test_vec_strir_us(void) { + // CHECK-BE: @llvm.ppc.altivec.vstrihr(<8 x i16> %{{.+}}) + // CHECK-BE-NEXT: ret <8 x i16> + // CHECK-LE: @llvm.ppc.altivec.vstrihl(<8 x i16> %{{.+}}) + // CHECK-LE-NEXT: ret <8 x i16> + return vec_strir(vusa); +} + +vector signed short test_vec_strir_ss(void) { + // CHECK-BE: @llvm.ppc.altivec.vstrihr(<8 x i16> %{{.+}}) + // CHECK-BE-NEXT: ret <8 x i16> + // CHECK-LE: @llvm.ppc.altivec.vstrihl(<8 x i16> %{{.+}}) + // CHECK-LE-NEXT: ret <8 x i16> + return vec_strir(vssa); +} + +int test_vec_strir_p_uc(void) { + // CHECK-BE: @llvm.ppc.altivec.vstribr.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-BE-NEXT: ret i32 + // CHECK-LE: @llvm.ppc.altivec.vstribl.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-LE-NEXT: ret i32 + return vec_strir_p(vuca); +} + +int test_vec_strir_p_sc(void) { + // CHECK-BE: @llvm.ppc.altivec.vstribr.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-BE-NEXT: ret i32 + // CHECK-LE: @llvm.ppc.altivec.vstribl.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-LE-NEXT: ret i32 + return vec_strir_p(vsca); +} + +int test_vec_strir_p_us(void) { + // CHECK-BE: @llvm.ppc.altivec.vstrihr.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-BE-NEXT: ret i32 + // CHECK-LE: @llvm.ppc.altivec.vstrihl.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-LE-NEXT: ret i32 + return vec_strir_p(vusa); +} + +int test_vec_strir_p_ss(void) { + // CHECK-BE: @llvm.ppc.altivec.vstrihr.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-BE-NEXT: ret i32 + // CHECK-LE: @llvm.ppc.altivec.vstrihl.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-LE-NEXT: ret i32 + return vec_strir_p(vssa); +} + +vector unsigned char test_vec_strir_p_uc_2(vector unsigned char *ptr, int len) { + // CHECK-BE: icmp slt i32 + // CHECK-BE: br i1 + // CHECK-BE: for.body: + // CHECK-BE: @llvm.ppc.altivec.vstribr.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-BE: if.then: + // CHECK-BE: @llvm.ppc.altivec.vstribr(<16 x i8> %{{.+}}) + // CHECK-BE: ret <16 x i8> + // CHECK-LE: icmp slt i32 + // CHECK-LE: br i1 + // CHECK-LE: for.body: + // CHECK-LE: @llvm.ppc.altivec.vstribl.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-LE: if.then: + // CHECK-LE: @llvm.ppc.altivec.vstribl(<16 x i8> %{{.+}}) + // CHECK-LE: ret <16 x i8> + for (int i = 0; i < len; i++) { + if (vec_strir_p(*(ptr + i))) { + return vec_strir(*(ptr + i)); + } + } + return vec_strir(*(ptr)); +} + +vector signed char test_vec_strir_p_sc_2(vector signed char *ptr, int len) { + // CHECK-BE: icmp slt i32 + // CHECK-BE: br i1 + // CHECK-BE: for.body: + // CHECK-BE: @llvm.ppc.altivec.vstribr.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-BE: if.then: + // CHECK-BE: @llvm.ppc.altivec.vstribr(<16 x i8> %{{.+}}) + // CHECK-BE: ret <16 x i8> + // CHECK-LE: icmp slt i32 + // CHECK-LE: br i1 + // CHECK-LE: for.body: + // CHECK-LE: @llvm.ppc.altivec.vstribl.p(i32 0, <16 x i8> %{{.+}}) + // CHECK-LE: if.then: + // CHECK-LE: @llvm.ppc.altivec.vstribl(<16 x i8> %{{.+}}) + // CHECK-LE: ret <16 x i8> + for (int i = 0; i < len; i++) { + if (vec_strir_p(*(ptr + i))) { + return vec_strir(*(ptr + i)); + } + } + return vec_strir(*(ptr)); +} + +vector unsigned short test_vec_strir_p_us_2(vector unsigned short *ptr, int len) { + // CHECK-BE: icmp slt i32 + // CHECK-BE: br i1 + // CHECK-BE: for.body: + // CHECK-BE: @llvm.ppc.altivec.vstrihr.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-BE: if.then: + // CHECK-BE: @llvm.ppc.altivec.vstrihr(<8 x i16> %{{.+}}) + // CHECK-BE: ret <8 x i16> + // CHECK-LE: icmp slt i32 + // CHECK-LE: br i1 + // CHECK-LE: for.body: + // CHECK-LE: @llvm.ppc.altivec.vstrihl.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-LE: if.then: + // CHECK-LE: @llvm.ppc.altivec.vstrihl(<8 x i16> %{{.+}}) + // CHECK-LE: ret <8 x i16> + for (int i = 0; i < len; i++) { + if (vec_strir_p(*(ptr + i))) { + return vec_strir(*(ptr + i)); + } + } + return vec_strir(*(ptr)); +} + +vector signed short test_vec_strir_p_ss_2(vector signed short *ptr, int len) { + // CHECK-BE: icmp slt i32 + // CHECK-BE: br i1 + // CHECK-BE: for.body: + // CHECK-BE: @llvm.ppc.altivec.vstrihr.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-BE: if.then: + // CHECK-BE: @llvm.ppc.altivec.vstrihr(<8 x i16> %{{.+}}) + // CHECK-BE: ret <8 x i16> + // CHECK-LE: icmp slt i32 + // CHECK-LE: br i1 + // CHECK-LE: for.body: + // CHECK-LE: @llvm.ppc.altivec.vstrihl.p(i32 0, <8 x i16> %{{.+}}) + // CHECK-LE: if.then: + // CHECK-LE: @llvm.ppc.altivec.vstrihl(<8 x i16> %{{.+}}) + // CHECK-LE: ret <8 x i16> + for (int i = 0; i < len; i++) { + if (vec_strir_p(*(ptr + i))) { + return vec_strir(*(ptr + i)); + } + } + return vec_strir(*(ptr)); +} + unsigned int test_vec_extractm_uc(void) { // CHECK: @llvm.ppc.altivec.vextractbm(<16 x i8> %{{.+}}) // CHECK-NEXT: ret i32 diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -475,6 +475,25 @@ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + // P10 Vector String Isolate Intrinsics. + def int_ppc_altivec_vstribr : GCCBuiltin<"__builtin_altivec_vstribr">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vstribl : GCCBuiltin<"__builtin_altivec_vstribl">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vstrihr : GCCBuiltin<"__builtin_altivec_vstrihr">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vstrihl : GCCBuiltin<"__builtin_altivec_vstrihl">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; + // Predicate Intrinsics: The first operand specifies interpretation of CR6. + def int_ppc_altivec_vstribr_p : GCCBuiltin<"__builtin_altivec_vstribr_p">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vstribl_p : GCCBuiltin<"__builtin_altivec_vstribl_p">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vstrihr_p : GCCBuiltin<"__builtin_altivec_vstrihr_p">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vstrihl_p : GCCBuiltin<"__builtin_altivec_vstrihl_p">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_v8i16_ty], [IntrNoMem]>; + // P10 Vector Centrifuge Builtin. def int_ppc_altivec_vcfuged : GCCBuiltin<"__builtin_altivec_vcfuged">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -42,6 +42,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/IntrinsicsPowerPC.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" @@ -4675,6 +4676,44 @@ } break; + case ISD::INTRINSIC_WO_CHAIN: { + if (!PPCSubTarget->isISA3_1()) + break; + unsigned Opcode = 0; + switch (N->getConstantOperandVal(0)) { + default: break; + case Intrinsic::ppc_altivec_vstribr_p: + Opcode = PPC::VSTRIBR_rec; + break; + case Intrinsic::ppc_altivec_vstribl_p: + Opcode = PPC::VSTRIBL_rec; + break; + case Intrinsic::ppc_altivec_vstrihr_p: + Opcode = PPC::VSTRIHR_rec; + break; + case Intrinsic::ppc_altivec_vstrihl_p: + Opcode = PPC::VSTRIHL_rec; + break; + } + if (!Opcode) + break; + + // Generate the appropriate vector string isolate intrinsic to match. + EVT VTs[] = { MVT::v16i8, MVT::Glue }; + SDValue VecStrOp = + SDValue(CurDAG->getMachineNode(Opcode, dl, VTs, N->getOperand(2)), 0); + // Vector string isolate instructions update the EQ bit of CR6. + // Generate a SETBC instruction to extract the bit and place it in a GPR. + SDValue SubRegIdx = CurDAG->getTargetConstant(PPC::sub_eq, dl, MVT::i32); + SDValue CR6Reg = CurDAG->getRegister(PPC::CR6, MVT::i32); + SDValue CRBit = + SDValue(CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, + MVT::i1, CR6Reg, SubRegIdx, + VecStrOp.getValue(1)), 0); + CurDAG->SelectNodeTo(N, PPC::SETBC, MVT::i32, CRBit); + return; + } + case ISD::SETCC: case ISD::STRICT_FSETCC: case ISD::STRICT_FSETCCS: diff --git a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td --- a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td +++ b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td @@ -921,13 +921,21 @@ v16i8:$VRB, i32:$SH))]>; defm VSTRIBR : VXForm_VTB5_RCr<13, 1, (outs vrrc:$vT), (ins vrrc:$vB), - "vstribr", "$vT, $vB", IIC_VecGeneral, []>; + "vstribr", "$vT, $vB", IIC_VecGeneral, + [(set v16i8:$vT, + (int_ppc_altivec_vstribr v16i8:$vB))]>; defm VSTRIBL : VXForm_VTB5_RCr<13, 0, (outs vrrc:$vT), (ins vrrc:$vB), - "vstribl", "$vT, $vB", IIC_VecGeneral, []>; + "vstribl", "$vT, $vB", IIC_VecGeneral, + [(set v16i8:$vT, + (int_ppc_altivec_vstribl v16i8:$vB))]>; defm VSTRIHR : VXForm_VTB5_RCr<13, 3, (outs vrrc:$vT), (ins vrrc:$vB), - "vstrihr", "$vT, $vB", IIC_VecGeneral, []>; + "vstrihr", "$vT, $vB", IIC_VecGeneral, + [(set v8i16:$vT, + (int_ppc_altivec_vstrihr v8i16:$vB))]>; defm VSTRIHL : VXForm_VTB5_RCr<13, 2, (outs vrrc:$vT), (ins vrrc:$vB), - "vstrihl", "$vT, $vB", IIC_VecGeneral, []>; + "vstrihl", "$vT, $vB", IIC_VecGeneral, + [(set v8i16:$vT, + (int_ppc_altivec_vstrihl v8i16:$vB))]>; def VINSW : VXForm_1<207, (outs vrrc:$vD), (ins vrrc:$vDi, u4imm:$UIM, gprc:$rB), "vinsw $vD, $rB, $UIM", IIC_VecGeneral, diff --git a/llvm/test/CodeGen/PowerPC/p10-string-ops.ll b/llvm/test/CodeGen/PowerPC/p10-string-ops.ll --- a/llvm/test/CodeGen/PowerPC/p10-string-ops.ll +++ b/llvm/test/CodeGen/PowerPC/p10-string-ops.ll @@ -2,6 +2,9 @@ ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ ; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ ; RUN: FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ +; RUN: FileCheck %s ; These test cases aim to test the vector string isolate builtins on Power10. @@ -27,3 +30,97 @@ %tmp = tail call <16 x i8> @llvm.ppc.altivec.vclrrb(<16 x i8> %a, i32 %n) ret <16 x i8> %tmp } + +declare <16 x i8> @llvm.ppc.altivec.vstribr(<16 x i8>) +declare <16 x i8> @llvm.ppc.altivec.vstribl(<16 x i8>) +declare <8 x i16> @llvm.ppc.altivec.vstrihr(<8 x i16>) +declare <8 x i16> @llvm.ppc.altivec.vstrihl(<8 x i16>) + +declare i32 @llvm.ppc.altivec.vstribr.p(i32, <16 x i8>) +declare i32 @llvm.ppc.altivec.vstribl.p(i32, <16 x i8>) +declare i32 @llvm.ppc.altivec.vstrihr.p(i32, <8 x i16>) +declare i32 @llvm.ppc.altivec.vstrihl.p(i32, <8 x i16>) + +define <16 x i8> @test_vstribr(<16 x i8> %a) { +; CHECK-LABEL: test_vstribr: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vstribr v2, v2 +; CHECK-NEXT: blr +entry: + %tmp = tail call <16 x i8> @llvm.ppc.altivec.vstribr(<16 x i8> %a) + ret <16 x i8> %tmp +} + +define <16 x i8> @test_vstribl(<16 x i8> %a) { +; CHECK-LABEL: test_vstribl: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vstribl v2, v2 +; CHECK-NEXT: blr +entry: + %tmp = tail call <16 x i8> @llvm.ppc.altivec.vstribl(<16 x i8>%a) + ret <16 x i8> %tmp +} + +define <8 x i16> @test_vstrihr(<8 x i16> %a) { +; CHECK-LABEL: test_vstrihr: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vstrihr v2, v2 +; CHECK-NEXT: blr +entry: + %tmp = tail call <8 x i16> @llvm.ppc.altivec.vstrihr(<8 x i16> %a) + ret <8 x i16> %tmp +} + +define <8 x i16> @test_vstrihl(<8 x i16> %a) { +; CHECK-LABEL: test_vstrihl: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vstrihl v2, v2 +; CHECK-NEXT: blr +entry: + %tmp = tail call <8 x i16> @llvm.ppc.altivec.vstrihl(<8 x i16> %a) + ret <8 x i16> %tmp +} + +define i32 @test_vstribr_p(<16 x i8> %a) { +; CHECK-LABEL: test_vstribr_p: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vstribr. v2, v2 +; CHECK-NEXT: setbc r3, 4*cr6+eq +; CHECK-NEXT: blr +entry: + %tmp = tail call i32 @llvm.ppc.altivec.vstribr.p(i32 1, <16 x i8> %a) + ret i32 %tmp +} + +define i32 @test_vstribl_p(<16 x i8> %a) { +; CHECK-LABEL: test_vstribl_p: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vstribl. v2, v2 +; CHECK-NEXT: setbc r3, 4*cr6+eq +; CHECK-NEXT: blr +entry: + %tmp = tail call i32 @llvm.ppc.altivec.vstribl.p(i32 1, <16 x i8> %a) + ret i32 %tmp +} + +define i32 @test_vstrihr_p(<8 x i16> %a) { +; CHECK-LABEL: test_vstrihr_p: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vstrihr. v2, v2 +; CHECK-NEXT: setbc r3, 4*cr6+eq +; CHECK-NEXT: blr +entry: + %tmp = tail call i32 @llvm.ppc.altivec.vstrihr.p(i32 1, <8 x i16> %a) + ret i32 %tmp +} + +define i32 @test_vstrihl_p(<8 x i16> %a) { +; CHECK-LABEL: test_vstrihl_p: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vstrihl. v2, v2 +; CHECK-NEXT: setbc r3, 4*cr6+eq +; CHECK-NEXT: blr +entry: + %tmp = tail call i32 @llvm.ppc.altivec.vstrihl.p(i32 1, <8 x i16> %a) + ret i32 %tmp +}