xref: /llvm-project/bolt/lib/Passes/VeneerElimination.cpp (revision d5956fb8f999e60af8bede8b17b02ca3a7b7cf4f)
1 //===- bolt/Passes/VeneerElimination.cpp ----------------------------------===//
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 class implements a pass that removes linker-inserted veneers from the
10 // code and redirects veneer callers to call to veneers destinations
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "bolt/Passes/VeneerElimination.h"
15 #define DEBUG_TYPE "veneer-elim"
16 
17 using namespace llvm;
18 
19 namespace opts {
20 
21 extern cl::OptionCategory BoltOptCategory;
22 
23 static llvm::cl::opt<bool>
24     EliminateVeneers("elim-link-veneers",
25                      cl::desc("run veneer elimination pass"), cl::init(true),
26                      cl::Hidden, cl::cat(BoltOptCategory));
27 } // namespace opts
28 
29 namespace llvm {
30 namespace bolt {
31 
32 static bool isPossibleVeneer(const BinaryFunction &BF) {
33   return BF.isAArch64Veneer() || BF.getOneName().starts_with("__AArch64");
34 }
35 
36 Error VeneerElimination::runOnFunctions(BinaryContext &BC) {
37   if (!opts::EliminateVeneers || !BC.isAArch64())
38     return Error::success();
39 
40   std::unordered_map<const MCSymbol *, const MCSymbol *> VeneerDestinations;
41   uint64_t NumEliminatedVeneers = 0;
42   for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) {
43     if (!isPossibleVeneer(BF))
44       continue;
45 
46     if (BF.isIgnored())
47       continue;
48 
49     MCInst &FirstInstruction = *(BF.begin()->begin());
50     const MCSymbol *VeneerTargetSymbol = 0;
51     uint64_t TargetAddress;
52     if (BC.MIB->isTailCall(FirstInstruction)) {
53       VeneerTargetSymbol = BC.MIB->getTargetSymbol(FirstInstruction);
54     } else if (BC.MIB->matchAbsLongVeneer(BF, TargetAddress)) {
55       if (BinaryFunction *TargetBF =
56               BC.getBinaryFunctionAtAddress(TargetAddress))
57         VeneerTargetSymbol = TargetBF->getSymbol();
58     } else if (BC.MIB->hasAnnotation(FirstInstruction, "AArch64Veneer")) {
59       VeneerTargetSymbol = BC.MIB->getTargetSymbol(FirstInstruction, 1);
60     }
61 
62     if (!VeneerTargetSymbol)
63       continue;
64 
65     for (const MCSymbol *Symbol : BF.getSymbols())
66       VeneerDestinations[Symbol] = VeneerTargetSymbol;
67 
68     NumEliminatedVeneers++;
69     BF.setPseudo(true);
70   }
71 
72   BC.outs() << "BOLT-INFO: number of removed linker-inserted veneers: "
73             << NumEliminatedVeneers << '\n';
74 
75   // Handle veneers to veneers in case they occur
76   for (auto &Entry : VeneerDestinations) {
77     const MCSymbol *Src = Entry.first;
78     const MCSymbol *Dest = Entry.second;
79     while (VeneerDestinations.find(Dest) != VeneerDestinations.end())
80       Dest = VeneerDestinations[Dest];
81 
82     VeneerDestinations[Src] = Dest;
83   }
84 
85   uint64_t VeneerCallers = 0;
86   for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) {
87     for (BinaryBasicBlock &BB : BF) {
88       for (MCInst &Instr : BB) {
89         if (!BC.MIB->isCall(Instr) || BC.MIB->isIndirectCall(Instr))
90           continue;
91 
92         const MCSymbol *TargetSymbol = BC.MIB->getTargetSymbol(Instr, 0);
93         auto It = VeneerDestinations.find(TargetSymbol);
94         if (It == VeneerDestinations.end())
95           continue;
96 
97         VeneerCallers++;
98         BC.MIB->replaceBranchTarget(Instr, It->second, BC.Ctx.get());
99       }
100     }
101   }
102 
103   LLVM_DEBUG(
104       dbgs() << "BOLT-INFO: number of linker-inserted veneers call sites: "
105              << VeneerCallers << "\n");
106   (void)VeneerCallers;
107   return Error::success();
108 }
109 
110 } // namespace bolt
111 } // namespace llvm
112