diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2014-06-18 12:02:29 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2014-06-18 12:02:29 +0000 |
commit | 4ea1647e8be3312e38ffd6b9e9831a7a81332e66 (patch) | |
tree | 5dd2057fbfde9f9ebb1672e38bf891ec40fba6ce | |
parent | d82ed2e581b5979912ec96d2649f077c3b6d9401 (diff) | |
download | bcm5719-llvm-4ea1647e8be3312e38ffd6b9e9831a7a81332e66.tar.gz bcm5719-llvm-4ea1647e8be3312e38ffd6b9e9831a7a81332e66.zip |
[msan] Handle X86 *.psad.* and *.pmadd.* intrinsics.
llvm-svn: 211156
-rw-r--r-- | compiler-rt/lib/msan/tests/msan_test.cc | 25 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 55 | ||||
-rw-r--r-- | llvm/test/Instrumentation/MemorySanitizer/vector_arith.ll | 65 |
3 files changed, 145 insertions, 0 deletions
diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index f1fca19c9fd..438a74af50f 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -3526,11 +3526,13 @@ TEST(MemorySanitizer, UnalignedStore64_precise2) { } namespace { +typedef U1 V16x8 __attribute__((__vector_size__(16))); typedef U2 V8x16 __attribute__((__vector_size__(16))); typedef U4 V4x32 __attribute__((__vector_size__(16))); typedef U8 V2x64 __attribute__((__vector_size__(16))); typedef U4 V8x32 __attribute__((__vector_size__(32))); typedef U8 V4x64 __attribute__((__vector_size__(32))); +typedef U4 V2x32 __attribute__((__vector_size__(8))); typedef U2 V4x16 __attribute__((__vector_size__(8))); typedef U1 V8x8 __attribute__((__vector_size__(8))); @@ -3661,6 +3663,29 @@ TEST(VectorPackTest, mmx_packuswb) { EXPECT_EQ(c[7], U1_max); } +TEST(VectorSadTest, sse2_psad_bw) { + V16x8 a = {Poisoned<U1>(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + V16x8 b = {100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115}; + V2x64 c = _mm_sad_epu8(a, b); + + EXPECT_POISONED(c[0]); + EXPECT_NOT_POISONED(c[1]); + + EXPECT_EQ(800U, c[1]); +} + +TEST(VectorMaddTest, mmx_pmadd_wd) { + V4x16 a = {Poisoned<U2>(), 1, 2, 3}; + V4x16 b = {100, 101, 102, 103}; + V2x32 c = _mm_madd_pi16(a, b); + + EXPECT_POISONED(c[0]); + EXPECT_NOT_POISONED(c[1]); + + EXPECT_EQ((unsigned)(2 * 102 + 3 * 103), c[1]); +} + TEST(MemorySanitizerDr, StoreInDSOTest) { if (!__msan_has_dynamic_component()) return; char* s = new char[10]; diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index e71e540aa82..75c56c2d430 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2060,6 +2060,40 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { setOriginForNaryOp(I); } + // \brief Instrument sum-of-absolute-differencies intrinsic. + void handleVectorSadIntrinsic(IntrinsicInst &I) { + const unsigned SignificantBitsPerResultElement = 16; + bool isX86_MMX = I.getOperand(0)->getType()->isX86_MMXTy(); + Type *ResTy = isX86_MMX ? IntegerType::get(*MS.C, 64) : I.getType(); + unsigned ZeroBitsPerResultElement = + ResTy->getScalarSizeInBits() - SignificantBitsPerResultElement; + + IRBuilder<> IRB(&I); + Value *S = IRB.CreateOr(getShadow(&I, 0), getShadow(&I, 1)); + S = IRB.CreateBitCast(S, ResTy); + S = IRB.CreateSExt(IRB.CreateICmpNE(S, Constant::getNullValue(ResTy)), + ResTy); + S = IRB.CreateLShr(S, ZeroBitsPerResultElement); + S = IRB.CreateBitCast(S, getShadowTy(&I)); + setShadow(&I, S); + setOriginForNaryOp(I); + } + + // \brief Instrument multiply-add intrinsic. + void handleVectorPmaddIntrinsic(IntrinsicInst &I, + unsigned EltSizeInBits = 0) { + bool isX86_MMX = I.getOperand(0)->getType()->isX86_MMXTy(); + Type *ResTy = isX86_MMX ? getMMXVectorTy(EltSizeInBits * 2) : I.getType(); + IRBuilder<> IRB(&I); + Value *S = IRB.CreateOr(getShadow(&I, 0), getShadow(&I, 1)); + S = IRB.CreateBitCast(S, ResTy); + S = IRB.CreateSExt(IRB.CreateICmpNE(S, Constant::getNullValue(ResTy)), + ResTy); + S = IRB.CreateBitCast(S, getShadowTy(&I)); + setShadow(&I, S); + setOriginForNaryOp(I); + } + void visitIntrinsicInst(IntrinsicInst &I) { switch (I.getIntrinsicID()) { case llvm::Intrinsic::bswap: @@ -2196,6 +2230,27 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { handleVectorPackIntrinsic(I, 32); break; + case llvm::Intrinsic::x86_mmx_psad_bw: + case llvm::Intrinsic::x86_sse2_psad_bw: + case llvm::Intrinsic::x86_avx2_psad_bw: + handleVectorSadIntrinsic(I); + break; + + case llvm::Intrinsic::x86_sse2_pmadd_wd: + case llvm::Intrinsic::x86_avx2_pmadd_wd: + case llvm::Intrinsic::x86_ssse3_pmadd_ub_sw_128: + case llvm::Intrinsic::x86_avx2_pmadd_ub_sw: + handleVectorPmaddIntrinsic(I); + break; + + case llvm::Intrinsic::x86_ssse3_pmadd_ub_sw: + handleVectorPmaddIntrinsic(I, 8); + break; + + case llvm::Intrinsic::x86_mmx_pmadd_wd: + handleVectorPmaddIntrinsic(I, 16); + break; + default: if (!handleUnknownIntrinsic(I)) visitInstruction(I); diff --git a/llvm/test/Instrumentation/MemorySanitizer/vector_arith.ll b/llvm/test/Instrumentation/MemorySanitizer/vector_arith.ll new file mode 100644 index 00000000000..6541a1c3a39 --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/vector_arith.ll @@ -0,0 +1,65 @@ +; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16>, <8 x i16>) nounwind readnone +declare x86_mmx @llvm.x86.ssse3.pmadd.ub.sw(x86_mmx, x86_mmx) nounwind readnone +declare <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8>, <16 x i8>) nounwind readnone +declare x86_mmx @llvm.x86.mmx.psad.bw(x86_mmx, x86_mmx) nounwind readnone + +define <4 x i32> @Test_sse2_pmadd_wd(<8 x i16> %a, <8 x i16> %b) sanitize_memory { +entry: + %c = tail call <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16> %a, <8 x i16> %b) nounwind + ret <4 x i32> %c +} + +; CHECK-LABEL: @Test_sse2_pmadd_wd( +; CHECK: or <8 x i16> +; CHECK: bitcast <8 x i16> {{.*}} to <4 x i32> +; CHECK: icmp ne <4 x i32> {{.*}}, zeroinitializer +; CHECK: sext <4 x i1> {{.*}} to <4 x i32> +; CHECK: ret <4 x i32> + + +define x86_mmx @Test_ssse3_pmadd_ub_sw(x86_mmx %a, x86_mmx %b) sanitize_memory { +entry: + %c = tail call x86_mmx @llvm.x86.ssse3.pmadd.ub.sw(x86_mmx %a, x86_mmx %b) nounwind + ret x86_mmx %c +} + +; CHECK-LABEL: @Test_ssse3_pmadd_ub_sw( +; CHECK: or i64 +; CHECK: bitcast i64 {{.*}} to <4 x i16> +; CHECK: icmp ne <4 x i16> {{.*}}, zeroinitializer +; CHECK: sext <4 x i1> {{.*}} to <4 x i16> +; CHECK: bitcast <4 x i16> {{.*}} to i64 +; CHECK: ret x86_mmx + + +define <2 x i64> @Test_x86_sse2_psad_bw(<16 x i8> %a, <16 x i8> %b) sanitize_memory { + %c = tail call <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8> %a, <16 x i8> %b) + ret <2 x i64> %c +} + +; CHECK-LABEL: @Test_x86_sse2_psad_bw( +; CHECK: or <16 x i8> {{.*}}, {{.*}} +; CHECK: bitcast <16 x i8> {{.*}} to <2 x i64> +; CHECK: icmp ne <2 x i64> {{.*}}, zeroinitializer +; CHECK: sext <2 x i1> {{.*}} to <2 x i64> +; CHECK: lshr <2 x i64> {{.*}}, <i64 48, i64 48> +; CHECK: ret <2 x i64> + + +define x86_mmx @Test_x86_mmx_psad_bw(x86_mmx %a, x86_mmx %b) sanitize_memory { +entry: + %c = tail call x86_mmx @llvm.x86.mmx.psad.bw(x86_mmx %a, x86_mmx %b) nounwind + ret x86_mmx %c +} + +; CHECK-LABEL: @Test_x86_mmx_psad_bw( +; CHECK: or i64 +; CHECK: icmp ne i64 +; CHECK: sext i1 {{.*}} to i64 +; CHECK: lshr i64 {{.*}}, 48 +; CHECK: ret x86_mmx |