Skip to content

Commit

Permalink
[msan] Reduces overhead of llvm#113200, by 10% (llvm#113201)
Browse files Browse the repository at this point in the history
CTMark llvm#113200 size overhead was 5.3%, now it's 4.7%.

The patch affects only signed integers.

https://alive2.llvm.org/ce/z/Lv5hyi

* The patch replaces code which extracted sign bit,
maximized/minimized it, then packed it back, with
simple sign bit flip. The another way to think about
transformation is as a subtraction of MIN_SINT from
A/B. Then we map MIN_SINT to 0, 0 to -MIN_SINT, and
MAX_SINT to MAX_UINT.

* Then to maximize/minimize A/B we don't need
to extract sign bit, we can apply shadow the
same way as to other bits.

* After sign bit flip, we had to switch to unsigned
version of the predicates.

* After change above  getHighestPossibleValue/getLowestPossibleValue
became very similar, so we can combine into a single function.

* Because the function does sign bit flip and
requires unsigned predicates used for returned values,
there is no point in keeping it as a member of class,
to hide, we switch to function local lambda.
  • Loading branch information
vitalybuka authored Oct 25, 2024
1 parent b852fb1 commit cf8d245
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 489 deletions.
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

0 comments on commit cf8d245

Please sign in to comment.