From edf5860e5108ebaa97a08173f24b10d6ac28948e Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Fri, 18 May 2018 20:19:53 +0000 Subject: [PATCH] [msan] Don't check divisor shadow in fdiv. Summary: Floating point division by zero or even undef does not have undefined behavior and may occur due to optimizations. Fixes https://bugs.llvm.org/show_bug.cgi?id=37523. Reviewers: kcc Subscribers: hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D47085 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332761 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/MemorySanitizer.cpp | 17 ++++++++++------- .../MemorySanitizer/msan_basic.ll | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index eb2af4f8311..5fbb6512fec 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -1841,7 +1841,7 @@ struct MemorySanitizerVisitor : public InstVisitor { void visitSub(BinaryOperator &I) { handleShadowOr(I); } void visitXor(BinaryOperator &I) { handleShadowOr(I); } - void handleDiv(Instruction &I) { + void handleIntegerDiv(Instruction &I) { IRBuilder<> IRB(&I); // Strict on the second argument. insertShadowCheck(I.getOperand(1), &I); @@ -1849,12 +1849,15 @@ struct MemorySanitizerVisitor : public InstVisitor { setOrigin(&I, getOrigin(&I, 0)); } - void visitUDiv(BinaryOperator &I) { handleDiv(I); } - void visitSDiv(BinaryOperator &I) { handleDiv(I); } - void visitFDiv(BinaryOperator &I) { handleDiv(I); } - void visitURem(BinaryOperator &I) { handleDiv(I); } - void visitSRem(BinaryOperator &I) { handleDiv(I); } - void visitFRem(BinaryOperator &I) { handleDiv(I); } + void visitUDiv(BinaryOperator &I) { handleIntegerDiv(I); } + void visitSDiv(BinaryOperator &I) { handleIntegerDiv(I); } + void visitURem(BinaryOperator &I) { handleIntegerDiv(I); } + void visitSRem(BinaryOperator &I) { handleIntegerDiv(I); } + + // Floating point division is side-effect free. We can not require that the + // divisor is fully initialized and must propagate shadow. See PR37523. + void visitFDiv(BinaryOperator &I) { handleShadowOr(I); } + void visitFRem(BinaryOperator &I) { handleShadowOr(I); } /// Instrument == and != comparisons. /// diff --git a/test/Instrumentation/MemorySanitizer/msan_basic.ll b/test/Instrumentation/MemorySanitizer/msan_basic.ll index 0c23edeb031..1f412ff498a 100644 --- a/test/Instrumentation/MemorySanitizer/msan_basic.ll +++ b/test/Instrumentation/MemorySanitizer/msan_basic.ll @@ -417,6 +417,21 @@ entry: ; CHECK-NOT: icmp ; CHECK: ret i32 +; Check that fdiv, unlike udiv, simply propagates shadow. + +define float @FDiv(float %a, float %b) nounwind uwtable readnone sanitize_memory { +entry: + %c = fdiv float %a, %b + ret float %c +} + +; CHECK-LABEL: @FDiv +; CHECK: %[[SA:.*]] = load i32,{{.*}}@__msan_param_tls +; CHECK: %[[SB:.*]] = load i32,{{.*}}@__msan_param_tls +; CHECK: %[[SC:.*]] = or i32 %[[SB]], %[[SA]] +; CHECK: = fdiv float +; CHECK: store i32 %[[SC]], i32* {{.*}}@__msan_retval_tls +; CHECK: ret float ; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests)