Skip to content

Commit cf8d245

Browse files
authored
[msan] Reduces overhead of #113200, by 10% (#113201)
CTMark #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.
1 parent b852fb1 commit cf8d245

File tree

3 files changed

+217
-489
lines changed

3 files changed

+217
-489
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,40 +2694,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
26942694
setOriginForNaryOp(I);
26952695
}
26962696

2697-
/// Build the lowest possible value of V, taking into account V's
2698-
/// uninitialized bits.
2699-
Value *getLowestPossibleValue(IRBuilder<> &IRB, Value *A, Value *Sa,
2700-
bool isSigned) {
2701-
if (isSigned) {
2702-
// Split shadow into sign bit and other bits.
2703-
Value *SaOtherBits = IRB.CreateLShr(IRB.CreateShl(Sa, 1), 1);
2704-
Value *SaSignBit = IRB.CreateXor(Sa, SaOtherBits);
2705-
// Maximise the undefined shadow bit, minimize other undefined bits.
2706-
return IRB.CreateOr(IRB.CreateAnd(A, IRB.CreateNot(SaOtherBits)),
2707-
SaSignBit);
2708-
} else {
2709-
// Minimize undefined bits.
2710-
return IRB.CreateAnd(A, IRB.CreateNot(Sa));
2711-
}
2712-
}
2713-
2714-
/// Build the highest possible value of V, taking into account V's
2715-
/// uninitialized bits.
2716-
Value *getHighestPossibleValue(IRBuilder<> &IRB, Value *A, Value *Sa,
2717-
bool isSigned) {
2718-
if (isSigned) {
2719-
// Split shadow into sign bit and other bits.
2720-
Value *SaOtherBits = IRB.CreateLShr(IRB.CreateShl(Sa, 1), 1);
2721-
Value *SaSignBit = IRB.CreateXor(Sa, SaOtherBits);
2722-
// Minimise the undefined shadow bit, maximise other undefined bits.
2723-
return IRB.CreateOr(IRB.CreateAnd(A, IRB.CreateNot(SaSignBit)),
2724-
SaOtherBits);
2725-
} else {
2726-
// Maximize undefined bits.
2727-
return IRB.CreateOr(A, Sa);
2728-
}
2729-
}
2730-
27312697
/// Instrument relational comparisons.
27322698
///
27332699
/// This function does exact shadow propagation for all relational
@@ -2750,12 +2716,30 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
27502716
// its undefined bits. Let [b0, b1] be the interval of possible values of B.
27512717
// Then (A cmp B) is defined iff (a0 cmp b1) == (a1 cmp b0).
27522718
bool IsSigned = I.isSigned();
2753-
Value *Amin = getLowestPossibleValue(IRB, A, Sa, IsSigned);
2754-
Value *Bmax = getHighestPossibleValue(IRB, B, Sb, IsSigned);
2755-
Value *S1 = IRB.CreateICmp(I.getPredicate(), Amin, Bmax);
2756-
Value *Amax = getHighestPossibleValue(IRB, A, Sa, IsSigned);
2757-
Value *Bmin = getLowestPossibleValue(IRB, B, Sb, IsSigned);
2758-
Value *S2 = IRB.CreateICmp(I.getPredicate(), Amax, Bmin);
2719+
2720+
auto GetMinMaxUnsigned = [&](Value *V, Value *S) {
2721+
if (IsSigned) {
2722+
// Sign-flip to map from signed range to unsigned range. Relation A vs B
2723+
// should be preserved, if checked with `getUnsignedPredicate()`.
2724+
// Relationship between Amin, Amax, Bmin, Bmax also will not be
2725+
// affected, as they are created by effectively adding/substructing from
2726+
// A (or B) a value, derived from shadow, with no overflow, either
2727+
// before or after sign flip.
2728+
APInt MinVal =
2729+
APInt::getSignedMinValue(V->getType()->getScalarSizeInBits());
2730+
V = IRB.CreateXor(V, ConstantInt::get(V->getType(), MinVal));
2731+
}
2732+
// Minimize undefined bits.
2733+
Value *Min = IRB.CreateAnd(V, IRB.CreateNot(S));
2734+
Value *Max = IRB.CreateOr(V, S);
2735+
return std::make_pair(Min, Max);
2736+
};
2737+
2738+
auto [Amin, Amax] = GetMinMaxUnsigned(A, Sa);
2739+
auto [Bmin, Bmax] = GetMinMaxUnsigned(B, Sb);
2740+
Value *S1 = IRB.CreateICmp(I.getUnsignedPredicate(), Amin, Bmax);
2741+
Value *S2 = IRB.CreateICmp(I.getUnsignedPredicate(), Amax, Bmin);
2742+
27592743
Value *Si = IRB.CreateXor(S1, S2);
27602744
setShadow(&I, Si);
27612745
setOriginForNaryOp(I);

0 commit comments

Comments
 (0)