mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 21:53:12 +08:00
103 lines
3.2 KiB
C++
103 lines
3.2 KiB
C++
//===- RemoveTrapsPass.cpp --------------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Transforms/Instrumentation/RemoveTrapsPass.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "llvm/IR/Intrinsics.h"
|
|
#include "llvm/Support/RandomNumberGenerator.h"
|
|
#include <memory>
|
|
#include <random>
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "remove-traps"
|
|
|
|
static cl::opt<int> HotPercentileCutoff("remove-traps-percentile-cutoff-hot",
|
|
cl::desc("Hot percentile cuttoff."));
|
|
|
|
static cl::opt<float>
|
|
RandomRate("remove-traps-random-rate",
|
|
cl::desc("Probability value in the range [0.0, 1.0] of "
|
|
"unconditional pseudo-random checks removal."));
|
|
|
|
STATISTIC(NumChecksTotal, "Number of checks");
|
|
STATISTIC(NumChecksRemoved, "Number of removed checks");
|
|
|
|
static bool removeUbsanTraps(Function &F, const BlockFrequencyInfo &BFI,
|
|
const ProfileSummaryInfo *PSI) {
|
|
SmallVector<IntrinsicInst *, 16> Remove;
|
|
std::unique_ptr<RandomNumberGenerator> Rng;
|
|
|
|
auto ShouldRemove = [&](bool IsHot) {
|
|
if (!RandomRate.getNumOccurrences())
|
|
return IsHot;
|
|
if (!Rng)
|
|
Rng = F.getParent()->createRNG(F.getName());
|
|
std::bernoulli_distribution D(RandomRate);
|
|
return D(*Rng);
|
|
};
|
|
|
|
for (BasicBlock &BB : F) {
|
|
for (Instruction &I : BB) {
|
|
IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
|
|
if (!II)
|
|
continue;
|
|
auto ID = II->getIntrinsicID();
|
|
switch (ID) {
|
|
case Intrinsic::ubsantrap: {
|
|
++NumChecksTotal;
|
|
|
|
bool IsHot = false;
|
|
if (PSI) {
|
|
uint64_t Count = 0;
|
|
for (const auto *PR : predecessors(&BB))
|
|
Count += BFI.getBlockProfileCount(PR).value_or(0);
|
|
IsHot = PSI->isHotCountNthPercentile(HotPercentileCutoff, Count);
|
|
}
|
|
|
|
if (ShouldRemove(IsHot)) {
|
|
Remove.push_back(II);
|
|
++NumChecksRemoved;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (IntrinsicInst *I : Remove)
|
|
I->eraseFromParent();
|
|
|
|
return !Remove.empty();
|
|
}
|
|
|
|
PreservedAnalyses RemoveTrapsPass::run(Function &F,
|
|
FunctionAnalysisManager &AM) {
|
|
if (F.isDeclaration())
|
|
return PreservedAnalyses::all();
|
|
auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
|
|
ProfileSummaryInfo *PSI =
|
|
MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
|
|
BlockFrequencyInfo &BFI = AM.getResult<BlockFrequencyAnalysis>(F);
|
|
|
|
return removeUbsanTraps(F, BFI, PSI) ? PreservedAnalyses::none()
|
|
: PreservedAnalyses::all();
|
|
}
|
|
|
|
bool RemoveTrapsPass::IsRequested() {
|
|
return RandomRate.getNumOccurrences() ||
|
|
HotPercentileCutoff.getNumOccurrences();
|
|
}
|