LLVM API Documentation
00001 //===- LowerExpectIntrinsic.cpp - Lower expect intrinsic ------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This pass lowers the 'expect' intrinsic to LLVM metadata. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/Transforms/Scalar.h" 00015 #include "llvm/ADT/Statistic.h" 00016 #include "llvm/IR/BasicBlock.h" 00017 #include "llvm/IR/Constants.h" 00018 #include "llvm/IR/Function.h" 00019 #include "llvm/IR/Instructions.h" 00020 #include "llvm/IR/Intrinsics.h" 00021 #include "llvm/IR/LLVMContext.h" 00022 #include "llvm/IR/MDBuilder.h" 00023 #include "llvm/IR/Metadata.h" 00024 #include "llvm/Pass.h" 00025 #include "llvm/Support/CommandLine.h" 00026 #include "llvm/Support/Debug.h" 00027 #include <vector> 00028 00029 using namespace llvm; 00030 00031 #define DEBUG_TYPE "lower-expect-intrinsic" 00032 00033 STATISTIC(IfHandled, "Number of 'expect' intrinsic instructions handled"); 00034 00035 static cl::opt<uint32_t> 00036 LikelyBranchWeight("likely-branch-weight", cl::Hidden, cl::init(64), 00037 cl::desc("Weight of the branch likely to be taken (default = 64)")); 00038 static cl::opt<uint32_t> 00039 UnlikelyBranchWeight("unlikely-branch-weight", cl::Hidden, cl::init(4), 00040 cl::desc("Weight of the branch unlikely to be taken (default = 4)")); 00041 00042 namespace { 00043 00044 class LowerExpectIntrinsic : public FunctionPass { 00045 00046 bool HandleSwitchExpect(SwitchInst *SI); 00047 00048 bool HandleIfExpect(BranchInst *BI); 00049 00050 public: 00051 static char ID; 00052 LowerExpectIntrinsic() : FunctionPass(ID) { 00053 initializeLowerExpectIntrinsicPass(*PassRegistry::getPassRegistry()); 00054 } 00055 00056 bool runOnFunction(Function &F) override; 00057 }; 00058 } 00059 00060 00061 bool LowerExpectIntrinsic::HandleSwitchExpect(SwitchInst *SI) { 00062 CallInst *CI = dyn_cast<CallInst>(SI->getCondition()); 00063 if (!CI) 00064 return false; 00065 00066 Function *Fn = CI->getCalledFunction(); 00067 if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect) 00068 return false; 00069 00070 Value *ArgValue = CI->getArgOperand(0); 00071 ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1)); 00072 if (!ExpectedValue) 00073 return false; 00074 00075 SwitchInst::CaseIt Case = SI->findCaseValue(ExpectedValue); 00076 unsigned n = SI->getNumCases(); // +1 for default case. 00077 std::vector<uint32_t> Weights(n + 1); 00078 00079 Weights[0] = Case == SI->case_default() ? LikelyBranchWeight 00080 : UnlikelyBranchWeight; 00081 for (unsigned i = 0; i != n; ++i) 00082 Weights[i + 1] = i == Case.getCaseIndex() ? LikelyBranchWeight 00083 : UnlikelyBranchWeight; 00084 00085 SI->setMetadata(LLVMContext::MD_prof, 00086 MDBuilder(CI->getContext()).createBranchWeights(Weights)); 00087 00088 SI->setCondition(ArgValue); 00089 return true; 00090 } 00091 00092 00093 bool LowerExpectIntrinsic::HandleIfExpect(BranchInst *BI) { 00094 if (BI->isUnconditional()) 00095 return false; 00096 00097 // Handle non-optimized IR code like: 00098 // %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1) 00099 // %tobool = icmp ne i64 %expval, 0 00100 // br i1 %tobool, label %if.then, label %if.end 00101 // 00102 // Or the following simpler case: 00103 // %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1) 00104 // br i1 %expval, label %if.then, label %if.end 00105 00106 CallInst *CI; 00107 00108 ICmpInst *CmpI = dyn_cast<ICmpInst>(BI->getCondition()); 00109 if (!CmpI) { 00110 CI = dyn_cast<CallInst>(BI->getCondition()); 00111 } else { 00112 if (CmpI->getPredicate() != CmpInst::ICMP_NE) 00113 return false; 00114 CI = dyn_cast<CallInst>(CmpI->getOperand(0)); 00115 } 00116 00117 if (!CI) 00118 return false; 00119 00120 Function *Fn = CI->getCalledFunction(); 00121 if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect) 00122 return false; 00123 00124 Value *ArgValue = CI->getArgOperand(0); 00125 ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1)); 00126 if (!ExpectedValue) 00127 return false; 00128 00129 MDBuilder MDB(CI->getContext()); 00130 MDNode *Node; 00131 00132 // If expect value is equal to 1 it means that we are more likely to take 00133 // branch 0, in other case more likely is branch 1. 00134 if (ExpectedValue->isOne()) 00135 Node = MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight); 00136 else 00137 Node = MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight); 00138 00139 BI->setMetadata(LLVMContext::MD_prof, Node); 00140 00141 if (CmpI) 00142 CmpI->setOperand(0, ArgValue); 00143 else 00144 BI->setCondition(ArgValue); 00145 return true; 00146 } 00147 00148 00149 bool LowerExpectIntrinsic::runOnFunction(Function &F) { 00150 for (Function::iterator I = F.begin(), E = F.end(); I != E;) { 00151 BasicBlock *BB = I++; 00152 00153 // Create "block_weights" metadata. 00154 if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) { 00155 if (HandleIfExpect(BI)) 00156 IfHandled++; 00157 } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) { 00158 if (HandleSwitchExpect(SI)) 00159 IfHandled++; 00160 } 00161 00162 // remove llvm.expect intrinsics. 00163 for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); 00164 BI != BE; ) { 00165 CallInst *CI = dyn_cast<CallInst>(BI++); 00166 if (!CI) 00167 continue; 00168 00169 Function *Fn = CI->getCalledFunction(); 00170 if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) { 00171 Value *Exp = CI->getArgOperand(0); 00172 CI->replaceAllUsesWith(Exp); 00173 CI->eraseFromParent(); 00174 } 00175 } 00176 } 00177 00178 return false; 00179 } 00180 00181 00182 char LowerExpectIntrinsic::ID = 0; 00183 INITIALIZE_PASS(LowerExpectIntrinsic, "lower-expect", "Lower 'expect' " 00184 "Intrinsics", false, false) 00185 00186 FunctionPass *llvm::createLowerExpectIntrinsicPass() { 00187 return new LowerExpectIntrinsic(); 00188 }