From: Evgeniy Stepanov Date: Thu, 29 Nov 2012 14:25:47 +0000 (+0000) Subject: [msan] Propagate shadow through (x<0) and (x>=0) comparisons. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=857d9d2a59cdbd9038b14a3d1a682a295cf57b6b;p=platform%2Fupstream%2Fllvm.git [msan] Propagate shadow through (x<0) and (x>=0) comparisons. This is a special case of signed relational comparison where result only depends on the sign of x. llvm-svn: 168881 --- diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 3065237..46d22aa 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -949,9 +949,39 @@ struct MemorySanitizerVisitor : public InstVisitor { setOriginForNaryOp(I); } + /// \brief Instrument signed relational comparisons. + /// + /// Handle (x<0) and (x>=0) comparisons (essentially, sign bit tests) by + /// propagating the highest bit of the shadow. Everything else is delegated + /// to handleShadowOr(). + void handleSignedRelationalComparison(ICmpInst &I) { + Constant *constOp0 = dyn_cast(I.getOperand(0)); + Constant *constOp1 = dyn_cast(I.getOperand(1)); + Value* op = NULL; + CmpInst::Predicate pre = I.getPredicate(); + if (constOp0 && constOp0->isNullValue() && + (pre == CmpInst::ICMP_SGT || pre == CmpInst::ICMP_SLE)) { + op = I.getOperand(1); + } else if (constOp1 && constOp1->isNullValue() && + (pre == CmpInst::ICMP_SLT || pre == CmpInst::ICMP_SGE)) { + op = I.getOperand(0); + } + if (op) { + IRBuilder<> IRB(&I); + Value* Shadow = + IRB.CreateICmpSLT(getShadow(op), getCleanShadow(op), "_msprop_icmpslt"); + setShadow(&I, Shadow); + setOrigin(&I, getOrigin(op)); + } else { + handleShadowOr(I); + } + } + void visitICmpInst(ICmpInst &I) { if (ClHandleICmp && I.isEquality()) handleEqualityComparison(I); + else if (ClHandleICmp && I.isSigned() && I.isRelational()) + handleSignedRelationalComparison(I); else handleShadowOr(I); } diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll b/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll index 2346d75..8d729d6 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll @@ -235,6 +235,53 @@ entry: ; CHECK: } +; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests) + +define zeroext i1 @ICmpSLT(i32 %x) nounwind uwtable readnone { + %1 = icmp slt i32 %x, 0 + ret i1 %1 +} + +; CHECK: define zeroext i1 @ICmpSLT +; CHECK: icmp slt +; CHECK: icmp slt +; CHECK-NOT: br +; CHECK: } + +define zeroext i1 @ICmpSGE(i32 %x) nounwind uwtable readnone { + %1 = icmp sge i32 %x, 0 + ret i1 %1 +} + +; CHECK: define zeroext i1 @ICmpSGE +; CHECK: icmp slt +; CHECK: icmp sge +; CHECK-NOT: br +; CHECK: } + +define zeroext i1 @ICmpSGT(i32 %x) nounwind uwtable readnone { + %1 = icmp sgt i32 0, %x + ret i1 %1 +} + +; CHECK: define zeroext i1 @ICmpSGT +; CHECK: icmp slt +; CHECK: icmp sgt +; CHECK-NOT: br +; CHECK: } + +define zeroext i1 @ICmpSLE(i32 %x) nounwind uwtable readnone { + %1 = icmp sle i32 0, %x + ret i1 %1 +} + +; CHECK: define zeroext i1 @ICmpSLE +; CHECK: icmp slt +; CHECK: icmp sle +; CHECK-NOT: br +; CHECK: } + + ; Check that loads from shadow have the same aligment as the original loads. define i32 @ShadowLoadAlignmentLarge() nounwind uwtable {