Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -8408,6 +8408,40 @@ return CGF.Builder.CreateSExt(Mask, DstTy, "vpmovm2"); } +// Lowers PSAD intrinsics to native IR. +static Value *EmitX86SAD(CodeGenFunction &CGF, ArrayRef Ops, + unsigned N) { + // The operands arrive already bitcast to byte vectors, the N parameter + // showing the corresponding number of qwords. + Value *A = Ops[0]; + Value *B = Ops[1]; + + 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; + ShuffleMask.clear(); + 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), + ArrayRef(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), ArrayRef(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 +9086,13 @@ case X86::BI__builtin_ia32_pabsq512_mask: return EmitX86Abs(*this, Ops); + case X86::BI__builtin_ia32_psadbw128: + return EmitX86SAD(*this, Ops, 2); + case X86::BI__builtin_ia32_psadbw256: + return EmitX86SAD(*this, Ops, 4); + case X86::BI__builtin_ia32_psadbw512: + return EmitX86SAD(*this, Ops, 8); + case X86::BI__builtin_ia32_pmaxsb128: case X86::BI__builtin_ia32_pmaxsw128: case X86::BI__builtin_ia32_pmaxsd128: Index: test/CodeGen/avx2-builtins.c =================================================================== --- test/CodeGen/avx2-builtins.c +++ 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: test/CodeGen/avx512bw-builtins.c =================================================================== --- test/CodeGen/avx512bw-builtins.c +++ 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: test/CodeGen/sse2-builtins.c =================================================================== --- test/CodeGen/sse2-builtins.c +++ 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); }