summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2017-05-11 11:07:48 +0000
committerAlexander Potapenko <glider@google.com>2017-05-11 11:07:48 +0000
commita658ae8fe249aaf7dfe3109722b33da8b33b1346 (patch)
treee0ce79d10bcd97b4a14b5e917164701eec6232de
parent29006dc724d2eb5d003cb7c89e2d32d5b4c7ea2a (diff)
downloadbcm5719-llvm-a658ae8fe249aaf7dfe3109722b33da8b33b1346.tar.gz
bcm5719-llvm-a658ae8fe249aaf7dfe3109722b33da8b33b1346.zip
[msan] Fix PR32842
It turned out that MSan was incorrectly calculating the shadow for int comparisons: it was done by truncating the result of (Shadow1 OR Shadow2) to i1, effectively rendering all bits except LSB useless. This approach doesn't work e.g. in the case where the values being compared are even (i.e. have the LSB of the shadow equal to zero). Instead, if CreateShadowCast() has to cast a bigger int to i1, we replace the truncation with an ICMP to 0. This patch doesn't affect the code generated for SPEC 2006 binaries, i.e. there's no performance impact. For the test case reported in PR32842 MSan with the patch generates a slightly more efficient code: orq %rcx, %rax jne .LBB0_6 , instead of: orl %ecx, %eax testb $1, %al jne .LBB0_6 llvm-svn: 302787
-rw-r--r--llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp7
-rw-r--r--llvm/test/Instrumentation/MemorySanitizer/pr32842.ll20
2 files changed, 25 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 15333a5317d..ff753c20a94 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -1576,13 +1576,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
Value *CreateShadowCast(IRBuilder<> &IRB, Value *V, Type *dstTy,
bool Signed = false) {
Type *srcTy = V->getType();
+ size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
+ size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
+ if (srcSizeInBits > 1 && dstSizeInBits == 1)
+ return IRB.CreateICmpNE(V, getCleanShadow(V));
+
if (dstTy->isIntegerTy() && srcTy->isIntegerTy())
return IRB.CreateIntCast(V, dstTy, Signed);
if (dstTy->isVectorTy() && srcTy->isVectorTy() &&
dstTy->getVectorNumElements() == srcTy->getVectorNumElements())
return IRB.CreateIntCast(V, dstTy, Signed);
- size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
- size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
Value *V1 = IRB.CreateBitCast(V, Type::getIntNTy(*MS.C, srcSizeInBits));
Value *V2 =
IRB.CreateIntCast(V1, Type::getIntNTy(*MS.C, dstSizeInBits), Signed);
diff --git a/llvm/test/Instrumentation/MemorySanitizer/pr32842.ll b/llvm/test/Instrumentation/MemorySanitizer/pr32842.ll
new file mode 100644
index 00000000000..5d74c9a193b
--- /dev/null
+++ b/llvm/test/Instrumentation/MemorySanitizer/pr32842.ll
@@ -0,0 +1,20 @@
+; Regression test for https://bugs.llvm.org/show_bug.cgi?id=32842
+;
+; RUN: opt < %s -msan -S | FileCheck %s
+;target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define zeroext i1 @_Z1fii(i32 %x, i32 %y) sanitize_memory {
+entry:
+ %cmp = icmp slt i32 %x, %y
+ ret i1 %cmp
+}
+
+; CHECK: [[X:[^ ]+]] = load{{.*}}__msan_param_tls{{.*}}
+; CHECK: [[Y:[^ ]+]] = load{{.*}}__msan_param_tls{{.*}}
+; CHECK: [[OR:[^ ]+]] = or i32 [[Y]], [[X]]
+
+; Make sure the shadow of the (x < y) comparison isn't truncated to i1.
+; CHECK-NOT: trunc i32 [[OR]] to i1
+; CHECK: [[CMP:[^ ]+]] = icmp ne i32 [[OR]], 0
+; CHECK: store i1 [[CMP]],{{.*}}__msan_retval_tls
OpenPOWER on IntegriCloud