From e7c3cd245665042bbae163f7280aceed35f0fee5 Mon Sep 17 00:00:00 2001 From: Kirill Stoimenov <87100199+kstoimenov@users.noreply.github.com> Date: Thu, 29 Feb 2024 17:34:32 -0800 Subject: [HWASAN] Implement selective instrumentation based on profiling information (#83503) --- .../Instrumentation/HWAddressSanitizer.cpp | 36 ++++++++++++++++++++++ .../HWAddressSanitizer/pgo-opt-out-no-ps.ll | 14 +++++++++ .../HWAddressSanitizer/pgo-opt-out.ll | 31 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out-no-ps.ll create mode 100644 llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out.ll diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 33add6d..4404382 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -15,11 +15,14 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/StackSafetyAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/ValueTracking.h" @@ -177,6 +180,18 @@ static cl::opt ClWithTls( "platforms that support this"), cl::Hidden, cl::init(true)); +static cl::opt + CSkipHotCode("hwasan-skip-hot-code", + cl::desc("Do not instument hot functions based on FDO."), + cl::Hidden, cl::init(false)); + +static cl::opt HotPercentileCutoff("hwasan-percentile-cutoff-hot", + cl::init(0)); + +STATISTIC(NumTotalFuncs, "Number of total funcs HWASAN"); +STATISTIC(NumInstrumentedFuncs, "Number of HWASAN instrumented funcs"); +STATISTIC(NumNoProfileSummaryFuncs, "Number of HWASAN funcs without PS"); + // Mode for selecting how to insert frame record info into the stack ring // buffer. enum RecordStackHistoryMode { @@ -1507,6 +1522,27 @@ void HWAddressSanitizer::sanitizeFunction(Function &F, if (!F.hasFnAttribute(Attribute::SanitizeHWAddress)) return; + if (F.empty()) + return; + + NumTotalFuncs++; + if (CSkipHotCode) { + auto &MAMProxy = FAM.getResult(F); + ProfileSummaryInfo *PSI = + MAMProxy.getCachedResult(*F.getParent()); + if (PSI && PSI->hasProfileSummary()) { + auto &BFI = FAM.getResult(F); + if ((HotPercentileCutoff.getNumOccurrences() && HotPercentileCutoff >= 0) + ? PSI->isFunctionHotInCallGraphNthPercentile(HotPercentileCutoff, + &F, BFI) + : PSI->isFunctionHotInCallGraph(&F, BFI)) + return; + } else { + ++NumNoProfileSummaryFuncs; + } + } + NumInstrumentedFuncs++; + LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n"); SmallVector OperandsToInstrument; diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out-no-ps.ll b/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out-no-ps.ll new file mode 100644 index 0000000..ebc0366 --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out-no-ps.ll @@ -0,0 +1,14 @@ +; RUN: opt < %s -passes='require,hwasan' -S -stats 2>&1 \ +; RUN: -hwasan-skip-hot-code=0 | FileCheck %s --check-prefix=FULL +; RUN: opt < %s -passes='require,hwasan' -S -stats 2>&1 \ +; RUN: -hwasan-skip-hot-code=1 | FileCheck %s --check-prefix=SELSAN + +; FULL: 1 hwasan - Number of HWASAN instrumented funcs +; FULL: 1 hwasan - Number of total funcs HWASAN + +; SELSAN: 1 hwasan - Number of HWASAN instrumented funcs +; SELSAN: 1 hwasan - Number of HWASAN funcs without PS +; SELSAN: 1 hwasan - Number of total funcs HWASAN + +define void @not_sanitized() { ret void } +define void @sanitized_no_ps() sanitize_hwaddress { ret void } diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out.ll b/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out.ll new file mode 100644 index 0000000..ea5366c --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/pgo-opt-out.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -passes='require,hwasan' -S -stats 2>&1 \ +; RUN: -hwasan-skip-hot-code=1 | FileCheck %s --check-prefix=DEFAULT +; RUN: opt < %s -passes='require,hwasan' -S -stats 2>&1 \ +; RUN: -hwasan-skip-hot-code=1 -hwasan-percentile-cutoff-hot=700000 | FileCheck %s --check-prefix=PERCENT + +; DEFAULT: 1 hwasan - Number of total funcs HWASAN + +; PERCENT: 1 hwasan - Number of HWASAN instrumented funcs +; PERCENT: 1 hwasan - Number of total funcs HWASAN + +define void @sanitized() sanitize_hwaddress !prof !36 { ret void } + +!llvm.module.flags = !{!6} +!6 = !{i32 1, !"ProfileSummary", !7} +!7 = !{!8, !9, !10, !11, !12, !13, !14, !17} +!8 = !{!"ProfileFormat", !"InstrProf"} +!9 = !{!"TotalCount", i64 30000} +!10 = !{!"MaxCount", i64 10000} +!11 = !{!"MaxInternalCount", i64 10000} +!12 = !{!"MaxFunctionCount", i64 10000} +!13 = !{!"NumCounts", i64 3} +!14 = !{!"NumFunctions", i64 5} +!17 = !{!"DetailedSummary", !18} +!18 = !{!19, !29, !30, !32, !34} +!19 = !{i32 10000, i64 10000, i32 3} +!29 = !{i32 950000, i64 5000, i32 3} +!30 = !{i32 990000, i64 500, i32 4} +!32 = !{i32 999900, i64 250, i32 4} +!34 = !{i32 999999, i64 1, i32 6} + +!36 = !{!"function_entry_count", i64 1000} -- cgit v1.1