From: Simon Pilgrim Date: Thu, 20 Dec 2018 11:53:45 +0000 (+0000) Subject: [X86][SSE] Auto upgrade PADDS/PSUBS intrinsics to SADD_SAT/SSUB_SAT generic intrinsic... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7853d35ba79f9226ef77d5ca81a5bca85551a7ac;p=clang [X86][SSE] Auto upgrade PADDS/PSUBS intrinsics to SADD_SAT/SSUB_SAT generic intrinsics (clang) This emits SADD_SAT/SSUB_SAT generic intrinsics for the SSE signed saturated math intrinsics. LLVM counterpart: https://reviews.llvm.org/D55894 Differential Revision: https://reviews.llvm.org/D55890 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@349743 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 486e7d8ec3..d38e6b0262 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9487,12 +9487,13 @@ static Value *EmitX86SExtMask(CodeGenFunction &CGF, Value *Op, return CGF.Builder.CreateSExt(Mask, DstTy, "vpmovm2"); } -// Emit addition or subtraction with unsigned saturation. -// TODO: Handle signed intrinsics. +// Emit addition or subtraction with signed/unsigned saturation. static Value *EmitX86AddSubSatExpr(CodeGenFunction &CGF, - SmallVectorImpl &Ops, + ArrayRef Ops, bool IsSigned, bool IsAddition) { - Intrinsic::ID IID = IsAddition ? Intrinsic::uadd_sat : Intrinsic::usub_sat; + Intrinsic::ID IID = + IsSigned ? (IsAddition ? Intrinsic::sadd_sat : Intrinsic::ssub_sat) + : (IsAddition ? Intrinsic::uadd_sat : Intrinsic::usub_sat); llvm::Function *F = CGF.CGM.getIntrinsic(IID, Ops[0]->getType()); return CGF.Builder.CreateCall(F, {Ops[0], Ops[1]}); } @@ -11359,20 +11360,34 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Load->setVolatile(true); return Load; } + case X86::BI__builtin_ia32_paddsb512: + case X86::BI__builtin_ia32_paddsw512: + case X86::BI__builtin_ia32_paddsb256: + case X86::BI__builtin_ia32_paddsw256: + case X86::BI__builtin_ia32_paddsb128: + case X86::BI__builtin_ia32_paddsw128: + return EmitX86AddSubSatExpr(*this, Ops, true, true); case X86::BI__builtin_ia32_paddusb512: case X86::BI__builtin_ia32_paddusw512: 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, Ops, true /* IsAddition */); + return EmitX86AddSubSatExpr(*this, Ops, false, true); + case X86::BI__builtin_ia32_psubsb512: + case X86::BI__builtin_ia32_psubsw512: + case X86::BI__builtin_ia32_psubsb256: + case X86::BI__builtin_ia32_psubsw256: + case X86::BI__builtin_ia32_psubsb128: + case X86::BI__builtin_ia32_psubsw128: + return EmitX86AddSubSatExpr(*this, Ops, true, false); case X86::BI__builtin_ia32_psubusb512: case X86::BI__builtin_ia32_psubusw512: 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, Ops, false /* IsAddition */); + return EmitX86AddSubSatExpr(*this, Ops, false, false); } } diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c index c943796c12..89225e69aa 100644 --- a/test/CodeGen/avx2-builtins.c +++ b/test/CodeGen/avx2-builtins.c @@ -56,13 +56,13 @@ __m256i test_mm256_add_epi64(__m256i a, __m256i b) { __m256i test_mm256_adds_epi8(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_adds_epi8 - // CHECK: call <32 x i8> @llvm.x86.avx2.padds.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) + // CHECK: call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) return _mm256_adds_epi8(a, b); } __m256i test_mm256_adds_epi16(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_adds_epi16 - // CHECK: call <16 x i16> @llvm.x86.avx2.padds.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) + // CHECK: call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) return _mm256_adds_epi16(a, b); } @@ -1171,13 +1171,13 @@ __m256i test_mm256_sub_epi64(__m256i a, __m256i b) { __m256i test_mm256_subs_epi8(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_subs_epi8 - // CHECK: call <32 x i8> @llvm.x86.avx2.psubs.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) + // CHECK: call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}}) return _mm256_subs_epi8(a, b); } __m256i test_mm256_subs_epi16(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_subs_epi16 - // CHECK: call <16 x i16> @llvm.x86.avx2.psubs.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) + // CHECK: call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}) return _mm256_subs_epi16(a, b); } diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c index 64204bf2e8..aa6b45325c 100644 --- a/test/CodeGen/avx512bw-builtins.c +++ b/test/CodeGen/avx512bw-builtins.c @@ -992,35 +992,35 @@ __m512i test_mm512_maskz_packus_epi16(__mmask64 __M, __m512i __A, __m512i __B) { } __m512i test_mm512_adds_epi8(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_adds_epi8 - // CHECK: @llvm.x86.avx512.padds.b.512 + // CHECK: @llvm.sadd.sat.v64i8 return _mm512_adds_epi8(__A,__B); } __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.padds.b.512 + // CHECK: @llvm.sadd.sat.v64i8 // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} 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 - // CHECK: @llvm.x86.avx512.padds.b.512 + // CHECK: @llvm.sadd.sat.v64i8 // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} return _mm512_maskz_adds_epi8(__U,__A,__B); } __m512i test_mm512_adds_epi16(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_adds_epi16 - // CHECK: @llvm.x86.avx512.padds.w.512 + // CHECK: @llvm.sadd.sat.v32i16 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 - // CHECK: @llvm.x86.avx512.padds.w.512 + // CHECK: @llvm.sadd.sat.v32i16 // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_mask_adds_epi16(__W,__U,__A,__B); } __m512i test_mm512_maskz_adds_epi16(__mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_adds_epi16 - // CHECK: @llvm.x86.avx512.padds.w.512 + // CHECK: @llvm.sadd.sat.v32i16 // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_adds_epi16(__U,__A,__B); } @@ -1315,35 +1315,35 @@ __m512i test_mm512_maskz_shuffle_epi8(__mmask64 __U, __m512i __A, __m512i __B) { } __m512i test_mm512_subs_epi8(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_subs_epi8 - // CHECK: @llvm.x86.avx512.psubs.b.512 + // CHECK: @llvm.ssub.sat.v64i8 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.psubs.b.512 + // CHECK: @llvm.ssub.sat.v64i8 // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} 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.psubs.b.512 + // CHECK: @llvm.ssub.sat.v64i8 // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} 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.psubs.w.512 + // CHECK: @llvm.ssub.sat.v32i16 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.psubs.w.512 + // CHECK: @llvm.ssub.sat.v32i16 // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} 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.psubs.w.512 + // CHECK: @llvm.ssub.sat.v32i16 // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_subs_epi16(__U,__A,__B); } diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c index fb42ffc392..1037617eab 100644 --- a/test/CodeGen/avx512vlbw-builtins.c +++ b/test/CodeGen/avx512vlbw-builtins.c @@ -1075,49 +1075,49 @@ __m256i test_mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __ __m128i test_mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_adds_epi8 - // CHECK: @llvm.x86.sse2.padds.b + // CHECK: @llvm.sadd.sat.v16i8 // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_mask_adds_epi8(__W,__U,__A,__B); } __m128i test_mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_adds_epi8 - // CHECK: @llvm.x86.sse2.padds.b + // CHECK: @llvm.sadd.sat.v16i8 // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_adds_epi8(__U,__A,__B); } __m256i test_mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_adds_epi8 - // CHECK: @llvm.x86.avx2.padds.b + // CHECK: @llvm.sadd.sat.v32i8 // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_mask_adds_epi8(__W,__U,__A,__B); } __m256i test_mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_adds_epi8 - // CHECK: @llvm.x86.avx2.padds.b + // CHECK: @llvm.sadd.sat.v32i8 // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_adds_epi8(__U,__A,__B); } __m128i test_mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_adds_epi16 - // CHECK: @llvm.x86.sse2.padds.w + // CHECK: @llvm.sadd.sat.v8i16 // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_adds_epi16(__W,__U,__A,__B); } __m128i test_mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_adds_epi16 - // CHECK: @llvm.x86.sse2.padds.w + // CHECK: @llvm.sadd.sat.v8i16 // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_adds_epi16(__U,__A,__B); } __m256i test_mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_adds_epi16 - // CHECK: @llvm.x86.avx2.padds.w + // CHECK: @llvm.sadd.sat.v16i16 // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_adds_epi16(__W,__U,__A,__B); } __m256i test_mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_adds_epi16 - // CHECK: @llvm.x86.avx2.padds.w + // CHECK: @llvm.sadd.sat.v16i16 // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_adds_epi16(__U,__A,__B); } @@ -1527,49 +1527,49 @@ __m256i test_mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B) { } __m128i test_mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_subs_epi8 - // CHECK: @llvm.x86.sse2.psubs.b + // CHECK: @llvm.ssub.sat.v16i8 // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_mask_subs_epi8(__W,__U,__A,__B); } __m128i test_mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_subs_epi8 - // CHECK: @llvm.x86.sse2.psubs.b + // CHECK: @llvm.ssub.sat.v16i8 // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_subs_epi8(__U,__A,__B); } __m256i test_mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_subs_epi8 - // CHECK: @llvm.x86.avx2.psubs.b + // CHECK: @llvm.ssub.sat.v32i8 // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_mask_subs_epi8(__W,__U,__A,__B); } __m256i test_mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_subs_epi8 - // CHECK: @llvm.x86.avx2.psubs.b + // CHECK: @llvm.ssub.sat.v32i8 // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_subs_epi8(__U,__A,__B); } __m128i test_mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_subs_epi16 - // CHECK: @llvm.x86.sse2.psubs.w + // CHECK: @llvm.ssub.sat.v8i16 // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_subs_epi16(__W,__U,__A,__B); } __m128i test_mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_subs_epi16 - // CHECK: @llvm.x86.sse2.psubs.w + // CHECK: @llvm.ssub.sat.v8i16 // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_subs_epi16(__U,__A,__B); } __m256i test_mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_subs_epi16 - // CHECK: @llvm.x86.avx2.psubs.w + // CHECK: @llvm.ssub.sat.v16i16 // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_subs_epi16(__W,__U,__A,__B); } __m256i test_mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_subs_epi16 - // CHECK: @llvm.x86.avx2.psubs.w + // CHECK: @llvm.ssub.sat.v16i16 // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_subs_epi16(__U,__A,__B); } diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c index 942e86b28f..029340abd9 100644 --- a/test/CodeGen/sse2-builtins.c +++ b/test/CodeGen/sse2-builtins.c @@ -47,13 +47,13 @@ __m128d test_mm_add_sd(__m128d A, __m128d B) { __m128i test_mm_adds_epi8(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_adds_epi8 - // CHECK: call <16 x i8> @llvm.x86.sse2.padds.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) + // CHECK: call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) return _mm_adds_epi8(A, B); } __m128i test_mm_adds_epi16(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_adds_epi16 - // CHECK: call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) + // CHECK: call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) return _mm_adds_epi16(A, B); } @@ -1460,13 +1460,13 @@ __m128d test_mm_sub_sd(__m128d A, __m128d B) { __m128i test_mm_subs_epi8(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_subs_epi8 - // CHECK: call <16 x i8> @llvm.x86.sse2.psubs.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) + // CHECK: call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}) return _mm_subs_epi8(A, B); } __m128i test_mm_subs_epi16(__m128i A, __m128i B) { // CHECK-LABEL: test_mm_subs_epi16 - // CHECK: call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) + // CHECK: call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}) return _mm_subs_epi16(A, B); }