1 | //===- bolt/Passes/RegAnalysis.h --------------------------------*- C++ -*-===// |
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 | #ifndef BOLT_PASSES_REGANALYSIS_H |
10 | #define BOLT_PASSES_REGANALYSIS_H |
11 | |
12 | #include "llvm/ADT/BitVector.h" |
13 | #include <cstdint> |
14 | #include <map> |
15 | |
16 | namespace llvm { |
17 | class MCInst; |
18 | |
19 | namespace bolt { |
20 | class BinaryContext; |
21 | class BinaryFunction; |
22 | class BinaryFunctionCallGraph; |
23 | |
24 | /// Determine the set of registers read or clobbered for each instruction |
25 | /// in a BinaryFunction. If the instruction is a call, this analysis rely on |
26 | /// a call graph traversal to accurately extract the set of registers touched |
27 | /// after the call returns. |
28 | class RegAnalysis { |
29 | public: |
30 | /// Compute the set of registers \p Func may read from during its execution. |
31 | BitVector getFunctionUsedRegsList(const BinaryFunction *Func); |
32 | |
33 | /// Compute the set of registers \p Func may write to during its execution, |
34 | /// starting at the point when it is called up until when it returns. Returns |
35 | /// a BitVector the size of the target number of registers, representing the |
36 | /// set of clobbered registers. |
37 | BitVector getFunctionClobberList(const BinaryFunction *Func); |
38 | |
39 | RegAnalysis(BinaryContext &BC, std::map<uint64_t, BinaryFunction> *BFs, |
40 | BinaryFunctionCallGraph *CG); |
41 | |
42 | /// Compute the set of registers \p Inst may read from, marking them in |
43 | /// \p RegSet. If GetClobbers is true, the set set the instr may write to. |
44 | /// Use the callgraph to fill out this info for calls. |
45 | void getInstUsedRegsList(const MCInst &Inst, BitVector &RegSet, |
46 | bool GetClobbers) const; |
47 | |
48 | /// Compute the set of registers \p Inst may write to, marking them in |
49 | /// \p KillSet. If this is a call, try to get the set of registers the call |
50 | /// target will write to. |
51 | void getInstClobberList(const MCInst &Inst, BitVector &KillSet) const; |
52 | |
53 | /// Return true iff Vec has a conservative estimation of used/clobbered regs, |
54 | /// expressing no specific knowledge of reg usage. |
55 | bool isConservative(BitVector &Vec) const; |
56 | |
57 | /// Set what to do when lacking information about a call |
58 | enum class ConservativeStrategy { CLOBBERS_ALL, CLOBBERS_ABI, CLOBBERS_NONE }; |
59 | void setConservativeStrategy(ConservativeStrategy S) { CS = S; } |
60 | |
61 | /// Print stats about the quality of our analysis |
62 | void printStats(); |
63 | |
64 | private: |
65 | BinaryContext &BC; |
66 | |
67 | /// Map functions to the set of registers they may overwrite starting at when |
68 | /// it is called until it returns to the caller. |
69 | std::map<const BinaryFunction *, BitVector> RegsKilledMap; |
70 | |
71 | /// Similar concept above but for registers that are read in that function. |
72 | std::map<const BinaryFunction *, BitVector> RegsGenMap; |
73 | |
74 | /// Analysis stats counters |
75 | uint64_t NumFunctionsAllClobber{0}; |
76 | uint64_t CountFunctionsAllClobber{0}; |
77 | uint64_t CountDenominator{0}; |
78 | |
79 | ConservativeStrategy CS; |
80 | |
81 | /// Helper function used to get the set of clobbered/used regs whenever |
82 | /// we know nothing about the function. |
83 | void beConservative(BitVector &Result) const; |
84 | }; |
85 | |
86 | } // namespace bolt |
87 | } // namespace llvm |
88 | |
89 | #endif |
90 | |