Skip to content

[msan] Reduces overhead of #113200, by 10% #113201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
64 changes: 24 additions & 40 deletions llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2694,40 +2694,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
setOriginForNaryOp(I);
}

/// Build the lowest possible value of V, taking into account V's
/// uninitialized bits.
Value *getLowestPossibleValue(IRBuilder<> &IRB, Value *A, Value *Sa,
bool isSigned) {
if (isSigned) {
// Split shadow into sign bit and other bits.
Value *SaOtherBits = IRB.CreateLShr(IRB.CreateShl(Sa, 1), 1);
Value *SaSignBit = IRB.CreateXor(Sa, SaOtherBits);
// Maximise the undefined shadow bit, minimize other undefined bits.
return IRB.CreateOr(IRB.CreateAnd(A, IRB.CreateNot(SaOtherBits)),
SaSignBit);
} else {
// Minimize undefined bits.
return IRB.CreateAnd(A, IRB.CreateNot(Sa));
}
}

/// Build the highest possible value of V, taking into account V's
/// uninitialized bits.
Value *getHighestPossibleValue(IRBuilder<> &IRB, Value *A, Value *Sa,
bool isSigned) {
if (isSigned) {
// Split shadow into sign bit and other bits.
Value *SaOtherBits = IRB.CreateLShr(IRB.CreateShl(Sa, 1), 1);
Value *SaSignBit = IRB.CreateXor(Sa, SaOtherBits);
// Minimise the undefined shadow bit, maximise other undefined bits.
return IRB.CreateOr(IRB.CreateAnd(A, IRB.CreateNot(SaSignBit)),
SaOtherBits);
} else {
// Maximize undefined bits.
return IRB.CreateOr(A, Sa);
}
}

/// Instrument relational comparisons.
///
/// This function does exact shadow propagation for all relational
Expand All @@ -2750,12 +2716,30 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// its undefined bits. Let [b0, b1] be the interval of possible values of B.
// Then (A cmp B) is defined iff (a0 cmp b1) == (a1 cmp b0).
bool IsSigned = I.isSigned();
Value *Amin = getLowestPossibleValue(IRB, A, Sa, IsSigned);
Value *Bmax = getHighestPossibleValue(IRB, B, Sb, IsSigned);
Value *S1 = IRB.CreateICmp(I.getPredicate(), Amin, Bmax);
Value *Amax = getHighestPossibleValue(IRB, A, Sa, IsSigned);
Value *Bmin = getLowestPossibleValue(IRB, B, Sb, IsSigned);
Value *S2 = IRB.CreateICmp(I.getPredicate(), Amax, Bmin);

auto GetMinMaxUnsigned = [&](Value *V, Value *S) {
if (IsSigned) {
// Sign-flip to map from signed range to unsigned range. Relation A vs B
// should be preserved, if checked with `getUnsignedPredicate()`.
// Relationship between Amin, Amax, Bmin, Bmax also will not be
// affected, as they are created by effectively adding/substructing from
// A (or B) a value, derived from shadow, with no overflow, either
// before or after sign flip.
APInt MinVal =
APInt::getSignedMinValue(V->getType()->getScalarSizeInBits());
V = IRB.CreateXor(V, ConstantInt::get(V->getType(), MinVal));
}
// Minimize undefined bits.
Value *Min = IRB.CreateAnd(V, IRB.CreateNot(S));
Value *Max = IRB.CreateOr(V, S);
return std::make_pair(Min, Max);
};

auto [Amin, Amax] = GetMinMaxUnsigned(A, Sa);
auto [Bmin, Bmax] = GetMinMaxUnsigned(B, Sb);
Value *S1 = IRB.CreateICmp(I.getUnsignedPredicate(), Amin, Bmax);
Value *S2 = IRB.CreateICmp(I.getUnsignedPredicate(), Amax, Bmin);

Value *Si = IRB.CreateXor(S1, S2);
setShadow(&I, Si);
setOriginForNaryOp(I);
Expand Down
Loading