1 | //===- bolt/Passes/PLTCall.h - PLT call optimization ----------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements the PLTCall class, which replaces calls to PLT entries |
10 | // with indirect calls against GOT. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "bolt/Passes/PLTCall.h" |
15 | #include "llvm/Support/CommandLine.h" |
16 | |
17 | #define DEBUG_TYPE "bolt-plt" |
18 | |
19 | using namespace llvm; |
20 | |
21 | namespace opts { |
22 | |
23 | extern cl::OptionCategory BoltOptCategory; |
24 | |
25 | cl::opt<bolt::PLTCall::OptType> |
26 | PLT("plt" , |
27 | cl::desc("optimize PLT calls (requires linking with -znow)" ), |
28 | cl::init(Val: bolt::PLTCall::OT_NONE), |
29 | cl::values(clEnumValN(bolt::PLTCall::OT_NONE, |
30 | "none" , |
31 | "do not optimize PLT calls" ), |
32 | clEnumValN(bolt::PLTCall::OT_HOT, |
33 | "hot" , |
34 | "optimize executed (hot) PLT calls" ), |
35 | clEnumValN(bolt::PLTCall::OT_ALL, |
36 | "all" , |
37 | "optimize all PLT calls" )), |
38 | cl::ZeroOrMore, |
39 | cl::cat(BoltOptCategory)); |
40 | |
41 | } |
42 | |
43 | namespace llvm { |
44 | namespace bolt { |
45 | |
46 | Error PLTCall::runOnFunctions(BinaryContext &BC) { |
47 | if (opts::PLT == OT_NONE) |
48 | return Error::success(); |
49 | |
50 | uint64_t NumCallsOptimized = 0; |
51 | for (auto &It : BC.getBinaryFunctions()) { |
52 | BinaryFunction &Function = It.second; |
53 | if (!shouldOptimize(BF: Function)) |
54 | continue; |
55 | |
56 | if (opts::PLT == OT_HOT && |
57 | Function.getExecutionCount() == BinaryFunction::COUNT_NO_PROFILE) |
58 | continue; |
59 | |
60 | for (BinaryBasicBlock &BB : Function) { |
61 | if (opts::PLT == OT_HOT && !BB.getKnownExecutionCount()) |
62 | continue; |
63 | |
64 | for (MCInst &Instr : BB) { |
65 | if (!BC.MIB->isCall(Inst: Instr)) |
66 | continue; |
67 | const MCSymbol *CallSymbol = BC.MIB->getTargetSymbol(Inst: Instr); |
68 | if (!CallSymbol) |
69 | continue; |
70 | const BinaryFunction *CalleeBF = BC.getFunctionForSymbol(Symbol: CallSymbol); |
71 | if (!CalleeBF || !CalleeBF->isPLTFunction()) |
72 | continue; |
73 | BC.MIB->convertCallToIndirectCall(Inst&: Instr, TargetLocation: CalleeBF->getPLTSymbol(), |
74 | Ctx: BC.Ctx.get()); |
75 | BC.MIB->addAnnotation(Inst&: Instr, Name: "PLTCall" , Val: true); |
76 | ++NumCallsOptimized; |
77 | } |
78 | } |
79 | } |
80 | |
81 | if (NumCallsOptimized) { |
82 | BC.RequiresZNow = true; |
83 | BC.outs() << "BOLT-INFO: " << NumCallsOptimized |
84 | << " PLT calls in the binary were optimized.\n" ; |
85 | } |
86 | return Error::success(); |
87 | } |
88 | |
89 | } // namespace bolt |
90 | } // namespace llvm |
91 | |