[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
This commit is contained in:
Evgeniy Stepanov 2012-11-29 14:25:47 +00:00
parent fc6164c985
commit fafa2ae4b6
2 changed files with 77 additions and 0 deletions
lib/Transforms/Instrumentation
test/Instrumentation/MemorySanitizer

@ -949,9 +949,39 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
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<Constant>(I.getOperand(0));
Constant *constOp1 = dyn_cast<Constant>(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);
}

@ -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 {