LLVM API Documentation

LowerExpectIntrinsic.cpp
Go to the documentation of this file.
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 }