1*72793727SChandler Carruth //===- LowerExpectIntrinsic.cpp - Lower expect intrinsic ------------------===// 2*72793727SChandler Carruth // 3*72793727SChandler Carruth // The LLVM Compiler Infrastructure 4*72793727SChandler Carruth // 5*72793727SChandler Carruth // This file is distributed under the University of Illinois Open Source 6*72793727SChandler Carruth // License. See LICENSE.TXT for details. 7*72793727SChandler Carruth // 8*72793727SChandler Carruth //===----------------------------------------------------------------------===// 9*72793727SChandler Carruth // 10*72793727SChandler Carruth // This pass lowers the 'expect' intrinsic to LLVM metadata. 11*72793727SChandler Carruth // 12*72793727SChandler Carruth //===----------------------------------------------------------------------===// 13*72793727SChandler Carruth 14*72793727SChandler Carruth #include "llvm/Transforms/Scalar.h" 15*72793727SChandler Carruth #include "llvm/ADT/Statistic.h" 16*72793727SChandler Carruth #include "llvm/IR/BasicBlock.h" 17*72793727SChandler Carruth #include "llvm/IR/Constants.h" 18*72793727SChandler Carruth #include "llvm/IR/Function.h" 19*72793727SChandler Carruth #include "llvm/IR/Instructions.h" 20*72793727SChandler Carruth #include "llvm/IR/Intrinsics.h" 21*72793727SChandler Carruth #include "llvm/IR/LLVMContext.h" 22*72793727SChandler Carruth #include "llvm/IR/MDBuilder.h" 23*72793727SChandler Carruth #include "llvm/IR/Metadata.h" 24*72793727SChandler Carruth #include "llvm/Pass.h" 25*72793727SChandler Carruth #include "llvm/Support/CommandLine.h" 26*72793727SChandler Carruth #include "llvm/Support/Debug.h" 27*72793727SChandler Carruth #include <vector> 28*72793727SChandler Carruth 29*72793727SChandler Carruth using namespace llvm; 30*72793727SChandler Carruth 31*72793727SChandler Carruth #define DEBUG_TYPE "lower-expect-intrinsic" 32*72793727SChandler Carruth 33*72793727SChandler Carruth STATISTIC(IfHandled, "Number of 'expect' intrinsic instructions handled"); 34*72793727SChandler Carruth 35*72793727SChandler Carruth static cl::opt<uint32_t> 36*72793727SChandler Carruth LikelyBranchWeight("likely-branch-weight", cl::Hidden, cl::init(64), 37*72793727SChandler Carruth cl::desc("Weight of the branch likely to be taken (default = 64)")); 38*72793727SChandler Carruth static cl::opt<uint32_t> 39*72793727SChandler Carruth UnlikelyBranchWeight("unlikely-branch-weight", cl::Hidden, cl::init(4), 40*72793727SChandler Carruth cl::desc("Weight of the branch unlikely to be taken (default = 4)")); 41*72793727SChandler Carruth 42*72793727SChandler Carruth namespace { 43*72793727SChandler Carruth 44*72793727SChandler Carruth class LowerExpectIntrinsic : public FunctionPass { 45*72793727SChandler Carruth 46*72793727SChandler Carruth bool HandleSwitchExpect(SwitchInst *SI); 47*72793727SChandler Carruth 48*72793727SChandler Carruth bool HandleIfExpect(BranchInst *BI); 49*72793727SChandler Carruth 50*72793727SChandler Carruth public: 51*72793727SChandler Carruth static char ID; 52*72793727SChandler Carruth LowerExpectIntrinsic() : FunctionPass(ID) { 53*72793727SChandler Carruth initializeLowerExpectIntrinsicPass(*PassRegistry::getPassRegistry()); 54*72793727SChandler Carruth } 55*72793727SChandler Carruth 56*72793727SChandler Carruth bool runOnFunction(Function &F) override; 57*72793727SChandler Carruth }; 58*72793727SChandler Carruth } 59*72793727SChandler Carruth 60*72793727SChandler Carruth 61*72793727SChandler Carruth bool LowerExpectIntrinsic::HandleSwitchExpect(SwitchInst *SI) { 62*72793727SChandler Carruth CallInst *CI = dyn_cast<CallInst>(SI->getCondition()); 63*72793727SChandler Carruth if (!CI) 64*72793727SChandler Carruth return false; 65*72793727SChandler Carruth 66*72793727SChandler Carruth Function *Fn = CI->getCalledFunction(); 67*72793727SChandler Carruth if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect) 68*72793727SChandler Carruth return false; 69*72793727SChandler Carruth 70*72793727SChandler Carruth Value *ArgValue = CI->getArgOperand(0); 71*72793727SChandler Carruth ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1)); 72*72793727SChandler Carruth if (!ExpectedValue) 73*72793727SChandler Carruth return false; 74*72793727SChandler Carruth 75*72793727SChandler Carruth SwitchInst::CaseIt Case = SI->findCaseValue(ExpectedValue); 76*72793727SChandler Carruth unsigned n = SI->getNumCases(); // +1 for default case. 77*72793727SChandler Carruth std::vector<uint32_t> Weights(n + 1); 78*72793727SChandler Carruth 79*72793727SChandler Carruth Weights[0] = Case == SI->case_default() ? LikelyBranchWeight 80*72793727SChandler Carruth : UnlikelyBranchWeight; 81*72793727SChandler Carruth for (unsigned i = 0; i != n; ++i) 82*72793727SChandler Carruth Weights[i + 1] = i == Case.getCaseIndex() ? LikelyBranchWeight 83*72793727SChandler Carruth : UnlikelyBranchWeight; 84*72793727SChandler Carruth 85*72793727SChandler Carruth SI->setMetadata(LLVMContext::MD_prof, 86*72793727SChandler Carruth MDBuilder(CI->getContext()).createBranchWeights(Weights)); 87*72793727SChandler Carruth 88*72793727SChandler Carruth SI->setCondition(ArgValue); 89*72793727SChandler Carruth return true; 90*72793727SChandler Carruth } 91*72793727SChandler Carruth 92*72793727SChandler Carruth 93*72793727SChandler Carruth bool LowerExpectIntrinsic::HandleIfExpect(BranchInst *BI) { 94*72793727SChandler Carruth if (BI->isUnconditional()) 95*72793727SChandler Carruth return false; 96*72793727SChandler Carruth 97*72793727SChandler Carruth // Handle non-optimized IR code like: 98*72793727SChandler Carruth // %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1) 99*72793727SChandler Carruth // %tobool = icmp ne i64 %expval, 0 100*72793727SChandler Carruth // br i1 %tobool, label %if.then, label %if.end 101*72793727SChandler Carruth // 102*72793727SChandler Carruth // Or the following simpler case: 103*72793727SChandler Carruth // %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1) 104*72793727SChandler Carruth // br i1 %expval, label %if.then, label %if.end 105*72793727SChandler Carruth 106*72793727SChandler Carruth CallInst *CI; 107*72793727SChandler Carruth 108*72793727SChandler Carruth ICmpInst *CmpI = dyn_cast<ICmpInst>(BI->getCondition()); 109*72793727SChandler Carruth if (!CmpI) { 110*72793727SChandler Carruth CI = dyn_cast<CallInst>(BI->getCondition()); 111*72793727SChandler Carruth } else { 112*72793727SChandler Carruth if (CmpI->getPredicate() != CmpInst::ICMP_NE) 113*72793727SChandler Carruth return false; 114*72793727SChandler Carruth CI = dyn_cast<CallInst>(CmpI->getOperand(0)); 115*72793727SChandler Carruth } 116*72793727SChandler Carruth 117*72793727SChandler Carruth if (!CI) 118*72793727SChandler Carruth return false; 119*72793727SChandler Carruth 120*72793727SChandler Carruth Function *Fn = CI->getCalledFunction(); 121*72793727SChandler Carruth if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect) 122*72793727SChandler Carruth return false; 123*72793727SChandler Carruth 124*72793727SChandler Carruth Value *ArgValue = CI->getArgOperand(0); 125*72793727SChandler Carruth ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1)); 126*72793727SChandler Carruth if (!ExpectedValue) 127*72793727SChandler Carruth return false; 128*72793727SChandler Carruth 129*72793727SChandler Carruth MDBuilder MDB(CI->getContext()); 130*72793727SChandler Carruth MDNode *Node; 131*72793727SChandler Carruth 132*72793727SChandler Carruth // If expect value is equal to 1 it means that we are more likely to take 133*72793727SChandler Carruth // branch 0, in other case more likely is branch 1. 134*72793727SChandler Carruth if (ExpectedValue->isOne()) 135*72793727SChandler Carruth Node = MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight); 136*72793727SChandler Carruth else 137*72793727SChandler Carruth Node = MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight); 138*72793727SChandler Carruth 139*72793727SChandler Carruth BI->setMetadata(LLVMContext::MD_prof, Node); 140*72793727SChandler Carruth 141*72793727SChandler Carruth if (CmpI) 142*72793727SChandler Carruth CmpI->setOperand(0, ArgValue); 143*72793727SChandler Carruth else 144*72793727SChandler Carruth BI->setCondition(ArgValue); 145*72793727SChandler Carruth return true; 146*72793727SChandler Carruth } 147*72793727SChandler Carruth 148*72793727SChandler Carruth 149*72793727SChandler Carruth bool LowerExpectIntrinsic::runOnFunction(Function &F) { 150*72793727SChandler Carruth for (Function::iterator I = F.begin(), E = F.end(); I != E;) { 151*72793727SChandler Carruth BasicBlock *BB = I++; 152*72793727SChandler Carruth 153*72793727SChandler Carruth // Create "block_weights" metadata. 154*72793727SChandler Carruth if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) { 155*72793727SChandler Carruth if (HandleIfExpect(BI)) 156*72793727SChandler Carruth IfHandled++; 157*72793727SChandler Carruth } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) { 158*72793727SChandler Carruth if (HandleSwitchExpect(SI)) 159*72793727SChandler Carruth IfHandled++; 160*72793727SChandler Carruth } 161*72793727SChandler Carruth 162*72793727SChandler Carruth // remove llvm.expect intrinsics. 163*72793727SChandler Carruth for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); 164*72793727SChandler Carruth BI != BE; ) { 165*72793727SChandler Carruth CallInst *CI = dyn_cast<CallInst>(BI++); 166*72793727SChandler Carruth if (!CI) 167*72793727SChandler Carruth continue; 168*72793727SChandler Carruth 169*72793727SChandler Carruth Function *Fn = CI->getCalledFunction(); 170*72793727SChandler Carruth if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) { 171*72793727SChandler Carruth Value *Exp = CI->getArgOperand(0); 172*72793727SChandler Carruth CI->replaceAllUsesWith(Exp); 173*72793727SChandler Carruth CI->eraseFromParent(); 174*72793727SChandler Carruth } 175*72793727SChandler Carruth } 176*72793727SChandler Carruth } 177*72793727SChandler Carruth 178*72793727SChandler Carruth return false; 179*72793727SChandler Carruth } 180*72793727SChandler Carruth 181*72793727SChandler Carruth 182*72793727SChandler Carruth char LowerExpectIntrinsic::ID = 0; 183*72793727SChandler Carruth INITIALIZE_PASS(LowerExpectIntrinsic, "lower-expect", "Lower 'expect' " 184*72793727SChandler Carruth "Intrinsics", false, false) 185*72793727SChandler Carruth 186*72793727SChandler Carruth FunctionPass *llvm::createLowerExpectIntrinsicPass() { 187*72793727SChandler Carruth return new LowerExpectIntrinsic(); 188*72793727SChandler Carruth } 189