2020#include " llvm/IR/Intrinsics.h"
2121#include " llvm/IR/Metadata.h"
2222#include " llvm/IR/Module.h"
23+ #include " llvm/Support/Debug.h"
2324#include " llvm/Support/RandomNumberGenerator.h"
2425#include < memory>
2526#include < random>
@@ -71,7 +72,8 @@ static void emitRemark(IntrinsicInst *II, OptimizationRemarkEmitter &ORE,
7172
7273static bool removeUbsanTraps (Function &F, const BlockFrequencyInfo &BFI,
7374 const ProfileSummaryInfo *PSI,
74- OptimizationRemarkEmitter &ORE) {
75+ OptimizationRemarkEmitter &ORE,
76+ const std::vector<unsigned int > &cutoffs) {
7577 SmallVector<std::pair<IntrinsicInst *, bool >, 16 > ReplaceWithValue;
7678 std::unique_ptr<RandomNumberGenerator> Rng;
7779
@@ -81,19 +83,32 @@ static bool removeUbsanTraps(Function &F, const BlockFrequencyInfo &BFI,
8183 return *Rng;
8284 };
8385
84- auto ShouldRemoveHot = [&](const BasicBlock &BB) {
85- return HotPercentileCutoff.getNumOccurrences () && PSI &&
86- PSI->isHotCountNthPercentile (
87- HotPercentileCutoff, BFI.getBlockProfileCount (&BB).value_or (0 ));
86+ auto GetCutoff = [&](const IntrinsicInst *II) -> unsigned {
87+ if (HotPercentileCutoff.getNumOccurrences ())
88+ return HotPercentileCutoff;
89+ else if (II->getIntrinsicID () == Intrinsic::allow_ubsan_check) {
90+ auto *Kind = cast<ConstantInt>(II->getArgOperand (0 ));
91+ if (Kind->getZExtValue () < cutoffs.size ())
92+ return cutoffs[Kind->getZExtValue ()];
93+ }
94+
95+ return 0 ;
96+ };
97+
98+ auto ShouldRemoveHot = [&](const BasicBlock &BB, unsigned int cutoff) {
99+ return (cutoff == 1000000 ) ||
100+ (PSI && PSI->isHotCountNthPercentile (
101+ cutoff, BFI.getBlockProfileCount (&BB).value_or (0 )));
88102 };
89103
90104 auto ShouldRemoveRandom = [&]() {
91105 return RandomRate.getNumOccurrences () &&
92106 !std::bernoulli_distribution (RandomRate)(GetRng ());
93107 };
94108
95- auto ShouldRemove = [&](const BasicBlock &BB) {
96- return ShouldRemoveRandom () || ShouldRemoveHot (BB);
109+ auto ShouldRemove = [&](const IntrinsicInst *II) {
110+ unsigned int cutoff = GetCutoff (II);
111+ return ShouldRemoveRandom () || ShouldRemoveHot (*(II->getParent ()), cutoff);
97112 };
98113
99114 for (BasicBlock &BB : F) {
@@ -107,7 +122,8 @@ static bool removeUbsanTraps(Function &F, const BlockFrequencyInfo &BFI,
107122 case Intrinsic::allow_runtime_check: {
108123 ++NumChecksTotal;
109124
110- bool ToRemove = ShouldRemove (BB);
125+ bool ToRemove = ShouldRemove (II);
126+
111127 ReplaceWithValue.push_back ({
112128 II,
113129 ToRemove,
@@ -142,11 +158,37 @@ PreservedAnalyses LowerAllowCheckPass::run(Function &F,
142158 OptimizationRemarkEmitter &ORE =
143159 AM.getResult <OptimizationRemarkEmitterAnalysis>(F);
144160
145- return removeUbsanTraps (F, BFI, PSI, ORE) ? PreservedAnalyses::none ()
146- : PreservedAnalyses::all ();
161+ return removeUbsanTraps (F, BFI, PSI, ORE, Opts.cutoffs )
162+ ? PreservedAnalyses::none ()
163+ : PreservedAnalyses::all ();
147164}
148165
149166bool LowerAllowCheckPass::IsRequested () {
150167 return RandomRate.getNumOccurrences () ||
151168 HotPercentileCutoff.getNumOccurrences ();
152169}
170+
171+ void LowerAllowCheckPass::printPipeline (
172+ raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
173+ static_cast <PassInfoMixin<LowerAllowCheckPass> *>(this )->printPipeline (
174+ OS, MapClassName2PassName);
175+ OS << " <" ;
176+
177+ // Format is <cutoffs[0,1,2]=70000;cutoffs[5,6,8]=90000>
178+ // but it's equally valid to specify
179+ // cutoffs[0]=70000;cutoffs[1]=70000;cutoffs[2]=70000;cutoffs[5]=90000;...
180+ // and that's what we do here. It is verbose but valid and easy to verify
181+ // correctness.
182+ // TODO: print shorter output by combining adjacent runs, etc.
183+ int i = 0 ;
184+ for (unsigned int cutoff : Opts.cutoffs ) {
185+ if (cutoff > 0 ) {
186+ if (i > 0 )
187+ OS << " ;" ;
188+ OS << " cutoffs[" << i << " ]=" << cutoff;
189+ }
190+
191+ i++;
192+ }
193+ OS << ' >' ;
194+ }
0 commit comments