31#define DEBUG_TYPE "lower-expect-intrinsic"
34 "Number of 'expect' intrinsic instructions handled");
50 cl::desc(
"Weight of the branch likely to be taken (default = 2000)"));
53 cl::desc(
"Weight of the branch unlikely to be taken (default = 1)"));
55static std::tuple<uint32_t, uint32_t>
57 if (IntrinsicID == Intrinsic::expect) {
64 "expect with probability must have 3 arguments");
66 double TrueProb = Confidence->getValueAPF().convertToDouble();
67 assert((TrueProb >= 0.0 && TrueProb <= 1.0) &&
68 "probability value must be in the range [0.0, 1.0]");
69 double FalseProb = (1.0 - TrueProb) / (BranchCount - 1);
70 uint32_t LikelyBW = ceil((TrueProb * (
double)(INT32_MAX - 1)) + 1.0);
71 uint32_t UnlikelyBW = ceil((FalseProb * (
double)(INT32_MAX - 1)) + 1.0);
72 return std::make_tuple(LikelyBW, UnlikelyBW);
77 CallInst *CI = dyn_cast<CallInst>(SI.getCondition());
92 unsigned n = SI.getNumCases();
93 uint32_t LikelyBranchWeightVal, UnlikelyBranchWeightVal;
94 std::tie(LikelyBranchWeightVal, UnlikelyBranchWeightVal) =
100 Weights[Index] = LikelyBranchWeightVal;
104 SI.setCondition(ArgValue);
122 bool ExpectedValueIsLikely =
true;
129 auto *Confidence = cast<ConstantFP>(Expect->
getArgOperand(2));
130 double TrueProb = Confidence->getValueAPF().convertToDouble();
131 ExpectedValueIsLikely = (TrueProb > 0.5);
146 while (!isa<PHINode>(V)) {
147 if (
ZExtInst *ZExt = dyn_cast<ZExtInst>(V)) {
148 V = ZExt->getOperand(0);
153 if (
SExtInst *SExt = dyn_cast<SExtInst>(V)) {
154 V = SExt->getOperand(0);
160 if (!BinOp || BinOp->
getOpcode() != Instruction::Xor)
172 auto ApplyOperations = [&](
const APInt &
Value) {
175 switch (
Op->getOpcode()) {
176 case Instruction::Xor:
177 Result ^= cast<ConstantInt>(
Op->getOperand(1))->getValue();
179 case Instruction::ZExt:
180 Result = Result.zext(
Op->getType()->getIntegerBitWidth());
182 case Instruction::SExt:
183 Result = Result.sext(
Op->getType()->getIntegerBitWidth());
192 auto *PhiDef = cast<PHINode>(V);
196 auto GetDomConditional = [&](
unsigned i) ->
BranchInst * {
213 for (
unsigned i = 0, e = PhiDef->getNumIncomingValues(); i != e; ++i) {
215 Value *PhiOpnd = PhiDef->getIncomingValue(i);
225 const APInt &CurrentPhiValue = ApplyOperations(CI->
getValue());
226 if (ExpectedValueIsLikely == (ExpectedPhiValue == CurrentPhiValue))
243 auto *OpndIncomingBB = PhiDef->getIncomingBlock(i);
244 auto IsOpndComingFromSuccessor = [&](
BasicBlock *Succ) {
245 if (OpndIncomingBB == Succ)
249 if (OpndIncomingBB == BI->
getParent() && Succ == PhiDef->getParent())
256 uint32_t LikelyBranchWeightVal, UnlikelyBranchWeightVal;
257 std::tie(LikelyBranchWeightVal, UnlikelyBranchWeightVal) =
getBranchWeight(
259 if (!ExpectedValueIsLikely)
260 std::swap(LikelyBranchWeightVal, UnlikelyBranchWeightVal);
265 UnlikelyBranchWeightVal,
267 else if (IsOpndComingFromSuccessor(BI->
getSuccessor(0)))
270 LikelyBranchWeightVal,
289 ICmpInst *CmpI = dyn_cast<ICmpInst>(BSI.getCondition());
293 CI = dyn_cast<CallInst>(BSI.getCondition());
300 CmpConstOperand = dyn_cast<ConstantInt>(CmpI->
getOperand(1));
301 if (!CmpConstOperand)
310 if (CmpConstOperand) {
329 uint32_t LikelyBranchWeightVal, UnlikelyBranchWeightVal;
330 std::tie(LikelyBranchWeightVal, UnlikelyBranchWeightVal) =
334 if ((ExpectedValue->
getZExtValue() == ValueComparedTo) ==
337 LikelyBranchWeightVal, UnlikelyBranchWeightVal,
true);
338 ExpectedWeights = {LikelyBranchWeightVal, UnlikelyBranchWeightVal};
341 LikelyBranchWeightVal,
true);
342 ExpectedWeights = {UnlikelyBranchWeightVal, LikelyBranchWeightVal};
348 BSI.setCondition(ArgValue);
352 BSI.setMetadata(LLVMContext::MD_prof,
Node);
361 return handleBrSelExpect<BranchInst>(BI);
365 bool Changed =
false;
369 if (
BranchInst *BI = dyn_cast<BranchInst>(BB.getTerminator())) {
371 ExpectIntrinsicsHandled++;
372 }
else if (
SwitchInst *SI = dyn_cast<SwitchInst>(BB.getTerminator())) {
374 ExpectIntrinsicsHandled++;
381 CallInst *CI = dyn_cast<CallInst>(&Inst);
383 if (
SelectInst *SI = dyn_cast<SelectInst>(&Inst)) {
385 ExpectIntrinsicsHandled++;
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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 bool handleBranchExpect(BranchInst &BI)
static std::tuple< uint32_t, uint32_t > getBranchWeight(Intrinsic::ID IntrinsicID, CallInst *CI, int BranchCount)
static bool handleBrSelExpect(BrSelInst &BSI)
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 bool handleSwitchExpect(SwitchInst &SI)
static bool lowerExpectIntrinsic(Function &F)
static void handlePhiDef(CallInst *Expect)
Handler for PHINodes that define the value argument to an @llvm.expect call.
The header file for the LowerExpectIntrinsic pass as used by the new pass manager.
This file contains the declarations for profiling metadata utility functions.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
LLVM Basic Block Representation.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
BinaryOps getOpcode() const
Conditional or Unconditional Branch instruction.
bool isConditional() const
BasicBlock * getSuccessor(unsigned i) const
bool isUnconditional() const
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getArgOperand(unsigned i) const
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Predicate getPredicate() const
Return the predicate for this instruction.
This is the shared class of boolean and integer constants.
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
This class represents an Operation in the Expression.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
This instruction compares its operands according to the predicate given to the constructor.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)
Return metadata containing two branch weights.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This class represents a sign extension of integer types.
This class represents the LLVM 'select' instruction.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
unsigned getCaseIndex() const
Returns number of current case.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
This class represents zero extension of integer types.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
void checkFrontendInstrumentation(Instruction &I, const ArrayRef< uint32_t > ExpectedWeights)
checkFrontendInstrumentation - compares PGO counters to the thresholds used for llvm....
void checkExpectAnnotations(Instruction &I, const ArrayRef< uint32_t > ExistingWeights, bool IsFrontend)
checkExpectAnnotations - compares PGO counters to the thresholds used for llvm.expect and warns if th...
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto reverse(ContainerTy &&C)
void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected)
Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
Run the pass over the function.