From 09542052351380a455bb23a28df86b80db461eb2 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 26 Jul 2024 11:54:09 -0700 Subject: [PATCH] [ubsan][hwasan] Let mixing filters (#100680) Now the check will be enabled only if each filter is satisfied. --- .../Instrumentation/HWAddressSanitizer.cpp | 17 +++++++---- .../Instrumentation/LowerAllowCheckPass.cpp | 30 +++++++++++-------- .../HWAddressSanitizer/pgo-opt-out.ll | 2 ++ .../Transforms/lower-builtin-allow-check.ll | 2 +- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index a0e63bf12400e3..812874ff3c1739 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -1528,11 +1528,7 @@ static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool HWAddressSanitizer::selectiveInstrumentationShouldSkip( Function &F, FunctionAnalysisManager &FAM) const { - bool Skip = [&]() { - if (ClRandomSkipRate.getNumOccurrences()) { - std::bernoulli_distribution D(ClRandomSkipRate); - return !D(*Rng); - } + auto SkipHot = [&]() { if (!ClHotPercentileCutoff.getNumOccurrences()) return false; auto &MAMProxy = FAM.getResult(F); @@ -1544,7 +1540,16 @@ bool HWAddressSanitizer::selectiveInstrumentationShouldSkip( } return PSI->isFunctionHotInCallGraphNthPercentile( ClHotPercentileCutoff, &F, FAM.getResult(F)); - }(); + }; + + auto SkipRandom = [&]() { + if (!ClRandomSkipRate.getNumOccurrences()) + return false; + std::bernoulli_distribution D(ClRandomSkipRate); + return !D(*Rng); + }; + + bool Skip = SkipRandom() || SkipHot(); emitRemark(F, FAM.getResult(F), Skip); return Skip; } diff --git a/llvm/lib/Transforms/Instrumentation/LowerAllowCheckPass.cpp b/llvm/lib/Transforms/Instrumentation/LowerAllowCheckPass.cpp index 0115809e939e8c..19cf7dc7e75443 100644 --- a/llvm/lib/Transforms/Instrumentation/LowerAllowCheckPass.cpp +++ b/llvm/lib/Transforms/Instrumentation/LowerAllowCheckPass.cpp @@ -76,13 +76,25 @@ static bool removeUbsanTraps(Function &F, const BlockFrequencyInfo &BFI, SmallVector, 16> ReplaceWithValue; std::unique_ptr Rng; - auto ShouldRemove = [&](bool IsHot) { - if (!RandomRate.getNumOccurrences()) - return IsHot; + auto GetRng = [&]() -> RandomNumberGenerator & { if (!Rng) Rng = F.getParent()->createRNG(F.getName()); - std::bernoulli_distribution D(RandomRate); - return !D(*Rng); + return *Rng; + }; + + auto ShouldRemoveHot = [&](const BasicBlock &BB) { + return HotPercentileCutoff.getNumOccurrences() && PSI && + PSI->isHotCountNthPercentile( + HotPercentileCutoff, BFI.getBlockProfileCount(&BB).value_or(0)); + }; + + auto ShouldRemoveRandom = [&]() { + return RandomRate.getNumOccurrences() && + !std::bernoulli_distribution(RandomRate)(GetRng()); + }; + + auto ShouldRemove = [&](const BasicBlock &BB) { + return ShouldRemoveRandom() || ShouldRemoveHot(BB); }; for (BasicBlock &BB : F) { @@ -96,13 +108,7 @@ static bool removeUbsanTraps(Function &F, const BlockFrequencyInfo &BFI, case Intrinsic::allow_runtime_check: { ++NumChecksTotal; - bool IsHot = false; - if (PSI) { - uint64_t Count = BFI.getBlockProfileCount(&BB).value_or(0); - IsHot = PSI->isHotCountNthPercentile(HotPercentileCutoff, Count); - } - - bool ToRemove = ShouldRemove(IsHot); + bool ToRemove = ShouldRemove(BB); ReplaceWithValue.push_back({ II, ToRemove, diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out.ll b/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out.ll index 01eda4e35d7c1b..0ef94235fd515e 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out.ll @@ -2,6 +2,8 @@ ; RUN: opt < %s -passes='require,hwasan' -pass-remarks=hwasan -pass-remarks-missed=hwasan -S -hwasan-percentile-cutoff-hot=990000 2>&1 | FileCheck %s --check-prefix=NONE ; RUN: opt < %s -passes='require,hwasan' -pass-remarks=hwasan -pass-remarks-missed=hwasan -S -hwasan-random-rate=1.0 2>&1 | FileCheck %s --check-prefix=ALL ; RUN: opt < %s -passes='require,hwasan' -pass-remarks=hwasan -pass-remarks-missed=hwasan -S -hwasan-random-rate=0.0 2>&1 | FileCheck %s --check-prefix=NONE +; RUN: opt < %s -passes='require,hwasan' -pass-remarks=hwasan -pass-remarks-missed=hwasan -S -hwasan-random-rate=1.0 -hwasan-percentile-cutoff-hot=990000 2>&1 | FileCheck %s --check-prefix=NONE +; RUN: opt < %s -passes='require,hwasan' -pass-remarks=hwasan -pass-remarks-missed=hwasan -S -hwasan-random-rate=0.0 -hwasan-percentile-cutoff-hot=700000 2>&1 | FileCheck %s --check-prefix=NONE ; ALL: remark: :0:0: Sanitized: F=sanitize ; ALL: @sanitized diff --git a/llvm/test/Transforms/lower-builtin-allow-check.ll b/llvm/test/Transforms/lower-builtin-allow-check.ll index 2f6fa96ffd9c5f..bcd9722d2b289d 100644 --- a/llvm/test/Transforms/lower-builtin-allow-check.ll +++ b/llvm/test/Transforms/lower-builtin-allow-check.ll @@ -309,7 +309,7 @@ define dso_local noundef i32 @veryHot(ptr noundef readonly %0) !prof !39 { ; ALL70-LABEL: define dso_local noundef i32 @veryHot( ; ALL70-SAME: ptr noundef readonly [[TMP0:%.*]]) !prof [[PROF17:![0-9]+]] { ; ALL70-NEXT: [[CHK:%.*]] = icmp eq ptr [[TMP0]], null -; ALL70-NEXT: [[HOT:%.*]] = xor i1 true, true +; ALL70-NEXT: [[HOT:%.*]] = xor i1 false, true ; ALL70-NEXT: [[TMP2:%.*]] = or i1 [[CHK]], [[HOT]] ; ALL70-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]] ; ALL70: 3: