Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -8907,6 +8907,39 @@ return CGF.Builder.CreateSExt(Mask, DstTy, "vpmovm2"); } +// Emit addition or subtraction with saturation. +// Handles both signed and unsigned intrinsics. +static Value *EmitX86AddSubSatExpr(CodeGenFunction &CGF, const CallExpr *E, + SmallVectorImpl &Ops, + bool IsAddition) { + + // Collect vector elements and type data. + llvm::Type *ResultType = CGF.ConvertType(E->getType()); + + Value *Res; + if (IsAddition) { + // ADDUS: a > (a+b) ? ~0 : (a+b) + // If Ops[0] > Add, overflow occured. + Value *Add = CGF.Builder.CreateAdd(Ops[0], Ops[1]); + Value *ICmp = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGT, Ops[0], Add); + Value *Max = llvm::Constant::getAllOnesValue(ResultType); + Res = CGF.Builder.CreateSelect(ICmp, Max, Add); + } else { + // SUBUS: max(a, b) - b + Value *ICmp = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGT, Ops[0], Ops[1]); + Value *Select = CGF.Builder.CreateSelect(ICmp, Ops[0], Ops[1]); + Res = CGF.Builder.CreateSub(Select, Ops[1]); + } + + if (E->getNumArgs() == 4) { // For masked intrinsics. + Value *VecSRC = Ops[2]; + Value *Mask = Ops[3]; + return EmitX86Select(CGF, Mask, Res, VecSRC); + } + + return Res; +} + Value *CodeGenFunction::EmitX86CpuIs(const CallExpr *E) { const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); StringRef CPUStr = cast(CPUExpr)->getString(); @@ -10530,10 +10563,23 @@ Load->setVolatile(true); return Load; } + case X86::BI__builtin_ia32_paddusb512_mask: + case X86::BI__builtin_ia32_paddusw512_mask: + case X86::BI__builtin_ia32_paddusb256: + case X86::BI__builtin_ia32_paddusw256: + case X86::BI__builtin_ia32_paddusb128: + case X86::BI__builtin_ia32_paddusw128: + return EmitX86AddSubSatExpr(*this, E, Ops, true /* IsAddition */); + case X86::BI__builtin_ia32_psubusb512_mask: + case X86::BI__builtin_ia32_psubusw512_mask: + case X86::BI__builtin_ia32_psubusb256: + case X86::BI__builtin_ia32_psubusw256: + case X86::BI__builtin_ia32_psubusb128: + case X86::BI__builtin_ia32_psubusw128: + return EmitX86AddSubSatExpr(*this, E, Ops, false /* IsAddition */); } } - Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { SmallVector Ops; Index: test/CodeGen/avx2-builtins.c =================================================================== --- test/CodeGen/avx2-builtins.c +++ test/CodeGen/avx2-builtins.c @@ -68,13 +68,19 @@ __m256i test_mm256_adds_epu8(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_adds_epu8 - // CHECK: call <32 x i8> @llvm.x86.avx2.paddus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) + // CHECK-NOT: call <32 x i8> @llvm.x86.avx2.paddus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) + // CHECK: add <32 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <32 x i8> %{{.*}}, %{{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i8> , <32 x i8> {{.*}} return _mm256_adds_epu8(a, b); } __m256i test_mm256_adds_epu16(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_adds_epu16 - // CHECK: call <16 x i16> @llvm.x86.avx2.paddus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) + // CHECK-NOT: call <16 x i16> @llvm.x86.avx2.paddus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) + // CHECK: add <16 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <16 x i16> %{{.*}}, %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> , <16 x i16> {{.*}} return _mm256_adds_epu16(a, b); } @@ -1181,13 +1187,19 @@ __m256i test_mm256_subs_epu8(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_subs_epu8 - // CHECK: call <32 x i8> @llvm.x86.avx2.psubus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) + // CHECK-NOT: call <32 x i8> @llvm.x86.avx2.psubus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) + // CHECK: icmp ugt <32 x i8> {{.*}}, {{.*}} + // CHECK: select <32 x i1> {{.*}}, <32 x i8> {{.*}}, <32 x i8> {{.*}} + // CHECK: sub <32 x i8> {{.*}}, {{.*}} return _mm256_subs_epu8(a, b); } __m256i test_mm256_subs_epu16(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_subs_epu16 - // CHECK: call <16 x i16> @llvm.x86.avx2.psubus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) + // CHECK-NOT: call <16 x i16> @llvm.x86.avx2.psubus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) + // CHECK: icmp ugt <16 x i16> {{.*}}, {{.*}} + // CHECK: select <16 x i1> {{.*}}, <16 x i16> {{.*}}, <16 x i16> {{.*}} + // CHECK: sub <16 x i16> {{.*}}, {{.*}} return _mm256_subs_epu16(a, b); } Index: test/CodeGen/avx512bw-builtins.c =================================================================== --- test/CodeGen/avx512bw-builtins.c +++ test/CodeGen/avx512bw-builtins.c @@ -600,7 +600,7 @@ __m512i test_mm512_mask_adds_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_adds_epi8 // CHECK: @llvm.x86.avx512.mask.padds.b.512 - return _mm512_mask_adds_epi8(__W,__U,__A,__B); + return _mm512_mask_adds_epi8(__W,__U,__A,__B); } __m512i test_mm512_maskz_adds_epi8(__mmask64 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_adds_epi8 @@ -610,7 +610,7 @@ __m512i test_mm512_adds_epi16(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_adds_epi16 // CHECK: @llvm.x86.avx512.mask.padds.w.512 - return _mm512_adds_epi16(__A,__B); + return _mm512_adds_epi16(__A,__B); } __m512i test_mm512_mask_adds_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_adds_epi16 @@ -620,36 +620,58 @@ __m512i test_mm512_maskz_adds_epi16(__mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_adds_epi16 // CHECK: @llvm.x86.avx512.mask.padds.w.512 - return _mm512_maskz_adds_epi16(__U,__A,__B); +return _mm512_maskz_adds_epi16(__U,__A,__B); } __m512i test_mm512_adds_epu8(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_adds_epu8 - // CHECK: @llvm.x86.avx512.mask.paddus.b.512 + // CHECK-NOT: @llvm.x86.avx512.mask.paddus.b.512 + // CHECK: add <64 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <64 x i8> %{{.*}}, %{{.*}} + // CHECK: select <64 x i1> %{{.*}}, <64 x i8> , <64 x i8> {{.*}} return _mm512_adds_epu8(__A,__B); } __m512i test_mm512_mask_adds_epu8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_adds_epu8 - // CHECK: @llvm.x86.avx512.mask.paddus.b.512 + // CHECK-NOT: @llvm.x86.avx512.mask.paddus.b.512 + // CHECK: add <64 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <64 x i8> %{{.*}}, %{{.*}} + // CHECK: select <64 x i1> %{{.*}}, <64 x i8> , <64 x i8> {{.*}} + // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} return _mm512_mask_adds_epu8(__W,__U,__A,__B); } __m512i test_mm512_maskz_adds_epu8(__mmask64 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_adds_epu8 - // CHECK: @llvm.x86.avx512.mask.paddus.b.512 + // CHECK-NOT: @llvm.x86.avx512.mask.paddus.b.512 + // CHECK: add <64 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <64 x i8> %{{.*}}, %{{.*}} + // CHECK: select <64 x i1> %{{.*}}, <64 x i8> , <64 x i8> {{.*}} + // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} return _mm512_maskz_adds_epu8(__U,__A,__B); } __m512i test_mm512_adds_epu16(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_adds_epu16 - // CHECK: @llvm.x86.avx512.mask.paddus.w.512 + // CHECK-NOT: @llvm.x86.avx512.mask.paddus.w.512 + // CHECK: add <32 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <32 x i16> %{{.*}}, %{{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> , <32 x i16> {{.*}} return _mm512_adds_epu16(__A,__B); } __m512i test_mm512_mask_adds_epu16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_adds_epu16 - // CHECK: @llvm.x86.avx512.mask.paddus.w.512 + // CHECK-NOT: @llvm.x86.avx512.mask.paddus.w.512 + // CHECK: add <32 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <32 x i16> %{{.*}}, %{{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> , <32 x i16> {{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_mask_adds_epu16(__W,__U,__A,__B); } __m512i test_mm512_maskz_adds_epu16(__mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_adds_epu16 - // CHECK: @llvm.x86.avx512.mask.paddus.w.512 + // CHECK-NOT: @llvm.x86.avx512.mask.paddus.w.512 + // CHECK: add <32 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <32 x i16> %{{.*}}, %{{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> , <32 x i16> {{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_adds_epu16(__U,__A,__B); } __m512i test_mm512_avg_epu8(__m512i __A, __m512i __B) { @@ -904,62 +926,84 @@ __m512i test_mm512_subs_epi8(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_subs_epi8 // CHECK: @llvm.x86.avx512.mask.psubs.b.512 - return _mm512_subs_epi8(__A,__B); +return _mm512_subs_epi8(__A,__B); } __m512i test_mm512_mask_subs_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_subs_epi8 // CHECK: @llvm.x86.avx512.mask.psubs.b.512 - return _mm512_mask_subs_epi8(__W,__U,__A,__B); +return _mm512_mask_subs_epi8(__W,__U,__A,__B); } __m512i test_mm512_maskz_subs_epi8(__mmask64 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_subs_epi8 // CHECK: @llvm.x86.avx512.mask.psubs.b.512 - return _mm512_maskz_subs_epi8(__U,__A,__B); +return _mm512_maskz_subs_epi8(__U,__A,__B); } __m512i test_mm512_subs_epi16(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_subs_epi16 // CHECK: @llvm.x86.avx512.mask.psubs.w.512 - return _mm512_subs_epi16(__A,__B); +return _mm512_subs_epi16(__A,__B); } __m512i test_mm512_mask_subs_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_subs_epi16 // CHECK: @llvm.x86.avx512.mask.psubs.w.512 - return _mm512_mask_subs_epi16(__W,__U,__A,__B); +return _mm512_mask_subs_epi16(__W,__U,__A,__B); } __m512i test_mm512_maskz_subs_epi16(__mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_subs_epi16 // CHECK: @llvm.x86.avx512.mask.psubs.w.512 - return _mm512_maskz_subs_epi16(__U,__A,__B); +return _mm512_maskz_subs_epi16(__U,__A,__B); } __m512i test_mm512_subs_epu8(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_subs_epu8 - // CHECK: @llvm.x86.avx512.mask.psubus.b.512 - return _mm512_subs_epu8(__A,__B); + // CHECK-NOT: @llvm.x86.avx512.mask.psubus.b.512 + // CHECK: icmp ugt <64 x i8> {{.*}}, {{.*}} + // CHECK: select <64 x i1> {{.*}}, <64 x i8> {{.*}}, <64 x i8> {{.*}} + // CHECK: sub <64 x i8> {{.*}}, {{.*}} +return _mm512_subs_epu8(__A,__B); } __m512i test_mm512_mask_subs_epu8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_subs_epu8 - // CHECK: @llvm.x86.avx512.mask.psubus.b.512 - return _mm512_mask_subs_epu8(__W,__U,__A,__B); + // CHECK-NOT: @llvm.x86.avx512.mask.psubus.b.512 + // CHECK: icmp ugt <64 x i8> {{.*}}, {{.*}} + // CHECK: select <64 x i1> {{.*}}, <64 x i8> {{.*}}, <64 x i8> {{.*}} + // CHECK: sub <64 x i8> {{.*}}, {{.*}} + // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} +return _mm512_mask_subs_epu8(__W,__U,__A,__B); } __m512i test_mm512_maskz_subs_epu8(__mmask64 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_subs_epu8 - // CHECK: @llvm.x86.avx512.mask.psubus.b.512 - return _mm512_maskz_subs_epu8(__U,__A,__B); + // CHECK-NOT: @llvm.x86.avx512.mask.psubus.b.512 + // CHECK: icmp ugt <64 x i8> {{.*}}, {{.*}} + // CHECK: select <64 x i1> {{.*}}, <64 x i8> {{.*}}, <64 x i8> {{.*}} + // CHECK: sub <64 x i8> {{.*}}, {{.*}} + // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} +return _mm512_maskz_subs_epu8(__U,__A,__B); } __m512i test_mm512_subs_epu16(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_subs_epu16 - // CHECK: @llvm.x86.avx512.mask.psubus.w.512 - return _mm512_subs_epu16(__A,__B); + // CHECK-NOT: @llvm.x86.avx512.mask.psubus.w.512 + // CHECK: icmp ugt <32 x i16> {{.*}}, {{.*}} + // CHECK: select <32 x i1> {{.*}}, <32 x i16> {{.*}}, <32 x i16> {{.*}} + // CHECK: sub <32 x i16> {{.*}}, {{.*}} +return _mm512_subs_epu16(__A,__B); } __m512i test_mm512_mask_subs_epu16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_subs_epu16 - // CHECK: @llvm.x86.avx512.mask.psubus.w.512 - return _mm512_mask_subs_epu16(__W,__U,__A,__B); + // CHECK-NOT: @llvm.x86.avx512.mask.psubus.w.512 + // CHECK: icmp ugt <32 x i16> {{.*}}, {{.*}} + // CHECK: select <32 x i1> {{.*}}, <32 x i16> {{.*}}, <32 x i16> {{.*}} + // CHECK: sub <32 x i16> {{.*}}, {{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} +return _mm512_mask_subs_epu16(__W,__U,__A,__B); } __m512i test_mm512_maskz_subs_epu16(__mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_subs_epu16 - // CHECK: @llvm.x86.avx512.mask.psubus.w.512 - return _mm512_maskz_subs_epu16(__U,__A,__B); + // CHECK-NOT: @llvm.x86.avx512.mask.psubus.w.512 + // CHECK: icmp ugt <32 x i16> {{.*}}, {{.*}} + // CHECK: select <32 x i1> {{.*}}, <32 x i16> {{.*}}, <32 x i16> {{.*}} + // CHECK: sub <32 x i16> {{.*}}, {{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} +return _mm512_maskz_subs_epu16(__U,__A,__B); } __m512i test_mm512_mask2_permutex2var_epi16(__m512i __A, __m512i __I, __mmask32 __U, __m512i __B) { // CHECK-LABEL: @test_mm512_mask2_permutex2var_epi16 Index: test/CodeGen/avx512vlbw-builtins.c =================================================================== --- test/CodeGen/avx512vlbw-builtins.c +++ test/CodeGen/avx512vlbw-builtins.c @@ -1123,49 +1123,73 @@ } __m128i test_mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_adds_epu8 - // CHECK: @llvm.x86.sse2.paddus.b + // CHECK-NOT: @llvm.x86.sse2.paddus.b + // CHECK: add <16 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <16 x i8> %{{.*}}, %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x i8> , <16 x i8> {{.*}} // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_mask_adds_epu8(__W,__U,__A,__B); } __m128i test_mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_adds_epu8 - // CHECK: @llvm.x86.sse2.paddus.b + // CHECK-NOT: @llvm.x86.sse2.paddus.b + // CHECK: add <16 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <16 x i8> %{{.*}}, %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x i8> , <16 x i8> {{.*}} // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_adds_epu8(__U,__A,__B); } __m256i test_mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_adds_epu8 - // CHECK: @llvm.x86.avx2.paddus.b + // CHECK-NOT: @llvm.x86.avx2.paddus.b + // CHECK: add <32 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <32 x i8> %{{.*}}, %{{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i8> , <32 x i8> {{.*}} // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_mask_adds_epu8(__W,__U,__A,__B); } __m256i test_mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_adds_epu8 - // CHECK: @llvm.x86.avx2.paddus.b + // CHECK-NOT: @llvm.x86.avx2.paddus.b + // CHECK: add <32 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <32 x i8> %{{.*}}, %{{.*}} + // CHECK: select <32 x i1> %{{.*}}, <32 x i8> , <32 x i8> {{.*}} // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_adds_epu8(__U,__A,__B); } __m128i test_mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_adds_epu16 - // CHECK: @llvm.x86.sse2.paddus.w + // CHECK-NOT: @llvm.x86.sse2.paddus.w + // CHECK: add <8 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <8 x i16> %{{.*}}, %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> , <8 x i16> {{.*}} // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_adds_epu16(__W,__U,__A,__B); } __m128i test_mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_adds_epu16 - // CHECK: @llvm.x86.sse2.paddus.w + // CHECK-NOT: @llvm.x86.sse2.paddus.w + // CHECK: add <8 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <8 x i16> %{{.*}}, %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> , <8 x i16> {{.*}} // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_adds_epu16(__U,__A,__B); } __m256i test_mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_adds_epu16 - // CHECK: @llvm.x86.avx2.paddus.w + // CHECK-NOT: @llvm.x86.avx2.paddus.w + // CHECK: add <16 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <16 x i16> %{{.*}}, %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> , <16 x i16> {{.*}} // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_adds_epu16(__W,__U,__A,__B); } __m256i test_mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_adds_epu16 - // CHECK: @llvm.x86.avx2.paddus.w + // CHECK-NOT: @llvm.x86.avx2.paddus.w + // CHECK: add <16 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <16 x i16> %{{.*}}, %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> , <16 x i16> {{.*}} // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_adds_epu16(__U,__A,__B); } @@ -1567,49 +1591,73 @@ } __m128i test_mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_subs_epu8 - // CHECK: @llvm.x86.sse2.psubus.b + // CHECK-NOT: @llvm.x86.sse2.psubus.b + // CHECK: icmp ugt <16 x i8> {{.*}}, {{.*}} + // CHECK: select <16 x i1> {{.*}}, <16 x i8> {{.*}}, <16 x i8> {{.*}} + // CHECK: sub <16 x i8> {{.*}}, {{.*}} // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_mask_subs_epu8(__W,__U,__A,__B); } __m128i test_mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_subs_epu8 - // CHECK: @llvm.x86.sse2.psubus.b + // CHECK-NOT: @llvm.x86.sse2.psubus.b + // CHECK: icmp ugt <16 x i8> {{.*}}, {{.*}} + // CHECK: select <16 x i1> {{.*}}, <16 x i8> {{.*}}, <16 x i8> {{.*}} + // CHECK: sub <16 x i8> {{.*}}, {{.*}} // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_subs_epu8(__U,__A,__B); } __m256i test_mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_subs_epu8 - // CHECK: @llvm.x86.avx2.psubus.b + // CHECK-NOT: @llvm.x86.avx2.psubus.b + // CHECK: icmp ugt <32 x i8> {{.*}}, {{.*}} + // CHECK: select <32 x i1> {{.*}}, <32 x i8> {{.*}}, <32 x i8> {{.*}} + // CHECK: sub <32 x i8> {{.*}}, {{.*}} // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_mask_subs_epu8(__W,__U,__A,__B); } __m256i test_mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_subs_epu8 - // CHECK: @llvm.x86.avx2.psubus.b + // CHECK-NOT: @llvm.x86.avx2.psubus.b + // CHECK: icmp ugt <32 x i8> {{.*}}, {{.*}} + // CHECK: select <32 x i1> {{.*}}, <32 x i8> {{.*}}, <32 x i8> {{.*}} + // CHECK: sub <32 x i8> {{.*}}, {{.*}} // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_subs_epu8(__U,__A,__B); } __m128i test_mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_subs_epu16 - // CHECK: @llvm.x86.sse2.psubus.w + // CHECK-NOT: @llvm.x86.sse2.psubus.w + // CHECK: icmp ugt <8 x i16> {{.*}}, {{.*}} + // CHECK: select <8 x i1> {{.*}}, <8 x i16> {{.*}}, <8 x i16> {{.*}} + // CHECK: sub <8 x i16> {{.*}}, {{.*}} // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_subs_epu16(__W,__U,__A,__B); } __m128i test_mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_subs_epu16 - // CHECK: @llvm.x86.sse2.psubus.w + // CHECK-NOT: @llvm.x86.sse2.psubus.w + // CHECK: icmp ugt <8 x i16> {{.*}}, {{.*}} + // CHECK: select <8 x i1> {{.*}}, <8 x i16> {{.*}}, <8 x i16> {{.*}} + // CHECK: sub <8 x i16> {{.*}}, {{.*}} // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_subs_epu16(__U,__A,__B); } __m256i test_mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_subs_epu16 - // CHECK: @llvm.x86.avx2.psubus.w + // CHECK-NOT: @llvm.x86.avx2.psubus.w + // CHECK: icmp ugt <16 x i16> {{.*}}, {{.*}} + // CHECK: select <16 x i1> {{.*}}, <16 x i16> {{.*}}, <16 x i16> {{.*}} + // CHECK: sub <16 x i16> {{.*}}, {{.*}} // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_subs_epu16(__W,__U,__A,__B); } __m256i test_mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_subs_epu16 - // CHECK: @llvm.x86.avx2.psubus.w + // CHECK-NOT: @llvm.x86.avx2.psubus.w + // CHECK: icmp ugt <16 x i16> {{.*}}, {{.*}} + // CHECK: select <16 x i1> {{.*}}, <16 x i16> {{.*}}, <16 x i16> {{.*}} + // CHECK: sub <16 x i16> {{.*}}, {{.*}} // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_subs_epu16(__U,__A,__B); } Index: test/CodeGen/sse2-builtins.c =================================================================== --- test/CodeGen/sse2-builtins.c +++ test/CodeGen/sse2-builtins.c @@ -59,13 +59,19 @@ __m128i test_mm_adds_epu8(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_adds_epu8 - // CHECK: call <16 x i8> @llvm.x86.sse2.paddus.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) + // CHECK-NOT: call <16 x i8> @llvm.x86.sse2.paddus.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) + // CHECK: add <16 x i8> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <16 x i8> %{{.*}}, %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x i8> , <16 x i8> {{.*}} return _mm_adds_epu8(A, B); } __m128i test_mm_adds_epu16(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_adds_epu16 - // CHECK: call <8 x i16> @llvm.x86.sse2.paddus.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) + // CHECK-NOT: call <8 x i16> @llvm.x86.sse2.paddus.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) + // CHECK: add <8 x i16> %{{.*}}, %{{.*}} + // CHECK: icmp ugt <8 x i16> %{{.*}}, %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> , <8 x i16> {{.*}} return _mm_adds_epu16(A, B); } @@ -1422,13 +1428,19 @@ __m128i test_mm_subs_epu8(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_subs_epu8 - // CHECK: call <16 x i8> @llvm.x86.sse2.psubus.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) + // CHECK-NOT: call <16 x i8> @llvm.x86.sse2.psubus.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) + // CHECK: icmp ugt <16 x i8> {{.*}}, {{.*}} + // CHECK: select <16 x i1> {{.*}}, <16 x i8> {{.*}}, <16 x i8> {{.*}} + // CHECK: sub <16 x i8> {{.*}}, {{.*}} return _mm_subs_epu8(A, B); } __m128i test_mm_subs_epu16(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_subs_epu16 - // CHECK: call <8 x i16> @llvm.x86.sse2.psubus.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) + // CHECK-NOT: call <8 x i16> @llvm.x86.sse2.psubus.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) + // CHECK: icmp ugt <8 x i16> {{.*}}, {{.*}} + // CHECK: select <8 x i1> {{.*}}, <8 x i16> {{.*}}, <8 x i16> {{.*}} + // CHECK: sub <8 x i16> {{.*}}, {{.*}} return _mm_subs_epu16(A, B); }