blob: 2a11f9a4f5433c63707d6f7a83985379b4ccb2a9 [file] [log] [blame]
Chandler Carruth47e1db12011-10-16 22:15:07 +00001//===- LowerExpectIntrinsic.cpp - Lower expect intrinsic ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This pass lowers the 'expect' intrinsic to LLVM metadata.
11//
12//===----------------------------------------------------------------------===//
13
Chandler Carruthed0881b2012-12-03 16:50:05 +000014#include "llvm/Transforms/Scalar.h"
15#include "llvm/ADT/Statistic.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000016#include "llvm/IR/BasicBlock.h"
17#include "llvm/IR/Constants.h"
18#include "llvm/IR/Function.h"
19#include "llvm/IR/Instructions.h"
20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/LLVMContext.h"
22#include "llvm/IR/MDBuilder.h"
23#include "llvm/IR/Metadata.h"
Jakub Staszak3f158fd2011-07-06 18:22:43 +000024#include "llvm/Pass.h"
Jakub Staszak3f158fd2011-07-06 18:22:43 +000025#include "llvm/Support/CommandLine.h"
26#include "llvm/Support/Debug.h"
Jakub Staszak3f158fd2011-07-06 18:22:43 +000027#include <vector>
28
29using namespace llvm;
30
Chandler Carruth964daaa2014-04-22 02:55:47 +000031#define DEBUG_TYPE "lower-expect-intrinsic"
32
Robert Wilhelmf0cfb832013-09-28 11:46:15 +000033STATISTIC(IfHandled, "Number of 'expect' intrinsic instructions handled");
Jakub Staszak3f158fd2011-07-06 18:22:43 +000034
35static cl::opt<uint32_t>
36LikelyBranchWeight("likely-branch-weight", cl::Hidden, cl::init(64),
37 cl::desc("Weight of the branch likely to be taken (default = 64)"));
38static cl::opt<uint32_t>
39UnlikelyBranchWeight("unlikely-branch-weight", cl::Hidden, cl::init(4),
40 cl::desc("Weight of the branch unlikely to be taken (default = 4)"));
41
42namespace {
Chandler Carruth579c5c42015-01-24 10:32:53 +000043/// \brief Legacy pass for lowering expect intrinsics out of the IR.
44///
45/// When this pass is run over a function it uses expect intrinsics which feed
46/// branches and switches to provide branch weight metadata for those
47/// terminators. It then removes the expect intrinsics from the IR so the rest
48/// of the optimizer can ignore them.
Chandler Carruth0ea746b2015-01-24 10:30:14 +000049class LowerExpectIntrinsic : public FunctionPass {
Jakub Staszak3f158fd2011-07-06 18:22:43 +000050
Chandler Carruth0ea746b2015-01-24 10:30:14 +000051 bool HandleSwitchExpect(SwitchInst *SI);
Jakub Staszak3f158fd2011-07-06 18:22:43 +000052
Chandler Carruth0ea746b2015-01-24 10:30:14 +000053 bool HandleIfExpect(BranchInst *BI);
Jakub Staszak3f158fd2011-07-06 18:22:43 +000054
Chandler Carruth0ea746b2015-01-24 10:30:14 +000055public:
56 static char ID;
57 LowerExpectIntrinsic() : FunctionPass(ID) {
58 initializeLowerExpectIntrinsicPass(*PassRegistry::getPassRegistry());
59 }
Jakub Staszak3f158fd2011-07-06 18:22:43 +000060
Chandler Carruth0ea746b2015-01-24 10:30:14 +000061 bool runOnFunction(Function &F) override;
62};
Jakub Staszak3f158fd2011-07-06 18:22:43 +000063}
64
Jakub Staszak3f158fd2011-07-06 18:22:43 +000065bool LowerExpectIntrinsic::HandleSwitchExpect(SwitchInst *SI) {
66 CallInst *CI = dyn_cast<CallInst>(SI->getCondition());
67 if (!CI)
68 return false;
69
70 Function *Fn = CI->getCalledFunction();
71 if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect)
72 return false;
73
74 Value *ArgValue = CI->getArgOperand(0);
75 ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1));
76 if (!ExpectedValue)
77 return false;
78
Stepan Dyatkovskiy5b648af2012-03-08 07:06:20 +000079 SwitchInst::CaseIt Case = SI->findCaseValue(ExpectedValue);
Benjamin Kramer65e75662012-05-26 13:59:43 +000080 unsigned n = SI->getNumCases(); // +1 for default case.
81 std::vector<uint32_t> Weights(n + 1);
Jakub Staszak3f158fd2011-07-06 18:22:43 +000082
Chandler Carruth0ea746b2015-01-24 10:30:14 +000083 Weights[0] =
84 Case == SI->case_default() ? LikelyBranchWeight : UnlikelyBranchWeight;
Benjamin Kramer65e75662012-05-26 13:59:43 +000085 for (unsigned i = 0; i != n; ++i)
Chandler Carruth0ea746b2015-01-24 10:30:14 +000086 Weights[i + 1] =
87 i == Case.getCaseIndex() ? LikelyBranchWeight : UnlikelyBranchWeight;
Jakub Staszak3f158fd2011-07-06 18:22:43 +000088
Benjamin Kramer65e75662012-05-26 13:59:43 +000089 SI->setMetadata(LLVMContext::MD_prof,
90 MDBuilder(CI->getContext()).createBranchWeights(Weights));
Jakub Staszak3f158fd2011-07-06 18:22:43 +000091
92 SI->setCondition(ArgValue);
93 return true;
94}
95
Jakub Staszak3f158fd2011-07-06 18:22:43 +000096bool LowerExpectIntrinsic::HandleIfExpect(BranchInst *BI) {
97 if (BI->isUnconditional())
98 return false;
99
100 // Handle non-optimized IR code like:
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +0000101 // %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1)
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000102 // %tobool = icmp ne i64 %expval, 0
103 // br i1 %tobool, label %if.then, label %if.end
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +0000104 //
105 // Or the following simpler case:
106 // %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1)
107 // br i1 %expval, label %if.then, label %if.end
108
109 CallInst *CI;
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000110
111 ICmpInst *CmpI = dyn_cast<ICmpInst>(BI->getCondition());
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +0000112 if (!CmpI) {
113 CI = dyn_cast<CallInst>(BI->getCondition());
114 } else {
115 if (CmpI->getPredicate() != CmpInst::ICMP_NE)
116 return false;
117 CI = dyn_cast<CallInst>(CmpI->getOperand(0));
118 }
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000119
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000120 if (!CI)
121 return false;
122
123 Function *Fn = CI->getCalledFunction();
124 if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect)
125 return false;
126
127 Value *ArgValue = CI->getArgOperand(0);
128 ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1));
129 if (!ExpectedValue)
130 return false;
131
Benjamin Kramer65e75662012-05-26 13:59:43 +0000132 MDBuilder MDB(CI->getContext());
133 MDNode *Node;
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000134
135 // If expect value is equal to 1 it means that we are more likely to take
136 // branch 0, in other case more likely is branch 1.
Benjamin Kramer65e75662012-05-26 13:59:43 +0000137 if (ExpectedValue->isOne())
138 Node = MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight);
139 else
140 Node = MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight);
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000141
Benjamin Kramer65e75662012-05-26 13:59:43 +0000142 BI->setMetadata(LLVMContext::MD_prof, Node);
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000143
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +0000144 if (CmpI)
145 CmpI->setOperand(0, ArgValue);
146 else
147 BI->setCondition(ArgValue);
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000148 return true;
149}
150
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000151bool LowerExpectIntrinsic::runOnFunction(Function &F) {
152 for (Function::iterator I = F.begin(), E = F.end(); I != E;) {
153 BasicBlock *BB = I++;
154
155 // Create "block_weights" metadata.
156 if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) {
157 if (HandleIfExpect(BI))
158 IfHandled++;
159 } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
160 if (HandleSwitchExpect(SI))
161 IfHandled++;
162 }
163
164 // remove llvm.expect intrinsics.
Chandler Carruth0ea746b2015-01-24 10:30:14 +0000165 for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000166 CallInst *CI = dyn_cast<CallInst>(BI++);
167 if (!CI)
168 continue;
169
170 Function *Fn = CI->getCalledFunction();
Jakub Staszaka11f7ec2011-07-06 23:50:16 +0000171 if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) {
172 Value *Exp = CI->getArgOperand(0);
173 CI->replaceAllUsesWith(Exp);
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000174 CI->eraseFromParent();
Jakub Staszaka11f7ec2011-07-06 23:50:16 +0000175 }
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000176 }
177 }
178
179 return false;
180}
181
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000182char LowerExpectIntrinsic::ID = 0;
Chandler Carruth0ea746b2015-01-24 10:30:14 +0000183INITIALIZE_PASS(LowerExpectIntrinsic, "lower-expect",
184 "Lower 'expect' Intrinsics", false, false)
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000185
186FunctionPass *llvm::createLowerExpectIntrinsicPass() {
187 return new LowerExpectIntrinsic();
188}