20
20
#include " llvm/IR/Intrinsics.h"
21
21
#include " llvm/IR/Metadata.h"
22
22
#include " llvm/IR/Module.h"
23
+ #include " llvm/Support/Debug.h"
23
24
#include " llvm/Support/RandomNumberGenerator.h"
24
25
#include < memory>
25
26
#include < random>
@@ -71,7 +72,8 @@ static void emitRemark(IntrinsicInst *II, OptimizationRemarkEmitter &ORE,
71
72
72
73
static bool removeUbsanTraps (Function &F, const BlockFrequencyInfo &BFI,
73
74
const ProfileSummaryInfo *PSI,
74
- OptimizationRemarkEmitter &ORE) {
75
+ OptimizationRemarkEmitter &ORE,
76
+ const std::vector<unsigned int > &cutoffs) {
75
77
SmallVector<std::pair<IntrinsicInst *, bool >, 16 > ReplaceWithValue;
76
78
std::unique_ptr<RandomNumberGenerator> Rng;
77
79
@@ -81,19 +83,32 @@ static bool removeUbsanTraps(Function &F, const BlockFrequencyInfo &BFI,
81
83
return *Rng;
82
84
};
83
85
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 )));
88
102
};
89
103
90
104
auto ShouldRemoveRandom = [&]() {
91
105
return RandomRate.getNumOccurrences () &&
92
106
!std::bernoulli_distribution (RandomRate)(GetRng ());
93
107
};
94
108
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);
97
112
};
98
113
99
114
for (BasicBlock &BB : F) {
@@ -107,7 +122,8 @@ static bool removeUbsanTraps(Function &F, const BlockFrequencyInfo &BFI,
107
122
case Intrinsic::allow_runtime_check: {
108
123
++NumChecksTotal;
109
124
110
- bool ToRemove = ShouldRemove (BB);
125
+ bool ToRemove = ShouldRemove (II);
126
+
111
127
ReplaceWithValue.push_back ({
112
128
II,
113
129
ToRemove,
@@ -142,11 +158,37 @@ PreservedAnalyses LowerAllowCheckPass::run(Function &F,
142
158
OptimizationRemarkEmitter &ORE =
143
159
AM.getResult <OptimizationRemarkEmitterAnalysis>(F);
144
160
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 ();
147
164
}
148
165
149
166
bool LowerAllowCheckPass::IsRequested () {
150
167
return RandomRate.getNumOccurrences () ||
151
168
HotPercentileCutoff.getNumOccurrences ();
152
169
}
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