//===- LowerExpectIntrinsic.cpp - Lower expect intrinsic ------------------===// // // 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 // //===----------------------------------------------------------------------===// // // This pass lowers the 'expect' intrinsic to LLVM metadata. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/ProfDataUtils.h" #include "llvm/Support/CommandLine.h" #include "llvm/Transforms/Utils/MisExpect.h" #include <cmath> usingnamespacellvm; #define DEBUG_TYPE … STATISTIC(ExpectIntrinsicsHandled, "Number of 'expect' intrinsic instructions handled"); // These default values are chosen to represent an extremely skewed outcome for // a condition, but they leave some room for interpretation by later passes. // // If the documentation for __builtin_expect() was made explicit that it should // only be used in extreme cases, we could make this ratio higher. As it stands, // programmers may be using __builtin_expect() / llvm.expect to annotate that a // branch is likely or unlikely to be taken. // WARNING: these values are internal implementation detail of the pass. // They should not be exposed to the outside of the pass, front-end codegen // should emit @llvm.expect intrinsics instead of using these weights directly. // Transforms should use TargetTransformInfo's getPredictableBranchThreshold(). static cl::opt<uint32_t> LikelyBranchWeight( "likely-branch-weight", cl::Hidden, cl::init(2000), cl::desc("Weight of the branch likely to be taken (default = 2000)")); static cl::opt<uint32_t> UnlikelyBranchWeight( "unlikely-branch-weight", cl::Hidden, cl::init(1), cl::desc("Weight of the branch unlikely to be taken (default = 1)")); static std::tuple<uint32_t, uint32_t> getBranchWeight(Intrinsic::ID IntrinsicID, CallInst *CI, int BranchCount) { … } static bool handleSwitchExpect(SwitchInst &SI) { … } /// Handler for PHINodes that define the value argument to an /// @llvm.expect call. /// /// If the operand of the phi has a constant value and it 'contradicts' /// with the expected value of phi def, then the corresponding incoming /// edge of the phi is unlikely to be taken. Using that information, /// the branch probability info for the originating branch can be inferred. static void handlePhiDef(CallInst *Expect) { … } // Handle both BranchInst and SelectInst. template <class BrSelInst> static bool handleBrSelExpect(BrSelInst &BSI) { … } static bool handleBranchExpect(BranchInst &BI) { … } static bool lowerExpectIntrinsic(Function &F) { … } PreservedAnalyses LowerExpectIntrinsicPass::run(Function &F, FunctionAnalysisManager &) { … }