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 @@ -435,6 +435,8 @@ BUILTIN(__builtin_vsx_xxpermdi, "v.", "t") BUILTIN(__builtin_vsx_xxsldwi, "v.", "t") +BUILTIN(__builtin_vsx_xvtlsbb, "iV16Ucb", "") + // Float 128 built-ins BUILTIN(__builtin_sqrtf128_round_to_odd, "LLdLLd", "") BUILTIN(__builtin_addf128_round_to_odd, "LLdLLdLLd", "") 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 @@ -16830,6 +16830,22 @@ return __builtin_altivec_vclrrb((vector signed char)__a, __n); #endif } + +#ifdef __VSX__ +/* vec_test_lsbb_all_ones */ + +static __inline__ int __ATTRS_o_ai +vec_test_lsbb_all_ones(vector unsigned char __a) { + return __builtin_vsx_xvtlsbb(__a, 1); +} + +/* vec_test_lsbb_all_zeros */ + +static __inline__ int __ATTRS_o_ai +vec_test_lsbb_all_zeros(vector unsigned char __a) { + return __builtin_vsx_xvtlsbb(__a, 0); +} +#endif /* __VSX__ */ #endif /* __POWER10_VECTOR__ */ #undef __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 @@ -79,3 +79,15 @@ // CHECK-LE-NEXT: ret <16 x i8> return vec_clrr(vuca, uia); } + +int test_vec_test_lsbb_all_ones(void) { + // CHECK: @llvm.ppc.vsx.xvtlsbb(<16 x i8> %{{.+}}, i1 true + // CHECK-NEXT: ret i32 + return vec_test_lsbb_all_ones(vuca); +} + +int test_vec_test_lsbb_all_zeros(void) { + // CHECK: @llvm.ppc.vsx.xvtlsbb(<16 x i8> %{{.+}}, i1 false + // CHECK-NEXT: ret i32 + return vec_test_lsbb_all_zeros(vuca); +} 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 @@ -953,6 +953,9 @@ PowerPC_VSX_Intrinsic<"xxinsertw",[llvm_v4i32_ty], [llvm_v4i32_ty,llvm_v2i64_ty,llvm_i32_ty], [IntrNoMem]>; +def int_ppc_vsx_xvtlsbb : + PowerPC_VSX_Intrinsic<"xvtlsbb", [llvm_i32_ty], + [llvm_v16i8_ty, llvm_i1_ty], [IntrNoMem]>; def int_ppc_vsx_xxgenpcvbm : PowerPC_VSX_Intrinsic<"xxgenpcvbm", [llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; 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 @@ -177,6 +177,25 @@ let Inst{31} = XT{5}; } +// [PO BF / XO2 B XO BX /] +class XX2_BF3_XO5_XB6_XO9 opcode, bits<5> xo2, bits<9> xo, dag OOL, + dag IOL, string asmstr, InstrItinClass itin, + list pattern> + : I { + bits<3> BF; + bits<6> XB; + + let Pattern = pattern; + + let Inst{6-8} = BF; + let Inst{9-10} = 0; + let Inst{11-15} = xo2; + let Inst{16-20} = XB{4-0}; + let Inst{21-29} = xo; + let Inst{30} = XB{5}; + let Inst{31} = 0; +} + multiclass MLS_DForm_R_SI34_RTA5_MEM_p opcode, dag OOL, dag IOL, dag PCRel_IOL, string asmstr, InstrItinClass itin> { @@ -552,6 +571,8 @@ "vclrrb $vD, $vA, $rB", IIC_VecGeneral, [(set v16i8:$vD, (int_ppc_altivec_vclrrb v16i8:$vA, i32:$rB))]>; + def XVTLSBB : XX2_BF3_XO5_XB6_XO9<60, 2, 475, (outs crrc:$BF), (ins vsrc:$XB), + "xvtlsbb $BF, $XB", IIC_VecGeneral, []>; } //---------------------------- Anonymous Patterns ----------------------------// @@ -564,4 +585,8 @@ (v4i32 (COPY_TO_REGCLASS (XXGENPCVWM $VRB, imm:$IMM), VRRC))>; def : Pat<(v2i64 (int_ppc_vsx_xxgenpcvdm v2i64:$VRB, imm:$IMM)), (v2i64 (COPY_TO_REGCLASS (XXGENPCVDM $VRB, imm:$IMM), VRRC))>; + def : Pat<(i32 (int_ppc_vsx_xvtlsbb v16i8:$XB, -1)), + (EXTRACT_SUBREG (XVTLSBB (COPY_TO_REGCLASS $XB, VSRC)), sub_lt)>; + def : Pat<(i32 (int_ppc_vsx_xvtlsbb v16i8:$XB, 0)), + (EXTRACT_SUBREG (XVTLSBB (COPY_TO_REGCLASS $XB, VSRC)), sub_eq)>; } diff --git a/llvm/test/CodeGen/PowerPC/p10-vsx-builtins.ll b/llvm/test/CodeGen/PowerPC/p10-vsx-builtins.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/p10-vsx-builtins.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; 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 + +; This test case aims to test the builtins for VSX vector instructions +; on Power10. + +declare i32 @llvm.ppc.vsx.xvtlsbb(<16 x i8>, i1) + +define signext i32 @test_vec_test_lsbb_all_ones(<16 x i8> %vuca) { +; CHECK-LABEL: test_vec_test_lsbb_all_ones: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xvtlsbb cr0, v2 +; CHECK-NEXT: mfocrf r3, 128 +; CHECK-NEXT: srwi r3, r3, 31 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +entry: + %0 = tail call i32 @llvm.ppc.vsx.xvtlsbb(<16 x i8> %vuca, i1 1) + ret i32 %0 +} + +define signext i32 @test_vec_test_lsbb_all_zeros(<16 x i8> %vuca) { +; CHECK-LABEL: test_vec_test_lsbb_all_zeros: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xvtlsbb cr0, v2 +; CHECK-NEXT: mfocrf r3, 128 +; CHECK-NEXT: rlwinm r3, r3, 3, 31, 31 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +entry: + %0 = tail call i32 @llvm.ppc.vsx.xvtlsbb(<16 x i8> %vuca, i1 0) + ret i32 %0 +} diff --git a/llvm/test/MC/Disassembler/PowerPC/p10insts.txt b/llvm/test/MC/Disassembler/PowerPC/p10insts.txt --- a/llvm/test/MC/Disassembler/PowerPC/p10insts.txt +++ b/llvm/test/MC/Disassembler/PowerPC/p10insts.txt @@ -30,3 +30,6 @@ # CHECK: vclrrb 1, 4, 3 0x10 0x24 0x19 0xcd + +# CHECK: xvtlsbb 1, 7 +0xf0 0x82 0x3f 0x6c diff --git a/llvm/test/MC/PowerPC/p10.s b/llvm/test/MC/PowerPC/p10.s --- a/llvm/test/MC/PowerPC/p10.s +++ b/llvm/test/MC/PowerPC/p10.s @@ -33,3 +33,6 @@ # CHECK-BE: vclrrb 1, 4, 3 # encoding: [0x10,0x24,0x19,0xcd] # CHECK-LE: vclrrb 1, 4, 3 # encoding: [0xcd,0x19,0x24,0x10] vclrrb 1, 4, 3 +# CHECK-BE: xvtlsbb 1, 7 # encoding: [0xf0,0x82,0x3f,0x6c] +# CHECK-LE: xvtlsbb 1, 7 # encoding: [0x6c,0x3f,0x82,0xf0] + xvtlsbb 1, 7