xref: /aosp_15_r20/external/llvm/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- LowerExpectIntrinsic.cpp - Lower expect intrinsic ------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This pass lowers the 'expect' intrinsic to LLVM metadata.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/BasicBlock.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/MDBuilder.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Metadata.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar.h"
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker using namespace llvm;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "lower-expect-intrinsic"
33*9880d681SAndroid Build Coastguard Worker 
34*9880d681SAndroid Build Coastguard Worker STATISTIC(ExpectIntrinsicsHandled,
35*9880d681SAndroid Build Coastguard Worker           "Number of 'expect' intrinsic instructions handled");
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker // These default values are chosen to represent an extremely skewed outcome for
38*9880d681SAndroid Build Coastguard Worker // a condition, but they leave some room for interpretation by later passes.
39*9880d681SAndroid Build Coastguard Worker //
40*9880d681SAndroid Build Coastguard Worker // If the documentation for __builtin_expect() was made explicit that it should
41*9880d681SAndroid Build Coastguard Worker // only be used in extreme cases, we could make this ratio higher. As it stands,
42*9880d681SAndroid Build Coastguard Worker // programmers may be using __builtin_expect() / llvm.expect to annotate that a
43*9880d681SAndroid Build Coastguard Worker // branch is likely or unlikely to be taken.
44*9880d681SAndroid Build Coastguard Worker //
45*9880d681SAndroid Build Coastguard Worker // There is a known dependency on this ratio in CodeGenPrepare when transforming
46*9880d681SAndroid Build Coastguard Worker // 'select' instructions. It may be worthwhile to hoist these values to some
47*9880d681SAndroid Build Coastguard Worker // shared space, so they can be used directly by other passes.
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker static cl::opt<uint32_t> LikelyBranchWeight(
50*9880d681SAndroid Build Coastguard Worker     "likely-branch-weight", cl::Hidden, cl::init(2000),
51*9880d681SAndroid Build Coastguard Worker     cl::desc("Weight of the branch likely to be taken (default = 2000)"));
52*9880d681SAndroid Build Coastguard Worker static cl::opt<uint32_t> UnlikelyBranchWeight(
53*9880d681SAndroid Build Coastguard Worker     "unlikely-branch-weight", cl::Hidden, cl::init(1),
54*9880d681SAndroid Build Coastguard Worker     cl::desc("Weight of the branch unlikely to be taken (default = 1)"));
55*9880d681SAndroid Build Coastguard Worker 
handleSwitchExpect(SwitchInst & SI)56*9880d681SAndroid Build Coastguard Worker static bool handleSwitchExpect(SwitchInst &SI) {
57*9880d681SAndroid Build Coastguard Worker   CallInst *CI = dyn_cast<CallInst>(SI.getCondition());
58*9880d681SAndroid Build Coastguard Worker   if (!CI)
59*9880d681SAndroid Build Coastguard Worker     return false;
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker   Function *Fn = CI->getCalledFunction();
62*9880d681SAndroid Build Coastguard Worker   if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect)
63*9880d681SAndroid Build Coastguard Worker     return false;
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   Value *ArgValue = CI->getArgOperand(0);
66*9880d681SAndroid Build Coastguard Worker   ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1));
67*9880d681SAndroid Build Coastguard Worker   if (!ExpectedValue)
68*9880d681SAndroid Build Coastguard Worker     return false;
69*9880d681SAndroid Build Coastguard Worker 
70*9880d681SAndroid Build Coastguard Worker   SwitchInst::CaseIt Case = SI.findCaseValue(ExpectedValue);
71*9880d681SAndroid Build Coastguard Worker   unsigned n = SI.getNumCases(); // +1 for default case.
72*9880d681SAndroid Build Coastguard Worker   SmallVector<uint32_t, 16> Weights(n + 1, UnlikelyBranchWeight);
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker   if (Case == SI.case_default())
75*9880d681SAndroid Build Coastguard Worker     Weights[0] = LikelyBranchWeight;
76*9880d681SAndroid Build Coastguard Worker   else
77*9880d681SAndroid Build Coastguard Worker     Weights[Case.getCaseIndex() + 1] = LikelyBranchWeight;
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker   SI.setMetadata(LLVMContext::MD_prof,
80*9880d681SAndroid Build Coastguard Worker                  MDBuilder(CI->getContext()).createBranchWeights(Weights));
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker   SI.setCondition(ArgValue);
83*9880d681SAndroid Build Coastguard Worker   return true;
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker 
handleBranchExpect(BranchInst & BI)86*9880d681SAndroid Build Coastguard Worker static bool handleBranchExpect(BranchInst &BI) {
87*9880d681SAndroid Build Coastguard Worker   if (BI.isUnconditional())
88*9880d681SAndroid Build Coastguard Worker     return false;
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker   // Handle non-optimized IR code like:
91*9880d681SAndroid Build Coastguard Worker   //   %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1)
92*9880d681SAndroid Build Coastguard Worker   //   %tobool = icmp ne i64 %expval, 0
93*9880d681SAndroid Build Coastguard Worker   //   br i1 %tobool, label %if.then, label %if.end
94*9880d681SAndroid Build Coastguard Worker   //
95*9880d681SAndroid Build Coastguard Worker   // Or the following simpler case:
96*9880d681SAndroid Build Coastguard Worker   //   %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1)
97*9880d681SAndroid Build Coastguard Worker   //   br i1 %expval, label %if.then, label %if.end
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker   CallInst *CI;
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker   ICmpInst *CmpI = dyn_cast<ICmpInst>(BI.getCondition());
102*9880d681SAndroid Build Coastguard Worker   if (!CmpI) {
103*9880d681SAndroid Build Coastguard Worker     CI = dyn_cast<CallInst>(BI.getCondition());
104*9880d681SAndroid Build Coastguard Worker   } else {
105*9880d681SAndroid Build Coastguard Worker     if (CmpI->getPredicate() != CmpInst::ICMP_NE)
106*9880d681SAndroid Build Coastguard Worker       return false;
107*9880d681SAndroid Build Coastguard Worker     CI = dyn_cast<CallInst>(CmpI->getOperand(0));
108*9880d681SAndroid Build Coastguard Worker   }
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker   if (!CI)
111*9880d681SAndroid Build Coastguard Worker     return false;
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker   Function *Fn = CI->getCalledFunction();
114*9880d681SAndroid Build Coastguard Worker   if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect)
115*9880d681SAndroid Build Coastguard Worker     return false;
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker   Value *ArgValue = CI->getArgOperand(0);
118*9880d681SAndroid Build Coastguard Worker   ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1));
119*9880d681SAndroid Build Coastguard Worker   if (!ExpectedValue)
120*9880d681SAndroid Build Coastguard Worker     return false;
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker   MDBuilder MDB(CI->getContext());
123*9880d681SAndroid Build Coastguard Worker   MDNode *Node;
124*9880d681SAndroid Build Coastguard Worker 
125*9880d681SAndroid Build Coastguard Worker   // If expect value is equal to 1 it means that we are more likely to take
126*9880d681SAndroid Build Coastguard Worker   // branch 0, in other case more likely is branch 1.
127*9880d681SAndroid Build Coastguard Worker   if (ExpectedValue->isOne())
128*9880d681SAndroid Build Coastguard Worker     Node = MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight);
129*9880d681SAndroid Build Coastguard Worker   else
130*9880d681SAndroid Build Coastguard Worker     Node = MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight);
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker   BI.setMetadata(LLVMContext::MD_prof, Node);
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker   if (CmpI)
135*9880d681SAndroid Build Coastguard Worker     CmpI->setOperand(0, ArgValue);
136*9880d681SAndroid Build Coastguard Worker   else
137*9880d681SAndroid Build Coastguard Worker     BI.setCondition(ArgValue);
138*9880d681SAndroid Build Coastguard Worker   return true;
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker 
lowerExpectIntrinsic(Function & F)141*9880d681SAndroid Build Coastguard Worker static bool lowerExpectIntrinsic(Function &F) {
142*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker   for (BasicBlock &BB : F) {
145*9880d681SAndroid Build Coastguard Worker     // Create "block_weights" metadata.
146*9880d681SAndroid Build Coastguard Worker     if (BranchInst *BI = dyn_cast<BranchInst>(BB.getTerminator())) {
147*9880d681SAndroid Build Coastguard Worker       if (handleBranchExpect(*BI))
148*9880d681SAndroid Build Coastguard Worker         ExpectIntrinsicsHandled++;
149*9880d681SAndroid Build Coastguard Worker     } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB.getTerminator())) {
150*9880d681SAndroid Build Coastguard Worker       if (handleSwitchExpect(*SI))
151*9880d681SAndroid Build Coastguard Worker         ExpectIntrinsicsHandled++;
152*9880d681SAndroid Build Coastguard Worker     }
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker     // Remove llvm.expect intrinsics.
155*9880d681SAndroid Build Coastguard Worker     for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;) {
156*9880d681SAndroid Build Coastguard Worker       CallInst *CI = dyn_cast<CallInst>(BI++);
157*9880d681SAndroid Build Coastguard Worker       if (!CI)
158*9880d681SAndroid Build Coastguard Worker         continue;
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker       Function *Fn = CI->getCalledFunction();
161*9880d681SAndroid Build Coastguard Worker       if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) {
162*9880d681SAndroid Build Coastguard Worker         Value *Exp = CI->getArgOperand(0);
163*9880d681SAndroid Build Coastguard Worker         CI->replaceAllUsesWith(Exp);
164*9880d681SAndroid Build Coastguard Worker         CI->eraseFromParent();
165*9880d681SAndroid Build Coastguard Worker         Changed = true;
166*9880d681SAndroid Build Coastguard Worker       }
167*9880d681SAndroid Build Coastguard Worker     }
168*9880d681SAndroid Build Coastguard Worker   }
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker   return Changed;
171*9880d681SAndroid Build Coastguard Worker }
172*9880d681SAndroid Build Coastguard Worker 
run(Function & F,FunctionAnalysisManager &)173*9880d681SAndroid Build Coastguard Worker PreservedAnalyses LowerExpectIntrinsicPass::run(Function &F,
174*9880d681SAndroid Build Coastguard Worker                                                 FunctionAnalysisManager &) {
175*9880d681SAndroid Build Coastguard Worker   if (lowerExpectIntrinsic(F))
176*9880d681SAndroid Build Coastguard Worker     return PreservedAnalyses::none();
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker   return PreservedAnalyses::all();
179*9880d681SAndroid Build Coastguard Worker }
180*9880d681SAndroid Build Coastguard Worker 
181*9880d681SAndroid Build Coastguard Worker namespace {
182*9880d681SAndroid Build Coastguard Worker /// \brief Legacy pass for lowering expect intrinsics out of the IR.
183*9880d681SAndroid Build Coastguard Worker ///
184*9880d681SAndroid Build Coastguard Worker /// When this pass is run over a function it uses expect intrinsics which feed
185*9880d681SAndroid Build Coastguard Worker /// branches and switches to provide branch weight metadata for those
186*9880d681SAndroid Build Coastguard Worker /// terminators. It then removes the expect intrinsics from the IR so the rest
187*9880d681SAndroid Build Coastguard Worker /// of the optimizer can ignore them.
188*9880d681SAndroid Build Coastguard Worker class LowerExpectIntrinsic : public FunctionPass {
189*9880d681SAndroid Build Coastguard Worker public:
190*9880d681SAndroid Build Coastguard Worker   static char ID;
LowerExpectIntrinsic()191*9880d681SAndroid Build Coastguard Worker   LowerExpectIntrinsic() : FunctionPass(ID) {
192*9880d681SAndroid Build Coastguard Worker     initializeLowerExpectIntrinsicPass(*PassRegistry::getPassRegistry());
193*9880d681SAndroid Build Coastguard Worker   }
194*9880d681SAndroid Build Coastguard Worker 
runOnFunction(Function & F)195*9880d681SAndroid Build Coastguard Worker   bool runOnFunction(Function &F) override { return lowerExpectIntrinsic(F); }
196*9880d681SAndroid Build Coastguard Worker };
197*9880d681SAndroid Build Coastguard Worker }
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker char LowerExpectIntrinsic::ID = 0;
200*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(LowerExpectIntrinsic, "lower-expect",
201*9880d681SAndroid Build Coastguard Worker                 "Lower 'expect' Intrinsics", false, false)
202*9880d681SAndroid Build Coastguard Worker 
createLowerExpectIntrinsicPass()203*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createLowerExpectIntrinsicPass() {
204*9880d681SAndroid Build Coastguard Worker   return new LowerExpectIntrinsic();
205*9880d681SAndroid Build Coastguard Worker }
206