blob: 2ace902a7a1b8f614ba5711842907d49a886b84b [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 Carruth43e590e2015-01-24 11:13:02 +000014#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
Chandler Carruth3f5e7b12015-01-24 10:47:13 +000015#include "llvm/ADT/SmallVector.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/ADT/Statistic.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000017#include "llvm/IR/BasicBlock.h"
18#include "llvm/IR/Constants.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/Instructions.h"
21#include "llvm/IR/Intrinsics.h"
22#include "llvm/IR/LLVMContext.h"
23#include "llvm/IR/MDBuilder.h"
24#include "llvm/IR/Metadata.h"
Jakub Staszak3f158fd2011-07-06 18:22:43 +000025#include "llvm/Pass.h"
Jakub Staszak3f158fd2011-07-06 18:22:43 +000026#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/Debug.h"
Chandler Carruth43e590e2015-01-24 11:13:02 +000028#include "llvm/Transforms/Scalar.h"
Jakub Staszak3f158fd2011-07-06 18:22:43 +000029
30using namespace llvm;
31
Chandler Carruth964daaa2014-04-22 02:55:47 +000032#define DEBUG_TYPE "lower-expect-intrinsic"
33
Chandler Carruth6eb60eb2015-01-24 10:57:25 +000034STATISTIC(ExpectIntrinsicsHandled,
35 "Number of 'expect' intrinsic instructions handled");
Jakub Staszak3f158fd2011-07-06 18:22:43 +000036
37static cl::opt<uint32_t>
38LikelyBranchWeight("likely-branch-weight", cl::Hidden, cl::init(64),
39 cl::desc("Weight of the branch likely to be taken (default = 64)"));
40static cl::opt<uint32_t>
41UnlikelyBranchWeight("unlikely-branch-weight", cl::Hidden, cl::init(4),
42 cl::desc("Weight of the branch unlikely to be taken (default = 4)"));
43
Chandler Carruth0012c772015-01-24 10:39:24 +000044static bool handleSwitchExpect(SwitchInst &SI) {
45 CallInst *CI = dyn_cast<CallInst>(SI.getCondition());
Jakub Staszak3f158fd2011-07-06 18:22:43 +000046 if (!CI)
47 return false;
48
49 Function *Fn = CI->getCalledFunction();
50 if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect)
51 return false;
52
53 Value *ArgValue = CI->getArgOperand(0);
54 ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1));
55 if (!ExpectedValue)
56 return false;
57
Chandler Carruth0012c772015-01-24 10:39:24 +000058 SwitchInst::CaseIt Case = SI.findCaseValue(ExpectedValue);
59 unsigned n = SI.getNumCases(); // +1 for default case.
Chandler Carruth3f5e7b12015-01-24 10:47:13 +000060 SmallVector<uint32_t, 16> Weights(n + 1, UnlikelyBranchWeight);
Jakub Staszak3f158fd2011-07-06 18:22:43 +000061
Chandler Carruth3f5e7b12015-01-24 10:47:13 +000062 if (Case == SI.case_default())
63 Weights[0] = LikelyBranchWeight;
64 else
65 Weights[Case.getCaseIndex() + 1] = LikelyBranchWeight;
Jakub Staszak3f158fd2011-07-06 18:22:43 +000066
Chandler Carruth0012c772015-01-24 10:39:24 +000067 SI.setMetadata(LLVMContext::MD_prof,
68 MDBuilder(CI->getContext()).createBranchWeights(Weights));
Jakub Staszak3f158fd2011-07-06 18:22:43 +000069
Chandler Carruth0012c772015-01-24 10:39:24 +000070 SI.setCondition(ArgValue);
Jakub Staszak3f158fd2011-07-06 18:22:43 +000071 return true;
72}
73
Chandler Carruth0012c772015-01-24 10:39:24 +000074static bool handleBranchExpect(BranchInst &BI) {
75 if (BI.isUnconditional())
Jakub Staszak3f158fd2011-07-06 18:22:43 +000076 return false;
77
78 // Handle non-optimized IR code like:
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +000079 // %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1)
Jakub Staszak3f158fd2011-07-06 18:22:43 +000080 // %tobool = icmp ne i64 %expval, 0
81 // br i1 %tobool, label %if.then, label %if.end
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +000082 //
83 // Or the following simpler case:
84 // %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1)
85 // br i1 %expval, label %if.then, label %if.end
86
87 CallInst *CI;
Jakub Staszak3f158fd2011-07-06 18:22:43 +000088
Chandler Carruth0012c772015-01-24 10:39:24 +000089 ICmpInst *CmpI = dyn_cast<ICmpInst>(BI.getCondition());
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +000090 if (!CmpI) {
Chandler Carruth0012c772015-01-24 10:39:24 +000091 CI = dyn_cast<CallInst>(BI.getCondition());
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +000092 } else {
93 if (CmpI->getPredicate() != CmpInst::ICMP_NE)
94 return false;
95 CI = dyn_cast<CallInst>(CmpI->getOperand(0));
96 }
Jakub Staszak3f158fd2011-07-06 18:22:43 +000097
Jakub Staszak3f158fd2011-07-06 18:22:43 +000098 if (!CI)
99 return false;
100
101 Function *Fn = CI->getCalledFunction();
102 if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect)
103 return false;
104
105 Value *ArgValue = CI->getArgOperand(0);
106 ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1));
107 if (!ExpectedValue)
108 return false;
109
Benjamin Kramer65e75662012-05-26 13:59:43 +0000110 MDBuilder MDB(CI->getContext());
111 MDNode *Node;
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000112
113 // If expect value is equal to 1 it means that we are more likely to take
114 // branch 0, in other case more likely is branch 1.
Benjamin Kramer65e75662012-05-26 13:59:43 +0000115 if (ExpectedValue->isOne())
116 Node = MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight);
117 else
118 Node = MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight);
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000119
Chandler Carruth0012c772015-01-24 10:39:24 +0000120 BI.setMetadata(LLVMContext::MD_prof, Node);
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000121
Duncan P. N. Exon Smith1ff08e32014-02-02 22:43:55 +0000122 if (CmpI)
123 CmpI->setOperand(0, ArgValue);
124 else
Chandler Carruth0012c772015-01-24 10:39:24 +0000125 BI.setCondition(ArgValue);
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000126 return true;
127}
128
Chandler Carruth43e590e2015-01-24 11:13:02 +0000129static bool lowerExpectIntrinsic(Function &F) {
Chandler Carruthc3bf5bd2015-01-24 11:12:57 +0000130 bool Changed = false;
131
Chandler Carruthd12741e2015-01-24 10:57:19 +0000132 for (BasicBlock &BB : F) {
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000133 // Create "block_weights" metadata.
Chandler Carruthd12741e2015-01-24 10:57:19 +0000134 if (BranchInst *BI = dyn_cast<BranchInst>(BB.getTerminator())) {
Chandler Carruth0012c772015-01-24 10:39:24 +0000135 if (handleBranchExpect(*BI))
Chandler Carruth6eb60eb2015-01-24 10:57:25 +0000136 ExpectIntrinsicsHandled++;
Chandler Carruthd12741e2015-01-24 10:57:19 +0000137 } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB.getTerminator())) {
Chandler Carruth0012c772015-01-24 10:39:24 +0000138 if (handleSwitchExpect(*SI))
Chandler Carruth6eb60eb2015-01-24 10:57:25 +0000139 ExpectIntrinsicsHandled++;
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000140 }
141
Sanjay Patel6b2765f2015-08-24 20:11:14 +0000142 // Remove llvm.expect intrinsics.
Chandler Carruthd12741e2015-01-24 10:57:19 +0000143 for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;) {
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000144 CallInst *CI = dyn_cast<CallInst>(BI++);
145 if (!CI)
146 continue;
147
148 Function *Fn = CI->getCalledFunction();
Jakub Staszaka11f7ec2011-07-06 23:50:16 +0000149 if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) {
150 Value *Exp = CI->getArgOperand(0);
151 CI->replaceAllUsesWith(Exp);
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000152 CI->eraseFromParent();
Chandler Carruthc3bf5bd2015-01-24 11:12:57 +0000153 Changed = true;
Jakub Staszaka11f7ec2011-07-06 23:50:16 +0000154 }
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000155 }
156 }
157
Chandler Carruthc3bf5bd2015-01-24 11:12:57 +0000158 return Changed;
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000159}
160
Chandler Carruth43e590e2015-01-24 11:13:02 +0000161PreservedAnalyses LowerExpectIntrinsicPass::run(Function &F) {
162 if (lowerExpectIntrinsic(F))
163 return PreservedAnalyses::none();
164
165 return PreservedAnalyses::all();
166}
167
168namespace {
169/// \brief Legacy pass for lowering expect intrinsics out of the IR.
170///
171/// When this pass is run over a function it uses expect intrinsics which feed
172/// branches and switches to provide branch weight metadata for those
173/// terminators. It then removes the expect intrinsics from the IR so the rest
174/// of the optimizer can ignore them.
175class LowerExpectIntrinsic : public FunctionPass {
176public:
177 static char ID;
178 LowerExpectIntrinsic() : FunctionPass(ID) {
179 initializeLowerExpectIntrinsicPass(*PassRegistry::getPassRegistry());
180 }
181
182 bool runOnFunction(Function &F) override { return lowerExpectIntrinsic(F); }
183};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000184}
Chandler Carruth43e590e2015-01-24 11:13:02 +0000185
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000186char LowerExpectIntrinsic::ID = 0;
Chandler Carruth0ea746b2015-01-24 10:30:14 +0000187INITIALIZE_PASS(LowerExpectIntrinsic, "lower-expect",
188 "Lower 'expect' Intrinsics", false, false)
Jakub Staszak3f158fd2011-07-06 18:22:43 +0000189
190FunctionPass *llvm::createLowerExpectIntrinsicPass() {
191 return new LowerExpectIntrinsic();
192}