//===- 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 #include using namespace llvm; #define DEBUG_TYPE "remove-traps" static cl::opt HotPercentileCutoff( "remove-traps-percentile-cutoff-hot", cl::init(0), cl::desc("Alternative hot percentile cuttoff. By default " "`-profile-summary-cutoff-hot` is used.")); static cl::opt RandomRate("remove-traps-random-rate", cl::init(0.0), 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 Remove; std::unique_ptr 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(&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 = HotPercentileCutoff.getNumOccurrences() ? (HotPercentileCutoff > 0 && PSI->isHotCountNthPercentile(HotPercentileCutoff, Count)) : PSI->isHotCount(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(F); ProfileSummaryInfo *PSI = MAMProxy.getCachedResult(*F.getParent()); BlockFrequencyInfo &BFI = AM.getResult(F); return removeUbsanTraps(F, BFI, PSI) ? PreservedAnalyses::none() : PreservedAnalyses::all(); }