Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -8408,6 +8408,39 @@ return CGF.Builder.CreateSExt(Mask, DstTy, "vpmovm2"); } +// Lowers PSAD intrinsics to native IR. +static Value *EmitX86SAD(CodeGenFunction &CGF, ArrayRef Ops) { + // The operands arrive already bitcast to byte vectors. + Value *A = Ops[0]; + Value *B = Ops[1]; + // N shows the corresponding number of qwords. + unsigned N = (cast(A->getType()))->getBitWidth() / 64; + + Value *Cmp = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGT, A, B); + Value *AD = CGF.Builder.CreateSelect(Cmp, CGF.Builder.CreateSub(A, B), + CGF.Builder.CreateSub(B, A)); + + llvm::Type *QTy = CGF.Builder.getInt64Ty(); + llvm::Type *VTy = llvm::VectorType::get(QTy, N); + llvm::Type *BTy = llvm::VectorType::get(CGF.Builder.getInt8Ty(), N * 8); + SmallVector ShuffleMask; + for (unsigned i = 0; i < N; ++i) + ShuffleMask.push_back(i * 8); + Value *Res = + CGF.Builder.CreateZExt(CGF.Builder.CreateShuffleVector( + AD, llvm::UndefValue::get(BTy), ShuffleMask), + VTy); + for (unsigned i = 1; i < 8; ++i) { + ShuffleMask.clear(); + for (unsigned j = 0; j < N; ++j) + ShuffleMask.push_back(i + j * 8); + Value *Sum = CGF.Builder.CreateShuffleVector(AD, llvm::UndefValue::get(BTy), + ShuffleMask); + Res = CGF.Builder.CreateAdd(Res, CGF.Builder.CreateZExt(Sum, VTy)); + } + return Res; +} + Value *CodeGenFunction::EmitX86CpuIs(const CallExpr *E) { const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); StringRef CPUStr = cast(CPUExpr)->getString(); @@ -9052,6 +9085,11 @@ case X86::BI__builtin_ia32_pabsq512_mask: return EmitX86Abs(*this, Ops); + case X86::BI__builtin_ia32_psadbw128: + case X86::BI__builtin_ia32_psadbw256: + case X86::BI__builtin_ia32_psadbw512: + return EmitX86SAD(*this, Ops); + case X86::BI__builtin_ia32_pmaxsb128: case X86::BI__builtin_ia32_pmaxsw128: case X86::BI__builtin_ia32_pmaxsd128: Index: clang/test/CodeGen/avx2-builtins.c =================================================================== --- clang/test/CodeGen/avx2-builtins.c +++ clang/test/CodeGen/avx2-builtins.c @@ -943,7 +943,33 @@ __m256i test_mm256_sad_epu8(__m256i x, __m256i y) { // CHECK-LABEL: test_mm256_sad_epu8 - // CHECK: call <4 x i64> @llvm.x86.avx2.psad.bw(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) + // CHECK: %{{.*}} = icmp ugt <32 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = sub <32 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = sub <32 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} + // CHECK: %{{.*}} = shufflevector <32 x i8> %{{.*}}, <32 x i8> undef, <4 x i32> + // CHECK: %{{.*}} = zext <4 x i8> %{{.*}} to <4 x i64> + // CHECK: %{{.*}} = shufflevector <32 x i8> %{{.*}}, <32 x i8> undef, <4 x i32> + // CHECK: %{{.*}} = zext <4 x i8> %{{.*}} to <4 x i64> + // CHECK: %{{.*}} = add <4 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <32 x i8> %{{.*}}, <32 x i8> undef, <4 x i32> + // CHECK: %{{.*}} = zext <4 x i8> %{{.*}} to <4 x i64> + // CHECK: %{{.*}} = add <4 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <32 x i8> %{{.*}}, <32 x i8> undef, <4 x i32> + // CHECK: %{{.*}} = zext <4 x i8> %{{.*}} to <4 x i64> + // CHECK: %{{.*}} = add <4 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <32 x i8> %{{.*}}, <32 x i8> undef, <4 x i32> + // CHECK: %{{.*}} = zext <4 x i8> %{{.*}} to <4 x i64> + // CHECK: %{{.*}} = add <4 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <32 x i8> %{{.*}}, <32 x i8> undef, <4 x i32> + // CHECK: %{{.*}} = zext <4 x i8> %{{.*}} to <4 x i64> + // CHECK: %{{.*}} = add <4 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <32 x i8> %{{.*}}, <32 x i8> undef, <4 x i32> + // CHECK: %{{.*}} = zext <4 x i8> %{{.*}} to <4 x i64> + // CHECK: %{{.*}} = add <4 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <32 x i8> %{{.*}}, <32 x i8> undef, <4 x i32> + // CHECK: %{{.*}} = zext <4 x i8> %{{.*}} to <4 x i64> + // CHECK: %{{.*}} = add <4 x i64> %{{.*}}, %{{.*}} return _mm256_sad_epu8(x, y); } Index: clang/test/CodeGen/avx512bw-builtins.c =================================================================== --- clang/test/CodeGen/avx512bw-builtins.c +++ clang/test/CodeGen/avx512bw-builtins.c @@ -1945,7 +1945,33 @@ __m512i test_mm512_sad_epu8(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_sad_epu8 - // CHECK: @llvm.x86.avx512.psad.bw.512 + // CHECK: %{{.*}} = icmp ugt <64 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = sub <64 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = sub <64 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} + // CHECK: %{{.*}} = shufflevector <64 x i8> %{{.*}}, <64 x i8> undef, <8 x i32> + // CHECK: %{{.*}} = zext <8 x i8> %{{.*}} to <8 x i64> + // CHECK: %{{.*}} = shufflevector <64 x i8> %{{.*}}, <64 x i8> undef, <8 x i32> + // CHECK: %{{.*}} = zext <8 x i8> %{{.*}} to <8 x i64> + // CHECK: %{{.*}} = add <8 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <64 x i8> %{{.*}}, <64 x i8> undef, <8 x i32> + // CHECK: %{{.*}} = zext <8 x i8> %{{.*}} to <8 x i64> + // CHECK: %{{.*}} = add <8 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <64 x i8> %{{.*}}, <64 x i8> undef, <8 x i32> + // CHECK: %{{.*}} = zext <8 x i8> %{{.*}} to <8 x i64> + // CHECK: %{{.*}} = add <8 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <64 x i8> %{{.*}}, <64 x i8> undef, <8 x i32> + // CHECK: %{{.*}} = zext <8 x i8> %{{.*}} to <8 x i64> + // CHECK: %{{.*}} = add <8 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <64 x i8> %{{.*}}, <64 x i8> undef, <8 x i32> + // CHECK: %{{.*}} = zext <8 x i8> %{{.*}} to <8 x i64> + // CHECK: %{{.*}} = add <8 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <64 x i8> %{{.*}}, <64 x i8> undef, <8 x i32> + // CHECK: %{{.*}} = zext <8 x i8> %{{.*}} to <8 x i64> + // CHECK: %{{.*}} = add <8 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <64 x i8> %{{.*}}, <64 x i8> undef, <8 x i32> + // CHECK: %{{.*}} = zext <8 x i8> %{{.*}} to <8 x i64> + // CHECK: %{{.*}} = add <8 x i64> %{{.*}}, %{{.*}} return _mm512_sad_epu8(__A, __B); } Index: clang/test/CodeGen/sse2-builtins.c =================================================================== --- clang/test/CodeGen/sse2-builtins.c +++ clang/test/CodeGen/sse2-builtins.c @@ -893,7 +893,33 @@ __m128i test_mm_sad_epu8(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_sad_epu8 - // CHECK: call <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) + // CHECK: %{{.*}} = icmp ugt <16 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = sub <16 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = sub <16 x i8> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} + // CHECK: %{{.*}} = shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <2 x i32> + // CHECK: %{{.*}} = zext <2 x i8> %{{.*}} to <2 x i64> + // CHECK: %{{.*}} = shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <2 x i32> + // CHECK: %{{.*}} = zext <2 x i8> %{{.*}} to <2 x i64> + // CHECK: %{{.*}} = add <2 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <2 x i32> + // CHECK: %{{.*}} = zext <2 x i8> %{{.*}} to <2 x i64> + // CHECK: %{{.*}} = add <2 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <2 x i32> + // CHECK: %{{.*}} = zext <2 x i8> %{{.*}} to <2 x i64> + // CHECK: %{{.*}} = add <2 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <2 x i32> + // CHECK: %{{.*}} = zext <2 x i8> %{{.*}} to <2 x i64> + // CHECK: %{{.*}} = add <2 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <2 x i32> + // CHECK: %{{.*}} = zext <2 x i8> %{{.*}} to <2 x i64> + // CHECK: %{{.*}} = add <2 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <2 x i32> + // CHECK: %{{.*}} = zext <2 x i8> %{{.*}} to <2 x i64> + // CHECK: %{{.*}} = add <2 x i64> %{{.*}}, %{{.*}} + // CHECK: %{{.*}} = shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <2 x i32> + // CHECK: %{{.*}} = zext <2 x i8> %{{.*}} to <2 x i64> + // CHECK: %{{.*}} = add <2 x i64> %{{.*}}, %{{.*}} return _mm_sad_epu8(A, B); }