1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 19:42:54 +02:00

[msan] Handle vector compare x86 intrinsics.

This handles SSE and SSE2 cmp_* and comiXX_* intrinsics.

llvm-svn: 267966
This commit is contained in:
Evgeniy Stepanov 2016-04-29 01:19:52 +00:00
parent 4d9844ceb2
commit a73b38d454

View File

@ -2134,6 +2134,14 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
return CreateShadowCast(IRB, S2, T, /* Signed */ true);
}
// Given a vector, extract its first element, and return all
// zeroes if it is zero, and all ones otherwise.
Value *LowerElementShadowExtend(IRBuilder<> &IRB, Value *S, Type *T) {
Value *S1 = IRB.CreateExtractElement(S, (int)0);
Value *S2 = IRB.CreateICmpNE(S1, getCleanShadow(S1));
return CreateShadowCast(IRB, S2, T, /* Signed */ true);
}
Value *VariableShadowExtend(IRBuilder<> &IRB, Value *S) {
Type *T = S->getType();
assert(T->isVectorTy());
@ -2281,6 +2289,30 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
setOriginForNaryOp(I);
}
// \brief Instrument compare-packed intrinsic.
// Basically, an or followed by sext(icmp ne 0) to end up with all-zeros or
// all-ones shadow.
void handleVectorComparePackedIntrinsic(IntrinsicInst &I) {
IRBuilder<> IRB(&I);
Type *ResTy = getShadowTy(&I);
Value *S0 = IRB.CreateOr(getShadow(&I, 0), getShadow(&I, 1));
Value *S = IRB.CreateSExt(
IRB.CreateICmpNE(S0, Constant::getNullValue(ResTy)), ResTy);
setShadow(&I, S);
setOriginForNaryOp(I);
}
// \brief Instrument compare-scalar intrinsic.
// This handles both cmp* intrinsics which return the result in the first
// element of a vector, and comi* which return the result as i32.
void handleVectorCompareScalarIntrinsic(IntrinsicInst &I) {
IRBuilder<> IRB(&I);
Value *S0 = IRB.CreateOr(getShadow(&I, 0), getShadow(&I, 1));
Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&I));
setShadow(&I, S);
setOriginForNaryOp(I);
}
void visitIntrinsicInst(IntrinsicInst &I) {
switch (I.getIntrinsicID()) {
case llvm::Intrinsic::bswap:
@ -2424,6 +2456,43 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
handleVectorPmaddIntrinsic(I, 16);
break;
case llvm::Intrinsic::x86_sse_cmp_ss:
case llvm::Intrinsic::x86_sse2_cmp_sd:
case llvm::Intrinsic::x86_sse_comieq_ss:
case llvm::Intrinsic::x86_sse_comilt_ss:
case llvm::Intrinsic::x86_sse_comile_ss:
case llvm::Intrinsic::x86_sse_comigt_ss:
case llvm::Intrinsic::x86_sse_comige_ss:
case llvm::Intrinsic::x86_sse_comineq_ss:
case llvm::Intrinsic::x86_sse_ucomieq_ss:
case llvm::Intrinsic::x86_sse_ucomilt_ss:
case llvm::Intrinsic::x86_sse_ucomile_ss:
case llvm::Intrinsic::x86_sse_ucomigt_ss:
case llvm::Intrinsic::x86_sse_ucomige_ss:
case llvm::Intrinsic::x86_sse_ucomineq_ss:
case llvm::Intrinsic::x86_sse2_comieq_sd:
case llvm::Intrinsic::x86_sse2_comilt_sd:
case llvm::Intrinsic::x86_sse2_comile_sd:
case llvm::Intrinsic::x86_sse2_comigt_sd:
case llvm::Intrinsic::x86_sse2_comige_sd:
case llvm::Intrinsic::x86_sse2_comineq_sd:
case llvm::Intrinsic::x86_sse2_ucomieq_sd:
case llvm::Intrinsic::x86_sse2_ucomilt_sd:
case llvm::Intrinsic::x86_sse2_ucomile_sd:
case llvm::Intrinsic::x86_sse2_ucomigt_sd:
case llvm::Intrinsic::x86_sse2_ucomige_sd:
case llvm::Intrinsic::x86_sse2_ucomineq_sd:
handleVectorCompareScalarIntrinsic(I);
break;
case llvm::Intrinsic::x86_sse_cmp_ps:
case llvm::Intrinsic::x86_sse2_cmp_pd:
// FIXME: For x86_avx_cmp_pd_256 and x86_avx_cmp_ps_256 this function
// generates reasonably looking IR that fails in the backend with "Do not
// know how to split the result of this operator!".
handleVectorComparePackedIntrinsic(I);
break;
default:
if (!handleUnknownIntrinsic(I))
visitInstruction(I);