| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1 | //===---- MachineOutliner.cpp - Outline instructions -----------*- C++ -*-===// | 
|  | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 | /// | 
|  | 9 | /// \file | 
|  | 10 | /// Replaces repeated sequences of instructions with function calls. | 
|  | 11 | /// | 
|  | 12 | /// This works by placing every instruction from every basic block in a | 
|  | 13 | /// suffix tree, and repeatedly querying that tree for repeated sequences of | 
|  | 14 | /// instructions. If a sequence of instructions appears often, then it ought | 
|  | 15 | /// to be beneficial to pull out into a function. | 
|  | 16 | /// | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 17 | /// The MachineOutliner communicates with a given target using hooks defined in | 
|  | 18 | /// TargetInstrInfo.h. The target supplies the outliner with information on how | 
|  | 19 | /// a specific sequence of instructions should be outlined. This information | 
|  | 20 | /// is used to deduce the number of instructions necessary to | 
|  | 21 | /// | 
|  | 22 | /// * Create an outlined function | 
|  | 23 | /// * Call that outlined function | 
|  | 24 | /// | 
|  | 25 | /// Targets must implement | 
|  | 26 | ///   * getOutliningCandidateInfo | 
| Jessica Paquette | 32de26d | 2018-06-19 21:14:48 +0000 | [diff] [blame] | 27 | ///   * buildOutlinedFrame | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 28 | ///   * insertOutlinedCall | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 29 | ///   * isFunctionSafeToOutlineFrom | 
|  | 30 | /// | 
|  | 31 | /// in order to make use of the MachineOutliner. | 
|  | 32 | /// | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 33 | /// This was originally presented at the 2016 LLVM Developers' Meeting in the | 
|  | 34 | /// talk "Reducing Code Size Using Outlining". For a high-level overview of | 
|  | 35 | /// how this pass works, the talk is available on YouTube at | 
|  | 36 | /// | 
|  | 37 | /// https://www.youtube.com/watch?v=yorld-WSOeU | 
|  | 38 | /// | 
|  | 39 | /// The slides for the talk are available at | 
|  | 40 | /// | 
|  | 41 | /// http://www.llvm.org/devmtg/2016-11/Slides/Paquette-Outliner.pdf | 
|  | 42 | /// | 
|  | 43 | /// The talk provides an overview of how the outliner finds candidates and | 
|  | 44 | /// ultimately outlines them. It describes how the main data structure for this | 
|  | 45 | /// pass, the suffix tree, is queried and purged for candidates. It also gives | 
|  | 46 | /// a simplified suffix tree construction algorithm for suffix trees based off | 
|  | 47 | /// of the algorithm actually used here, Ukkonen's algorithm. | 
|  | 48 | /// | 
|  | 49 | /// For the original RFC for this pass, please see | 
|  | 50 | /// | 
|  | 51 | /// http://lists.llvm.org/pipermail/llvm-dev/2016-August/104170.html | 
|  | 52 | /// | 
|  | 53 | /// For more information on the suffix tree data structure, please see | 
|  | 54 | /// https://www.cs.helsinki.fi/u/ukkonen/SuffixT1withFigs.pdf | 
|  | 55 | /// | 
|  | 56 | //===----------------------------------------------------------------------===// | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 57 | #include "llvm/CodeGen/MachineOutliner.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 58 | #include "llvm/ADT/DenseMap.h" | 
| Jin Lin | fc6fda9 | 2020-03-05 13:54:58 -0800 | [diff] [blame] | 59 | #include "llvm/ADT/SmallSet.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 60 | #include "llvm/ADT/Statistic.h" | 
|  | 61 | #include "llvm/ADT/Twine.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 62 | #include "llvm/CodeGen/MachineFunction.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 63 | #include "llvm/CodeGen/MachineModuleInfo.h" | 
| Jessica Paquette | ffe4abc | 2017-08-31 21:02:45 +0000 | [diff] [blame] | 64 | #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" | 
| Geoff Berry | 82203c4 | 2018-01-31 20:15:16 +0000 | [diff] [blame] | 65 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 66 | #include "llvm/CodeGen/Passes.h" | 
| David Blaikie | 3f833ed | 2017-11-08 01:01:31 +0000 | [diff] [blame] | 67 | #include "llvm/CodeGen/TargetInstrInfo.h" | 
| David Blaikie | b3bde2e | 2017-11-17 01:07:10 +0000 | [diff] [blame] | 68 | #include "llvm/CodeGen/TargetSubtargetInfo.h" | 
| Jessica Paquette | 729e686 | 2018-01-18 00:00:58 +0000 | [diff] [blame] | 69 | #include "llvm/IR/DIBuilder.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 70 | #include "llvm/IR/IRBuilder.h" | 
| Jessica Paquette | a499c3c | 2018-01-19 21:21:49 +0000 | [diff] [blame] | 71 | #include "llvm/IR/Mangler.h" | 
| Reid Kleckner | 05da2fe | 2019-11-13 13:15:01 -0800 | [diff] [blame] | 72 | #include "llvm/InitializePasses.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 73 | #include "llvm/Support/Allocator.h" | 
| Jessica Paquette | 1eca23b | 2018-04-19 22:17:07 +0000 | [diff] [blame] | 74 | #include "llvm/Support/CommandLine.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 75 | #include "llvm/Support/Debug.h" | 
|  | 76 | #include "llvm/Support/raw_ostream.h" | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 77 | #include <functional> | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 78 | #include <tuple> | 
|  | 79 | #include <vector> | 
|  | 80 |  | 
|  | 81 | #define DEBUG_TYPE "machine-outliner" | 
|  | 82 |  | 
|  | 83 | using namespace llvm; | 
| Jessica Paquette | ffe4abc | 2017-08-31 21:02:45 +0000 | [diff] [blame] | 84 | using namespace ore; | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 85 | using namespace outliner; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 86 |  | 
|  | 87 | STATISTIC(NumOutlined, "Number of candidates outlined"); | 
|  | 88 | STATISTIC(FunctionsCreated, "Number of functions created"); | 
|  | 89 |  | 
| Jessica Paquette | 1eca23b | 2018-04-19 22:17:07 +0000 | [diff] [blame] | 90 | // Set to true if the user wants the outliner to run on linkonceodr linkage | 
|  | 91 | // functions. This is false by default because the linker can dedupe linkonceodr | 
|  | 92 | // functions. Since the outliner is confined to a single module (modulo LTO), | 
|  | 93 | // this is off by default. It should, however, be the default behaviour in | 
|  | 94 | // LTO. | 
|  | 95 | static cl::opt<bool> EnableLinkOnceODROutlining( | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 96 | "enable-linkonceodr-outlining", cl::Hidden, | 
| Jessica Paquette | 1eca23b | 2018-04-19 22:17:07 +0000 | [diff] [blame] | 97 | cl::desc("Enable the machine outliner on linkonceodr functions"), | 
|  | 98 | cl::init(false)); | 
|  | 99 |  | 
| Puyan Lotfi | ffd5e12 | 2020-04-29 03:33:47 -0400 | [diff] [blame] | 100 | /// Number of times to re-run the outliner. This is not the total number of runs | 
|  | 101 | /// as the outliner will run at least one time. The default value is set to 0, | 
|  | 102 | /// meaning the outliner will run one time and rerun zero times after that. | 
|  | 103 | static cl::opt<unsigned> OutlinerReruns( | 
|  | 104 | "machine-outliner-reruns", cl::init(0), cl::Hidden, | 
|  | 105 | cl::desc( | 
|  | 106 | "Number of times to rerun the outliner after the initial outline")); | 
| Jin Lin | 0d89627 | 2020-03-17 15:40:26 -0700 | [diff] [blame] | 107 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 108 | namespace { | 
|  | 109 |  | 
|  | 110 | /// Represents an undefined index in the suffix tree. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 111 | const unsigned EmptyIdx = -1; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 112 |  | 
|  | 113 | /// A node in a suffix tree which represents a substring or suffix. | 
|  | 114 | /// | 
|  | 115 | /// Each node has either no children or at least two children, with the root | 
|  | 116 | /// being a exception in the empty tree. | 
|  | 117 | /// | 
|  | 118 | /// Children are represented as a map between unsigned integers and nodes. If | 
|  | 119 | /// a node N has a child M on unsigned integer k, then the mapping represented | 
|  | 120 | /// by N is a proper prefix of the mapping represented by M. Note that this, | 
|  | 121 | /// although similar to a trie is somewhat different: each node stores a full | 
|  | 122 | /// substring of the full mapping rather than a single character state. | 
|  | 123 | /// | 
|  | 124 | /// Each internal node contains a pointer to the internal node representing | 
|  | 125 | /// the same string, but with the first character chopped off. This is stored | 
|  | 126 | /// in \p Link. Each leaf node stores the start index of its respective | 
|  | 127 | /// suffix in \p SuffixIdx. | 
|  | 128 | struct SuffixTreeNode { | 
|  | 129 |  | 
|  | 130 | /// The children of this node. | 
|  | 131 | /// | 
|  | 132 | /// A child existing on an unsigned integer implies that from the mapping | 
|  | 133 | /// represented by the current node, there is a way to reach another | 
|  | 134 | /// mapping by tacking that character on the end of the current string. | 
|  | 135 | DenseMap<unsigned, SuffixTreeNode *> Children; | 
|  | 136 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 137 | /// The start index of this node's substring in the main string. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 138 | unsigned StartIdx = EmptyIdx; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 139 |  | 
|  | 140 | /// The end index of this node's substring in the main string. | 
|  | 141 | /// | 
|  | 142 | /// Every leaf node must have its \p EndIdx incremented at the end of every | 
|  | 143 | /// step in the construction algorithm. To avoid having to update O(N) | 
|  | 144 | /// nodes individually at the end of every step, the end index is stored | 
|  | 145 | /// as a pointer. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 146 | unsigned *EndIdx = nullptr; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 147 |  | 
|  | 148 | /// For leaves, the start index of the suffix represented by this node. | 
|  | 149 | /// | 
|  | 150 | /// For all other nodes, this is ignored. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 151 | unsigned SuffixIdx = EmptyIdx; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 152 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 153 | /// For internal nodes, a pointer to the internal node representing | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 154 | /// the same sequence with the first character chopped off. | 
|  | 155 | /// | 
| Jessica Paquette | 4602c34 | 2017-07-28 05:59:30 +0000 | [diff] [blame] | 156 | /// This acts as a shortcut in Ukkonen's algorithm. One of the things that | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 157 | /// Ukkonen's algorithm does to achieve linear-time construction is | 
|  | 158 | /// keep track of which node the next insert should be at. This makes each | 
|  | 159 | /// insert O(1), and there are a total of O(N) inserts. The suffix link | 
|  | 160 | /// helps with inserting children of internal nodes. | 
|  | 161 | /// | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 162 | /// Say we add a child to an internal node with associated mapping S. The | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 163 | /// next insertion must be at the node representing S - its first character. | 
|  | 164 | /// This is given by the way that we iteratively build the tree in Ukkonen's | 
|  | 165 | /// algorithm. The main idea is to look at the suffixes of each prefix in the | 
|  | 166 | /// string, starting with the longest suffix of the prefix, and ending with | 
|  | 167 | /// the shortest. Therefore, if we keep pointers between such nodes, we can | 
|  | 168 | /// move to the next insertion point in O(1) time. If we don't, then we'd | 
|  | 169 | /// have to query from the root, which takes O(N) time. This would make the | 
|  | 170 | /// construction algorithm O(N^2) rather than O(N). | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 171 | SuffixTreeNode *Link = nullptr; | 
|  | 172 |  | 
| Jessica Paquette | acffa28 | 2017-03-23 21:27:38 +0000 | [diff] [blame] | 173 | /// The length of the string formed by concatenating the edge labels from the | 
|  | 174 | /// root to this node. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 175 | unsigned ConcatLen = 0; | 
| Jessica Paquette | acffa28 | 2017-03-23 21:27:38 +0000 | [diff] [blame] | 176 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 177 | /// Returns true if this node is a leaf. | 
|  | 178 | bool isLeaf() const { return SuffixIdx != EmptyIdx; } | 
|  | 179 |  | 
|  | 180 | /// Returns true if this node is the root of its owning \p SuffixTree. | 
|  | 181 | bool isRoot() const { return StartIdx == EmptyIdx; } | 
|  | 182 |  | 
|  | 183 | /// Return the number of elements in the substring associated with this node. | 
|  | 184 | size_t size() const { | 
|  | 185 |  | 
|  | 186 | // Is it the root? If so, it's the empty string so return 0. | 
|  | 187 | if (isRoot()) | 
|  | 188 | return 0; | 
|  | 189 |  | 
|  | 190 | assert(*EndIdx != EmptyIdx && "EndIdx is undefined!"); | 
|  | 191 |  | 
|  | 192 | // Size = the number of elements in the string. | 
|  | 193 | // For example, [0 1 2 3] has length 4, not 3. 3-0 = 3, so we have 3-0+1. | 
|  | 194 | return *EndIdx - StartIdx + 1; | 
|  | 195 | } | 
|  | 196 |  | 
| Jessica Paquette | df5b09b | 2018-11-07 19:56:13 +0000 | [diff] [blame] | 197 | SuffixTreeNode(unsigned StartIdx, unsigned *EndIdx, SuffixTreeNode *Link) | 
|  | 198 | : StartIdx(StartIdx), EndIdx(EndIdx), Link(Link) {} | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 199 |  | 
|  | 200 | SuffixTreeNode() {} | 
|  | 201 | }; | 
|  | 202 |  | 
|  | 203 | /// A data structure for fast substring queries. | 
|  | 204 | /// | 
|  | 205 | /// Suffix trees represent the suffixes of their input strings in their leaves. | 
|  | 206 | /// A suffix tree is a type of compressed trie structure where each node | 
|  | 207 | /// represents an entire substring rather than a single character. Each leaf | 
|  | 208 | /// of the tree is a suffix. | 
|  | 209 | /// | 
|  | 210 | /// A suffix tree can be seen as a type of state machine where each state is a | 
|  | 211 | /// substring of the full string. The tree is structured so that, for a string | 
|  | 212 | /// of length N, there are exactly N leaves in the tree. This structure allows | 
|  | 213 | /// us to quickly find repeated substrings of the input string. | 
|  | 214 | /// | 
|  | 215 | /// In this implementation, a "string" is a vector of unsigned integers. | 
|  | 216 | /// These integers may result from hashing some data type. A suffix tree can | 
|  | 217 | /// contain 1 or many strings, which can then be queried as one large string. | 
|  | 218 | /// | 
|  | 219 | /// The suffix tree is implemented using Ukkonen's algorithm for linear-time | 
|  | 220 | /// suffix tree construction. Ukkonen's algorithm is explained in more detail | 
|  | 221 | /// in the paper by Esko Ukkonen "On-line construction of suffix trees. The | 
|  | 222 | /// paper is available at | 
|  | 223 | /// | 
|  | 224 | /// https://www.cs.helsinki.fi/u/ukkonen/SuffixT1withFigs.pdf | 
|  | 225 | class SuffixTree { | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 226 | public: | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 227 | /// Each element is an integer representing an instruction in the module. | 
|  | 228 | ArrayRef<unsigned> Str; | 
|  | 229 |  | 
| Jessica Paquette | 4e54ef8 | 2018-11-06 21:46:41 +0000 | [diff] [blame] | 230 | /// A repeated substring in the tree. | 
|  | 231 | struct RepeatedSubstring { | 
|  | 232 | /// The length of the string. | 
|  | 233 | unsigned Length; | 
|  | 234 |  | 
|  | 235 | /// The start indices of each occurrence. | 
|  | 236 | std::vector<unsigned> StartIndices; | 
|  | 237 | }; | 
|  | 238 |  | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 239 | private: | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 240 | /// Maintains each node in the tree. | 
| Jessica Paquette | d4cb9c6 | 2017-03-08 23:55:33 +0000 | [diff] [blame] | 241 | SpecificBumpPtrAllocator<SuffixTreeNode> NodeAllocator; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 242 |  | 
|  | 243 | /// The root of the suffix tree. | 
|  | 244 | /// | 
|  | 245 | /// The root represents the empty string. It is maintained by the | 
|  | 246 | /// \p NodeAllocator like every other node in the tree. | 
|  | 247 | SuffixTreeNode *Root = nullptr; | 
|  | 248 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 249 | /// Maintains the end indices of the internal nodes in the tree. | 
|  | 250 | /// | 
|  | 251 | /// Each internal node is guaranteed to never have its end index change | 
|  | 252 | /// during the construction algorithm; however, leaves must be updated at | 
|  | 253 | /// every step. Therefore, we need to store leaf end indices by reference | 
|  | 254 | /// to avoid updating O(N) leaves at every step of construction. Thus, | 
|  | 255 | /// every internal node must be allocated its own end index. | 
|  | 256 | BumpPtrAllocator InternalEndIdxAllocator; | 
|  | 257 |  | 
|  | 258 | /// The end index of each leaf in the tree. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 259 | unsigned LeafEndIdx = -1; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 260 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 261 | /// Helper struct which keeps track of the next insertion point in | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 262 | /// Ukkonen's algorithm. | 
|  | 263 | struct ActiveState { | 
|  | 264 | /// The next node to insert at. | 
| Simon Pilgrim | c7f127d | 2019-11-05 15:08:21 +0000 | [diff] [blame] | 265 | SuffixTreeNode *Node = nullptr; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 266 |  | 
|  | 267 | /// The index of the first character in the substring currently being added. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 268 | unsigned Idx = EmptyIdx; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 269 |  | 
|  | 270 | /// The length of the substring we have to add at the current step. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 271 | unsigned Len = 0; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 272 | }; | 
|  | 273 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 274 | /// The point the next insertion will take place at in the | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 275 | /// construction algorithm. | 
|  | 276 | ActiveState Active; | 
|  | 277 |  | 
|  | 278 | /// Allocate a leaf node and add it to the tree. | 
|  | 279 | /// | 
|  | 280 | /// \param Parent The parent of this node. | 
|  | 281 | /// \param StartIdx The start index of this node's associated string. | 
|  | 282 | /// \param Edge The label on the edge leaving \p Parent to this node. | 
|  | 283 | /// | 
|  | 284 | /// \returns A pointer to the allocated leaf node. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 285 | SuffixTreeNode *insertLeaf(SuffixTreeNode &Parent, unsigned StartIdx, | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 286 | unsigned Edge) { | 
|  | 287 |  | 
|  | 288 | assert(StartIdx <= LeafEndIdx && "String can't start after it ends!"); | 
|  | 289 |  | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 290 | SuffixTreeNode *N = new (NodeAllocator.Allocate()) | 
| Jessica Paquette | df5b09b | 2018-11-07 19:56:13 +0000 | [diff] [blame] | 291 | SuffixTreeNode(StartIdx, &LeafEndIdx, nullptr); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 292 | Parent.Children[Edge] = N; | 
|  | 293 |  | 
|  | 294 | return N; | 
|  | 295 | } | 
|  | 296 |  | 
|  | 297 | /// Allocate an internal node and add it to the tree. | 
|  | 298 | /// | 
|  | 299 | /// \param Parent The parent of this node. Only null when allocating the root. | 
|  | 300 | /// \param StartIdx The start index of this node's associated string. | 
|  | 301 | /// \param EndIdx The end index of this node's associated string. | 
|  | 302 | /// \param Edge The label on the edge leaving \p Parent to this node. | 
|  | 303 | /// | 
|  | 304 | /// \returns A pointer to the allocated internal node. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 305 | SuffixTreeNode *insertInternalNode(SuffixTreeNode *Parent, unsigned StartIdx, | 
|  | 306 | unsigned EndIdx, unsigned Edge) { | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 307 |  | 
|  | 308 | assert(StartIdx <= EndIdx && "String can't start after it ends!"); | 
|  | 309 | assert(!(!Parent && StartIdx != EmptyIdx) && | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 310 | "Non-root internal nodes must have parents!"); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 311 |  | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 312 | unsigned *E = new (InternalEndIdxAllocator) unsigned(EndIdx); | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 313 | SuffixTreeNode *N = | 
|  | 314 | new (NodeAllocator.Allocate()) SuffixTreeNode(StartIdx, E, Root); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 315 | if (Parent) | 
|  | 316 | Parent->Children[Edge] = N; | 
|  | 317 |  | 
|  | 318 | return N; | 
|  | 319 | } | 
|  | 320 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 321 | /// Set the suffix indices of the leaves to the start indices of their | 
| Jessica Paquette | 4e54ef8 | 2018-11-06 21:46:41 +0000 | [diff] [blame] | 322 | /// respective suffixes. | 
| Jessica Paquette | d575077 | 2019-12-20 15:57:39 -0800 | [diff] [blame] | 323 | void setSuffixIndices() { | 
|  | 324 | // List of nodes we need to visit along with the current length of the | 
|  | 325 | // string. | 
|  | 326 | std::vector<std::pair<SuffixTreeNode *, unsigned>> ToVisit; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 327 |  | 
| Jessica Paquette | d575077 | 2019-12-20 15:57:39 -0800 | [diff] [blame] | 328 | // Current node being visited. | 
|  | 329 | SuffixTreeNode *CurrNode = Root; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 330 |  | 
| Jessica Paquette | d575077 | 2019-12-20 15:57:39 -0800 | [diff] [blame] | 331 | // Sum of the lengths of the nodes down the path to the current one. | 
|  | 332 | unsigned CurrNodeLen = 0; | 
|  | 333 | ToVisit.push_back({CurrNode, CurrNodeLen}); | 
|  | 334 | while (!ToVisit.empty()) { | 
|  | 335 | std::tie(CurrNode, CurrNodeLen) = ToVisit.back(); | 
|  | 336 | ToVisit.pop_back(); | 
|  | 337 | CurrNode->ConcatLen = CurrNodeLen; | 
|  | 338 | for (auto &ChildPair : CurrNode->Children) { | 
|  | 339 | assert(ChildPair.second && "Node had a null child!"); | 
|  | 340 | ToVisit.push_back( | 
|  | 341 | {ChildPair.second, CurrNodeLen + ChildPair.second->size()}); | 
|  | 342 | } | 
|  | 343 |  | 
|  | 344 | // No children, so we are at the end of the string. | 
|  | 345 | if (CurrNode->Children.size() == 0 && !CurrNode->isRoot()) | 
|  | 346 | CurrNode->SuffixIdx = Str.size() - CurrNodeLen; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 347 | } | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 348 | } | 
|  | 349 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 350 | /// Construct the suffix tree for the prefix of the input ending at | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 351 | /// \p EndIdx. | 
|  | 352 | /// | 
|  | 353 | /// Used to construct the full suffix tree iteratively. At the end of each | 
|  | 354 | /// step, the constructed suffix tree is either a valid suffix tree, or a | 
|  | 355 | /// suffix tree with implicit suffixes. At the end of the final step, the | 
|  | 356 | /// suffix tree is a valid tree. | 
|  | 357 | /// | 
|  | 358 | /// \param EndIdx The end index of the current prefix in the main string. | 
|  | 359 | /// \param SuffixesToAdd The number of suffixes that must be added | 
|  | 360 | /// to complete the suffix tree at the current phase. | 
|  | 361 | /// | 
|  | 362 | /// \returns The number of suffixes that have not been added at the end of | 
|  | 363 | /// this step. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 364 | unsigned extend(unsigned EndIdx, unsigned SuffixesToAdd) { | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 365 | SuffixTreeNode *NeedsLink = nullptr; | 
|  | 366 |  | 
|  | 367 | while (SuffixesToAdd > 0) { | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 368 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 369 | // Are we waiting to add anything other than just the last character? | 
|  | 370 | if (Active.Len == 0) { | 
|  | 371 | // If not, then say the active index is the end index. | 
|  | 372 | Active.Idx = EndIdx; | 
|  | 373 | } | 
|  | 374 |  | 
|  | 375 | assert(Active.Idx <= EndIdx && "Start index can't be after end index!"); | 
|  | 376 |  | 
|  | 377 | // The first character in the current substring we're looking at. | 
|  | 378 | unsigned FirstChar = Str[Active.Idx]; | 
|  | 379 |  | 
|  | 380 | // Have we inserted anything starting with FirstChar at the current node? | 
|  | 381 | if (Active.Node->Children.count(FirstChar) == 0) { | 
|  | 382 | // If not, then we can just insert a leaf and move too the next step. | 
|  | 383 | insertLeaf(*Active.Node, EndIdx, FirstChar); | 
|  | 384 |  | 
|  | 385 | // The active node is an internal node, and we visited it, so it must | 
|  | 386 | // need a link if it doesn't have one. | 
|  | 387 | if (NeedsLink) { | 
|  | 388 | NeedsLink->Link = Active.Node; | 
|  | 389 | NeedsLink = nullptr; | 
|  | 390 | } | 
|  | 391 | } else { | 
|  | 392 | // There's a match with FirstChar, so look for the point in the tree to | 
|  | 393 | // insert a new node. | 
|  | 394 | SuffixTreeNode *NextNode = Active.Node->Children[FirstChar]; | 
|  | 395 |  | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 396 | unsigned SubstringLen = NextNode->size(); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 397 |  | 
|  | 398 | // Is the current suffix we're trying to insert longer than the size of | 
|  | 399 | // the child we want to move to? | 
|  | 400 | if (Active.Len >= SubstringLen) { | 
|  | 401 | // If yes, then consume the characters we've seen and move to the next | 
|  | 402 | // node. | 
|  | 403 | Active.Idx += SubstringLen; | 
|  | 404 | Active.Len -= SubstringLen; | 
|  | 405 | Active.Node = NextNode; | 
|  | 406 | continue; | 
|  | 407 | } | 
|  | 408 |  | 
|  | 409 | // Otherwise, the suffix we're trying to insert must be contained in the | 
|  | 410 | // next node we want to move to. | 
|  | 411 | unsigned LastChar = Str[EndIdx]; | 
|  | 412 |  | 
|  | 413 | // Is the string we're trying to insert a substring of the next node? | 
|  | 414 | if (Str[NextNode->StartIdx + Active.Len] == LastChar) { | 
|  | 415 | // If yes, then we're done for this step. Remember our insertion point | 
|  | 416 | // and move to the next end index. At this point, we have an implicit | 
|  | 417 | // suffix tree. | 
|  | 418 | if (NeedsLink && !Active.Node->isRoot()) { | 
|  | 419 | NeedsLink->Link = Active.Node; | 
|  | 420 | NeedsLink = nullptr; | 
|  | 421 | } | 
|  | 422 |  | 
|  | 423 | Active.Len++; | 
|  | 424 | break; | 
|  | 425 | } | 
|  | 426 |  | 
|  | 427 | // The string we're trying to insert isn't a substring of the next node, | 
|  | 428 | // but matches up to a point. Split the node. | 
|  | 429 | // | 
|  | 430 | // For example, say we ended our search at a node n and we're trying to | 
|  | 431 | // insert ABD. Then we'll create a new node s for AB, reduce n to just | 
|  | 432 | // representing C, and insert a new leaf node l to represent d. This | 
|  | 433 | // allows us to ensure that if n was a leaf, it remains a leaf. | 
|  | 434 | // | 
|  | 435 | //   | ABC  ---split--->  | AB | 
|  | 436 | //   n                    s | 
|  | 437 | //                     C / \ D | 
|  | 438 | //                      n   l | 
|  | 439 |  | 
|  | 440 | // The node s from the diagram | 
|  | 441 | SuffixTreeNode *SplitNode = | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 442 | insertInternalNode(Active.Node, NextNode->StartIdx, | 
|  | 443 | NextNode->StartIdx + Active.Len - 1, FirstChar); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 444 |  | 
|  | 445 | // Insert the new node representing the new substring into the tree as | 
|  | 446 | // a child of the split node. This is the node l from the diagram. | 
|  | 447 | insertLeaf(*SplitNode, EndIdx, LastChar); | 
|  | 448 |  | 
|  | 449 | // Make the old node a child of the split node and update its start | 
|  | 450 | // index. This is the node n from the diagram. | 
|  | 451 | NextNode->StartIdx += Active.Len; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 452 | SplitNode->Children[Str[NextNode->StartIdx]] = NextNode; | 
|  | 453 |  | 
|  | 454 | // SplitNode is an internal node, update the suffix link. | 
|  | 455 | if (NeedsLink) | 
|  | 456 | NeedsLink->Link = SplitNode; | 
|  | 457 |  | 
|  | 458 | NeedsLink = SplitNode; | 
|  | 459 | } | 
|  | 460 |  | 
|  | 461 | // We've added something new to the tree, so there's one less suffix to | 
|  | 462 | // add. | 
|  | 463 | SuffixesToAdd--; | 
|  | 464 |  | 
|  | 465 | if (Active.Node->isRoot()) { | 
|  | 466 | if (Active.Len > 0) { | 
|  | 467 | Active.Len--; | 
|  | 468 | Active.Idx = EndIdx - SuffixesToAdd + 1; | 
|  | 469 | } | 
|  | 470 | } else { | 
|  | 471 | // Start the next phase at the next smallest suffix. | 
|  | 472 | Active.Node = Active.Node->Link; | 
|  | 473 | } | 
|  | 474 | } | 
|  | 475 |  | 
|  | 476 | return SuffixesToAdd; | 
|  | 477 | } | 
|  | 478 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 479 | public: | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 480 | /// Construct a suffix tree from a sequence of unsigned integers. | 
|  | 481 | /// | 
|  | 482 | /// \param Str The string to construct the suffix tree for. | 
|  | 483 | SuffixTree(const std::vector<unsigned> &Str) : Str(Str) { | 
|  | 484 | Root = insertInternalNode(nullptr, EmptyIdx, EmptyIdx, 0); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 485 | Active.Node = Root; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 486 |  | 
|  | 487 | // Keep track of the number of suffixes we have to add of the current | 
|  | 488 | // prefix. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 489 | unsigned SuffixesToAdd = 0; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 490 |  | 
|  | 491 | // Construct the suffix tree iteratively on each prefix of the string. | 
|  | 492 | // PfxEndIdx is the end index of the current prefix. | 
|  | 493 | // End is one past the last element in the string. | 
| Jessica Paquette | 4cf187b | 2017-09-27 20:47:39 +0000 | [diff] [blame] | 494 | for (unsigned PfxEndIdx = 0, End = Str.size(); PfxEndIdx < End; | 
|  | 495 | PfxEndIdx++) { | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 496 | SuffixesToAdd++; | 
|  | 497 | LeafEndIdx = PfxEndIdx; // Extend each of the leaves. | 
|  | 498 | SuffixesToAdd = extend(PfxEndIdx, SuffixesToAdd); | 
|  | 499 | } | 
|  | 500 |  | 
|  | 501 | // Set the suffix indices of each leaf. | 
|  | 502 | assert(Root && "Root node can't be nullptr!"); | 
| Jessica Paquette | d575077 | 2019-12-20 15:57:39 -0800 | [diff] [blame] | 503 | setSuffixIndices(); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 504 | } | 
| Jessica Paquette | 4e54ef8 | 2018-11-06 21:46:41 +0000 | [diff] [blame] | 505 |  | 
| Jessica Paquette | a409cc9 | 2018-11-07 19:20:55 +0000 | [diff] [blame] | 506 | /// Iterator for finding all repeated substrings in the suffix tree. | 
|  | 507 | struct RepeatedSubstringIterator { | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 508 | private: | 
| Jessica Paquette | a409cc9 | 2018-11-07 19:20:55 +0000 | [diff] [blame] | 509 | /// The current node we're visiting. | 
|  | 510 | SuffixTreeNode *N = nullptr; | 
|  | 511 |  | 
|  | 512 | /// The repeated substring associated with this node. | 
|  | 513 | RepeatedSubstring RS; | 
|  | 514 |  | 
|  | 515 | /// The nodes left to visit. | 
|  | 516 | std::vector<SuffixTreeNode *> ToVisit; | 
|  | 517 |  | 
|  | 518 | /// The minimum length of a repeated substring to find. | 
|  | 519 | /// Since we're outlining, we want at least two instructions in the range. | 
|  | 520 | /// FIXME: This may not be true for targets like X86 which support many | 
|  | 521 | /// instruction lengths. | 
|  | 522 | const unsigned MinLength = 2; | 
|  | 523 |  | 
|  | 524 | /// Move the iterator to the next repeated substring. | 
|  | 525 | void advance() { | 
|  | 526 | // Clear the current state. If we're at the end of the range, then this | 
|  | 527 | // is the state we want to be in. | 
|  | 528 | RS = RepeatedSubstring(); | 
|  | 529 | N = nullptr; | 
|  | 530 |  | 
| Jessica Paquette | 3cd70b3 | 2018-12-06 00:26:21 +0000 | [diff] [blame] | 531 | // Each leaf node represents a repeat of a string. | 
|  | 532 | std::vector<SuffixTreeNode *> LeafChildren; | 
|  | 533 |  | 
| Jessica Paquette | a409cc9 | 2018-11-07 19:20:55 +0000 | [diff] [blame] | 534 | // Continue visiting nodes until we find one which repeats more than once. | 
|  | 535 | while (!ToVisit.empty()) { | 
|  | 536 | SuffixTreeNode *Curr = ToVisit.back(); | 
|  | 537 | ToVisit.pop_back(); | 
| Jessica Paquette | 3cd70b3 | 2018-12-06 00:26:21 +0000 | [diff] [blame] | 538 | LeafChildren.clear(); | 
| Jessica Paquette | a409cc9 | 2018-11-07 19:20:55 +0000 | [diff] [blame] | 539 |  | 
|  | 540 | // Keep track of the length of the string associated with the node. If | 
|  | 541 | // it's too short, we'll quit. | 
|  | 542 | unsigned Length = Curr->ConcatLen; | 
|  | 543 |  | 
| Jessica Paquette | a409cc9 | 2018-11-07 19:20:55 +0000 | [diff] [blame] | 544 | // Iterate over each child, saving internal nodes for visiting, and | 
|  | 545 | // leaf nodes in LeafChildren. Internal nodes represent individual | 
|  | 546 | // strings, which may repeat. | 
|  | 547 | for (auto &ChildPair : Curr->Children) { | 
|  | 548 | // Save all of this node's children for processing. | 
|  | 549 | if (!ChildPair.second->isLeaf()) | 
|  | 550 | ToVisit.push_back(ChildPair.second); | 
|  | 551 |  | 
|  | 552 | // It's not an internal node, so it must be a leaf. If we have a | 
|  | 553 | // long enough string, then save the leaf children. | 
|  | 554 | else if (Length >= MinLength) | 
|  | 555 | LeafChildren.push_back(ChildPair.second); | 
|  | 556 | } | 
|  | 557 |  | 
|  | 558 | // The root never represents a repeated substring. If we're looking at | 
|  | 559 | // that, then skip it. | 
|  | 560 | if (Curr->isRoot()) | 
|  | 561 | continue; | 
|  | 562 |  | 
|  | 563 | // Do we have any repeated substrings? | 
|  | 564 | if (LeafChildren.size() >= 2) { | 
|  | 565 | // Yes. Update the state to reflect this, and then bail out. | 
|  | 566 | N = Curr; | 
|  | 567 | RS.Length = Length; | 
|  | 568 | for (SuffixTreeNode *Leaf : LeafChildren) | 
|  | 569 | RS.StartIndices.push_back(Leaf->SuffixIdx); | 
|  | 570 | break; | 
|  | 571 | } | 
|  | 572 | } | 
|  | 573 |  | 
|  | 574 | // At this point, either NewRS is an empty RepeatedSubstring, or it was | 
|  | 575 | // set in the above loop. Similarly, N is either nullptr, or the node | 
|  | 576 | // associated with NewRS. | 
|  | 577 | } | 
|  | 578 |  | 
|  | 579 | public: | 
|  | 580 | /// Return the current repeated substring. | 
|  | 581 | RepeatedSubstring &operator*() { return RS; } | 
|  | 582 |  | 
|  | 583 | RepeatedSubstringIterator &operator++() { | 
|  | 584 | advance(); | 
|  | 585 | return *this; | 
|  | 586 | } | 
|  | 587 |  | 
|  | 588 | RepeatedSubstringIterator operator++(int I) { | 
|  | 589 | RepeatedSubstringIterator It(*this); | 
|  | 590 | advance(); | 
|  | 591 | return It; | 
|  | 592 | } | 
|  | 593 |  | 
|  | 594 | bool operator==(const RepeatedSubstringIterator &Other) { | 
|  | 595 | return N == Other.N; | 
|  | 596 | } | 
|  | 597 | bool operator!=(const RepeatedSubstringIterator &Other) { | 
|  | 598 | return !(*this == Other); | 
|  | 599 | } | 
|  | 600 |  | 
|  | 601 | RepeatedSubstringIterator(SuffixTreeNode *N) : N(N) { | 
|  | 602 | // Do we have a non-null node? | 
|  | 603 | if (N) { | 
|  | 604 | // Yes. At the first step, we need to visit all of N's children. | 
|  | 605 | // Note: This means that we visit N last. | 
|  | 606 | ToVisit.push_back(N); | 
|  | 607 | advance(); | 
|  | 608 | } | 
|  | 609 | } | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 610 | }; | 
| Jessica Paquette | a409cc9 | 2018-11-07 19:20:55 +0000 | [diff] [blame] | 611 |  | 
|  | 612 | typedef RepeatedSubstringIterator iterator; | 
|  | 613 | iterator begin() { return iterator(Root); } | 
|  | 614 | iterator end() { return iterator(nullptr); } | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 615 | }; | 
|  | 616 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 617 | /// Maps \p MachineInstrs to unsigned integers and stores the mappings. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 618 | struct InstructionMapper { | 
|  | 619 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 620 | /// The next available integer to assign to a \p MachineInstr that | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 621 | /// cannot be outlined. | 
|  | 622 | /// | 
|  | 623 | /// Set to -3 for compatability with \p DenseMapInfo<unsigned>. | 
|  | 624 | unsigned IllegalInstrNumber = -3; | 
|  | 625 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 626 | /// The next available integer to assign to a \p MachineInstr that can | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 627 | /// be outlined. | 
|  | 628 | unsigned LegalInstrNumber = 0; | 
|  | 629 |  | 
|  | 630 | /// Correspondence from \p MachineInstrs to unsigned integers. | 
|  | 631 | DenseMap<MachineInstr *, unsigned, MachineInstrExpressionTrait> | 
|  | 632 | InstructionIntegerMap; | 
|  | 633 |  | 
| Jessica Paquette | cad864d | 2018-11-13 23:01:34 +0000 | [diff] [blame] | 634 | /// Correspondence between \p MachineBasicBlocks and target-defined flags. | 
|  | 635 | DenseMap<MachineBasicBlock *, unsigned> MBBFlagsMap; | 
|  | 636 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 637 | /// The vector of unsigned integers that the module is mapped to. | 
|  | 638 | std::vector<unsigned> UnsignedVec; | 
|  | 639 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 640 | /// Stores the location of the instruction associated with the integer | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 641 | /// at index i in \p UnsignedVec for each index i. | 
|  | 642 | std::vector<MachineBasicBlock::iterator> InstrList; | 
|  | 643 |  | 
| Jessica Paquette | c991cf3 | 2018-11-01 23:09:06 +0000 | [diff] [blame] | 644 | // Set if we added an illegal number in the previous step. | 
|  | 645 | // Since each illegal number is unique, we only need one of them between | 
|  | 646 | // each range of legal numbers. This lets us make sure we don't add more | 
|  | 647 | // than one illegal number per range. | 
|  | 648 | bool AddedIllegalLastTime = false; | 
|  | 649 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 650 | /// Maps \p *It to a legal integer. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 651 | /// | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 652 | /// Updates \p CanOutlineWithPrevInstr, \p HaveLegalRange, \p InstrListForMBB, | 
| Jessica Paquette | ca3ed96 | 2018-12-06 00:01:51 +0000 | [diff] [blame] | 653 | /// \p UnsignedVecForMBB, \p InstructionIntegerMap, and \p LegalInstrNumber. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 654 | /// | 
|  | 655 | /// \returns The integer that \p *It was mapped to. | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 656 | unsigned mapToLegalUnsigned( | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 657 | MachineBasicBlock::iterator &It, bool &CanOutlineWithPrevInstr, | 
|  | 658 | bool &HaveLegalRange, unsigned &NumLegalInBlock, | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 659 | std::vector<unsigned> &UnsignedVecForMBB, | 
|  | 660 | std::vector<MachineBasicBlock::iterator> &InstrListForMBB) { | 
| Jessica Paquette | c991cf3 | 2018-11-01 23:09:06 +0000 | [diff] [blame] | 661 | // We added something legal, so we should unset the AddedLegalLastTime | 
|  | 662 | // flag. | 
|  | 663 | AddedIllegalLastTime = false; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 664 |  | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 665 | // If we have at least two adjacent legal instructions (which may have | 
|  | 666 | // invisible instructions in between), remember that. | 
|  | 667 | if (CanOutlineWithPrevInstr) | 
|  | 668 | HaveLegalRange = true; | 
|  | 669 | CanOutlineWithPrevInstr = true; | 
|  | 670 |  | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 671 | // Keep track of the number of legal instructions we insert. | 
|  | 672 | NumLegalInBlock++; | 
|  | 673 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 674 | // Get the integer for this instruction or give it the current | 
|  | 675 | // LegalInstrNumber. | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 676 | InstrListForMBB.push_back(It); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 677 | MachineInstr &MI = *It; | 
|  | 678 | bool WasInserted; | 
|  | 679 | DenseMap<MachineInstr *, unsigned, MachineInstrExpressionTrait>::iterator | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 680 | ResultIt; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 681 | std::tie(ResultIt, WasInserted) = | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 682 | InstructionIntegerMap.insert(std::make_pair(&MI, LegalInstrNumber)); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 683 | unsigned MINumber = ResultIt->second; | 
|  | 684 |  | 
|  | 685 | // There was an insertion. | 
| Jessica Paquette | ca3ed96 | 2018-12-06 00:01:51 +0000 | [diff] [blame] | 686 | if (WasInserted) | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 687 | LegalInstrNumber++; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 688 |  | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 689 | UnsignedVecForMBB.push_back(MINumber); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 690 |  | 
|  | 691 | // Make sure we don't overflow or use any integers reserved by the DenseMap. | 
|  | 692 | if (LegalInstrNumber >= IllegalInstrNumber) | 
|  | 693 | report_fatal_error("Instruction mapping overflow!"); | 
|  | 694 |  | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 695 | assert(LegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() && | 
|  | 696 | "Tried to assign DenseMap tombstone or empty key to instruction."); | 
|  | 697 | assert(LegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() && | 
|  | 698 | "Tried to assign DenseMap tombstone or empty key to instruction."); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 699 |  | 
|  | 700 | return MINumber; | 
|  | 701 | } | 
|  | 702 |  | 
|  | 703 | /// Maps \p *It to an illegal integer. | 
|  | 704 | /// | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 705 | /// Updates \p InstrListForMBB, \p UnsignedVecForMBB, and \p | 
|  | 706 | /// IllegalInstrNumber. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 707 | /// | 
|  | 708 | /// \returns The integer that \p *It was mapped to. | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 709 | unsigned mapToIllegalUnsigned( | 
|  | 710 | MachineBasicBlock::iterator &It, bool &CanOutlineWithPrevInstr, | 
|  | 711 | std::vector<unsigned> &UnsignedVecForMBB, | 
|  | 712 | std::vector<MachineBasicBlock::iterator> &InstrListForMBB) { | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 713 | // Can't outline an illegal instruction. Set the flag. | 
|  | 714 | CanOutlineWithPrevInstr = false; | 
|  | 715 |  | 
| Jessica Paquette | c991cf3 | 2018-11-01 23:09:06 +0000 | [diff] [blame] | 716 | // Only add one illegal number per range of legal numbers. | 
|  | 717 | if (AddedIllegalLastTime) | 
|  | 718 | return IllegalInstrNumber; | 
|  | 719 |  | 
|  | 720 | // Remember that we added an illegal number last time. | 
|  | 721 | AddedIllegalLastTime = true; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 722 | unsigned MINumber = IllegalInstrNumber; | 
|  | 723 |  | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 724 | InstrListForMBB.push_back(It); | 
|  | 725 | UnsignedVecForMBB.push_back(IllegalInstrNumber); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 726 | IllegalInstrNumber--; | 
|  | 727 |  | 
|  | 728 | assert(LegalInstrNumber < IllegalInstrNumber && | 
|  | 729 | "Instruction mapping overflow!"); | 
|  | 730 |  | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 731 | assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() && | 
|  | 732 | "IllegalInstrNumber cannot be DenseMap tombstone or empty key!"); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 733 |  | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 734 | assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() && | 
|  | 735 | "IllegalInstrNumber cannot be DenseMap tombstone or empty key!"); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 736 |  | 
|  | 737 | return MINumber; | 
|  | 738 | } | 
|  | 739 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 740 | /// Transforms a \p MachineBasicBlock into a \p vector of \p unsigneds | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 741 | /// and appends it to \p UnsignedVec and \p InstrList. | 
|  | 742 | /// | 
|  | 743 | /// Two instructions are assigned the same integer if they are identical. | 
|  | 744 | /// If an instruction is deemed unsafe to outline, then it will be assigned an | 
|  | 745 | /// unique integer. The resulting mapping is placed into a suffix tree and | 
|  | 746 | /// queried for candidates. | 
|  | 747 | /// | 
|  | 748 | /// \param MBB The \p MachineBasicBlock to be translated into integers. | 
| Eli Friedman | da08078 | 2018-08-01 00:37:20 +0000 | [diff] [blame] | 749 | /// \param TII \p TargetInstrInfo for the function. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 750 | void convertToUnsignedVec(MachineBasicBlock &MBB, | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 751 | const TargetInstrInfo &TII) { | 
| Alexander Kornienko | 3635c89 | 2018-11-13 16:41:05 +0000 | [diff] [blame] | 752 | unsigned Flags = 0; | 
| Jessica Paquette | 82d9c0a | 2018-11-12 23:51:32 +0000 | [diff] [blame] | 753 |  | 
|  | 754 | // Don't even map in this case. | 
|  | 755 | if (!TII.isMBBSafeToOutlineFrom(MBB, Flags)) | 
|  | 756 | return; | 
|  | 757 |  | 
| Jessica Paquette | cad864d | 2018-11-13 23:01:34 +0000 | [diff] [blame] | 758 | // Store info for the MBB for later outlining. | 
|  | 759 | MBBFlagsMap[&MBB] = Flags; | 
|  | 760 |  | 
| Jessica Paquette | c991cf3 | 2018-11-01 23:09:06 +0000 | [diff] [blame] | 761 | MachineBasicBlock::iterator It = MBB.begin(); | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 762 |  | 
|  | 763 | // The number of instructions in this block that will be considered for | 
|  | 764 | // outlining. | 
|  | 765 | unsigned NumLegalInBlock = 0; | 
|  | 766 |  | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 767 | // True if we have at least two legal instructions which aren't separated | 
|  | 768 | // by an illegal instruction. | 
|  | 769 | bool HaveLegalRange = false; | 
|  | 770 |  | 
|  | 771 | // True if we can perform outlining given the last mapped (non-invisible) | 
|  | 772 | // instruction. This lets us know if we have a legal range. | 
|  | 773 | bool CanOutlineWithPrevInstr = false; | 
|  | 774 |  | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 775 | // FIXME: Should this all just be handled in the target, rather than using | 
|  | 776 | // repeated calls to getOutliningType? | 
|  | 777 | std::vector<unsigned> UnsignedVecForMBB; | 
|  | 778 | std::vector<MachineBasicBlock::iterator> InstrListForMBB; | 
|  | 779 |  | 
| Simon Pilgrim | 76166a1 | 2019-11-05 16:46:10 +0000 | [diff] [blame] | 780 | for (MachineBasicBlock::iterator Et = MBB.end(); It != Et; ++It) { | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 781 | // Keep track of where this instruction is in the module. | 
| Jessica Paquette | 3291e73 | 2018-01-09 00:26:18 +0000 | [diff] [blame] | 782 | switch (TII.getOutliningType(It, Flags)) { | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 783 | case InstrType::Illegal: | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 784 | mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB, | 
|  | 785 | InstrListForMBB); | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 786 | break; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 787 |  | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 788 | case InstrType::Legal: | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 789 | mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange, | 
|  | 790 | NumLegalInBlock, UnsignedVecForMBB, InstrListForMBB); | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 791 | break; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 792 |  | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 793 | case InstrType::LegalTerminator: | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 794 | mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange, | 
|  | 795 | NumLegalInBlock, UnsignedVecForMBB, InstrListForMBB); | 
| Jessica Paquette | c991cf3 | 2018-11-01 23:09:06 +0000 | [diff] [blame] | 796 | // The instruction also acts as a terminator, so we have to record that | 
|  | 797 | // in the string. | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 798 | mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB, | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 799 | InstrListForMBB); | 
| Eli Friedman | 042dc9e | 2018-05-22 19:11:06 +0000 | [diff] [blame] | 800 | break; | 
|  | 801 |  | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 802 | case InstrType::Invisible: | 
| Jessica Paquette | c991cf3 | 2018-11-01 23:09:06 +0000 | [diff] [blame] | 803 | // Normally this is set by mapTo(Blah)Unsigned, but we just want to | 
|  | 804 | // skip this instruction. So, unset the flag here. | 
| Jessica Paquette | bd72988 | 2018-09-17 18:40:21 +0000 | [diff] [blame] | 805 | AddedIllegalLastTime = false; | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 806 | break; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 807 | } | 
|  | 808 | } | 
|  | 809 |  | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 810 | // Are there enough legal instructions in the block for outlining to be | 
|  | 811 | // possible? | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 812 | if (HaveLegalRange) { | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 813 | // After we're done every insertion, uniquely terminate this part of the | 
|  | 814 | // "string". This makes sure we won't match across basic block or function | 
|  | 815 | // boundaries since the "end" is encoded uniquely and thus appears in no | 
|  | 816 | // repeated substring. | 
| Jessica Paquette | c4cf775 | 2018-11-08 00:33:38 +0000 | [diff] [blame] | 817 | mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB, | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 818 | InstrListForMBB); | 
| Jessica Paquette | 267d266 | 2018-11-08 00:02:11 +0000 | [diff] [blame] | 819 | InstrList.insert(InstrList.end(), InstrListForMBB.begin(), | 
|  | 820 | InstrListForMBB.end()); | 
|  | 821 | UnsignedVec.insert(UnsignedVec.end(), UnsignedVecForMBB.begin(), | 
|  | 822 | UnsignedVecForMBB.end()); | 
|  | 823 | } | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 824 | } | 
|  | 825 |  | 
|  | 826 | InstructionMapper() { | 
|  | 827 | // Make sure that the implementation of DenseMapInfo<unsigned> hasn't | 
|  | 828 | // changed. | 
|  | 829 | assert(DenseMapInfo<unsigned>::getEmptyKey() == (unsigned)-1 && | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 830 | "DenseMapInfo<unsigned>'s empty key isn't -1!"); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 831 | assert(DenseMapInfo<unsigned>::getTombstoneKey() == (unsigned)-2 && | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 832 | "DenseMapInfo<unsigned>'s tombstone key isn't -2!"); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 833 | } | 
|  | 834 | }; | 
|  | 835 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 836 | /// An interprocedural pass which finds repeated sequences of | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 837 | /// instructions and replaces them with calls to functions. | 
|  | 838 | /// | 
|  | 839 | /// Each instruction is mapped to an unsigned integer and placed in a string. | 
|  | 840 | /// The resulting mapping is then placed in a \p SuffixTree. The \p SuffixTree | 
|  | 841 | /// is then repeatedly queried for repeated sequences of instructions. Each | 
|  | 842 | /// non-overlapping repeated sequence is then placed in its own | 
|  | 843 | /// \p MachineFunction and each instance is then replaced with a call to that | 
|  | 844 | /// function. | 
|  | 845 | struct MachineOutliner : public ModulePass { | 
|  | 846 |  | 
|  | 847 | static char ID; | 
|  | 848 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 849 | /// Set to true if the outliner should consider functions with | 
| Jessica Paquette | 1359384 | 2017-10-07 00:16:34 +0000 | [diff] [blame] | 850 | /// linkonceodr linkage. | 
|  | 851 | bool OutlineFromLinkOnceODRs = false; | 
|  | 852 |  | 
| Jin Lin | 0d89627 | 2020-03-17 15:40:26 -0700 | [diff] [blame] | 853 | /// The current repeat number of machine outlining. | 
|  | 854 | unsigned OutlineRepeatedNum = 0; | 
|  | 855 |  | 
| Jessica Paquette | 8bda188 | 2018-06-30 03:56:03 +0000 | [diff] [blame] | 856 | /// Set to true if the outliner should run on all functions in the module | 
|  | 857 | /// considered safe for outlining. | 
|  | 858 | /// Set to true by default for compatibility with llc's -run-pass option. | 
|  | 859 | /// Set when the pass is constructed in TargetPassConfig. | 
|  | 860 | bool RunOnAllFunctions = true; | 
|  | 861 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 862 | StringRef getPassName() const override { return "Machine Outliner"; } | 
|  | 863 |  | 
|  | 864 | void getAnalysisUsage(AnalysisUsage &AU) const override { | 
| Yuanfang Chen | cc382cf | 2019-09-30 17:54:50 +0000 | [diff] [blame] | 865 | AU.addRequired<MachineModuleInfoWrapperPass>(); | 
|  | 866 | AU.addPreserved<MachineModuleInfoWrapperPass>(); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 867 | AU.setPreservesAll(); | 
|  | 868 | ModulePass::getAnalysisUsage(AU); | 
|  | 869 | } | 
|  | 870 |  | 
| Jessica Paquette | 1eca23b | 2018-04-19 22:17:07 +0000 | [diff] [blame] | 871 | MachineOutliner() : ModulePass(ID) { | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 872 | initializeMachineOutlinerPass(*PassRegistry::getPassRegistry()); | 
|  | 873 | } | 
|  | 874 |  | 
| Jessica Paquette | 1cc52a0 | 2018-07-24 17:37:28 +0000 | [diff] [blame] | 875 | /// Remark output explaining that not outlining a set of candidates would be | 
|  | 876 | /// better than outlining that set. | 
|  | 877 | void emitNotOutliningCheaperRemark( | 
|  | 878 | unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq, | 
|  | 879 | OutlinedFunction &OF); | 
|  | 880 |  | 
| Jessica Paquette | 58e706a | 2018-07-24 20:20:45 +0000 | [diff] [blame] | 881 | /// Remark output explaining that a function was outlined. | 
|  | 882 | void emitOutlinedFunctionRemark(OutlinedFunction &OF); | 
|  | 883 |  | 
| Jessica Paquette | ce3a2dc | 2018-12-05 23:39:07 +0000 | [diff] [blame] | 884 | /// Find all repeated substrings that satisfy the outlining cost model by | 
|  | 885 | /// constructing a suffix tree. | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 886 | /// | 
|  | 887 | /// If a substring appears at least twice, then it must be represented by | 
| Jessica Paquette | 1cc52a0 | 2018-07-24 17:37:28 +0000 | [diff] [blame] | 888 | /// an internal node which appears in at least two suffixes. Each suffix | 
|  | 889 | /// is represented by a leaf node. To do this, we visit each internal node | 
|  | 890 | /// in the tree, using the leaf children of each internal node. If an | 
|  | 891 | /// internal node represents a beneficial substring, then we use each of | 
|  | 892 | /// its leaf children to find the locations of its substring. | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 893 | /// | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 894 | /// \param Mapper Contains outlining mapping information. | 
| Jessica Paquette | 1cc52a0 | 2018-07-24 17:37:28 +0000 | [diff] [blame] | 895 | /// \param[out] FunctionList Filled with a list of \p OutlinedFunctions | 
|  | 896 | /// each type of candidate. | 
| Jessica Paquette | ce3a2dc | 2018-12-05 23:39:07 +0000 | [diff] [blame] | 897 | void findCandidates(InstructionMapper &Mapper, | 
|  | 898 | std::vector<OutlinedFunction> &FunctionList); | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 899 |  | 
| Jessica Paquette | 4ae3b71 | 2018-12-05 22:50:26 +0000 | [diff] [blame] | 900 | /// Replace the sequences of instructions represented by \p OutlinedFunctions | 
|  | 901 | /// with calls to functions. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 902 | /// | 
|  | 903 | /// \param M The module we are outlining from. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 904 | /// \param FunctionList A list of functions to be inserted into the module. | 
|  | 905 | /// \param Mapper Contains the instruction mappings for the module. | 
| Jessica Paquette | 4ae3b71 | 2018-12-05 22:50:26 +0000 | [diff] [blame] | 906 | bool outline(Module &M, std::vector<OutlinedFunction> &FunctionList, | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 907 | InstructionMapper &Mapper, unsigned &OutlinedFunctionNum); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 908 |  | 
|  | 909 | /// Creates a function for \p OF and inserts it into the module. | 
| Jessica Paquette | e18d6ff | 2018-12-05 23:24:22 +0000 | [diff] [blame] | 910 | MachineFunction *createOutlinedFunction(Module &M, OutlinedFunction &OF, | 
| Jessica Paquette | a3eb0fa | 2018-11-07 18:36:43 +0000 | [diff] [blame] | 911 | InstructionMapper &Mapper, | 
|  | 912 | unsigned Name); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 913 |  | 
| Puyan Lotfi | ffd5e12 | 2020-04-29 03:33:47 -0400 | [diff] [blame] | 914 | /// Calls 'doOutline()' 1 + OutlinerReruns times. | 
| Jin Lin | 7b166d5 | 2020-03-17 18:33:55 -0700 | [diff] [blame] | 915 | bool runOnModule(Module &M) override; | 
| Jin Lin | ab2dcff | 2020-03-17 15:40:26 -0700 | [diff] [blame] | 916 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 917 | /// Construct a suffix tree on the instructions in \p M and outline repeated | 
|  | 918 | /// strings from that tree. | 
| Puyan Lotfi | a51fc8d | 2019-10-28 15:10:21 -0400 | [diff] [blame] | 919 | bool doOutline(Module &M, unsigned &OutlinedFunctionNum); | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 920 |  | 
|  | 921 | /// Return a DISubprogram for OF if one exists, and null otherwise. Helper | 
|  | 922 | /// function for remark emission. | 
|  | 923 | DISubprogram *getSubprogramOrNull(const OutlinedFunction &OF) { | 
| Jessica Paquette | e18d6ff | 2018-12-05 23:24:22 +0000 | [diff] [blame] | 924 | for (const Candidate &C : OF.Candidates) | 
| Simon Pilgrim | 7ad2583 | 2019-11-05 15:58:04 +0000 | [diff] [blame] | 925 | if (MachineFunction *MF = C.getMF()) | 
|  | 926 | if (DISubprogram *SP = MF->getFunction().getSubprogram()) | 
|  | 927 | return SP; | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 928 | return nullptr; | 
|  | 929 | } | 
| Jessica Paquette | 050d1ac | 2018-09-11 16:33:46 +0000 | [diff] [blame] | 930 |  | 
|  | 931 | /// Populate and \p InstructionMapper with instruction-to-integer mappings. | 
|  | 932 | /// These are used to construct a suffix tree. | 
|  | 933 | void populateMapper(InstructionMapper &Mapper, Module &M, | 
|  | 934 | MachineModuleInfo &MMI); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 935 |  | 
| Jessica Paquette | 2386eab | 2018-09-11 23:05:34 +0000 | [diff] [blame] | 936 | /// Initialize information necessary to output a size remark. | 
|  | 937 | /// FIXME: This should be handled by the pass manager, not the outliner. | 
|  | 938 | /// FIXME: This is nearly identical to the initSizeRemarkInfo in the legacy | 
|  | 939 | /// pass manager. | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 940 | void initSizeRemarkInfo(const Module &M, const MachineModuleInfo &MMI, | 
|  | 941 | StringMap<unsigned> &FunctionToInstrCount); | 
| Jessica Paquette | 2386eab | 2018-09-11 23:05:34 +0000 | [diff] [blame] | 942 |  | 
|  | 943 | /// Emit the remark. | 
|  | 944 | // FIXME: This should be handled by the pass manager, not the outliner. | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 945 | void | 
|  | 946 | emitInstrCountChangedRemark(const Module &M, const MachineModuleInfo &MMI, | 
|  | 947 | const StringMap<unsigned> &FunctionToInstrCount); | 
| Jessica Paquette | 2386eab | 2018-09-11 23:05:34 +0000 | [diff] [blame] | 948 | }; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 949 | } // Anonymous namespace. | 
|  | 950 |  | 
|  | 951 | char MachineOutliner::ID = 0; | 
|  | 952 |  | 
|  | 953 | namespace llvm { | 
| Jessica Paquette | 8bda188 | 2018-06-30 03:56:03 +0000 | [diff] [blame] | 954 | ModulePass *createMachineOutlinerPass(bool RunOnAllFunctions) { | 
|  | 955 | MachineOutliner *OL = new MachineOutliner(); | 
|  | 956 | OL->RunOnAllFunctions = RunOnAllFunctions; | 
|  | 957 | return OL; | 
| Jessica Paquette | 1359384 | 2017-10-07 00:16:34 +0000 | [diff] [blame] | 958 | } | 
|  | 959 |  | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 960 | } // namespace llvm | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 961 |  | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 962 | INITIALIZE_PASS(MachineOutliner, DEBUG_TYPE, "Machine Function Outliner", false, | 
|  | 963 | false) | 
|  | 964 |  | 
| Jessica Paquette | 1cc52a0 | 2018-07-24 17:37:28 +0000 | [diff] [blame] | 965 | void MachineOutliner::emitNotOutliningCheaperRemark( | 
|  | 966 | unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq, | 
|  | 967 | OutlinedFunction &OF) { | 
| Jessica Paquette | c991cf3 | 2018-11-01 23:09:06 +0000 | [diff] [blame] | 968 | // FIXME: Right now, we arbitrarily choose some Candidate from the | 
|  | 969 | // OutlinedFunction. This isn't necessarily fixed, nor does it have to be. | 
|  | 970 | // We should probably sort these by function name or something to make sure | 
|  | 971 | // the remarks are stable. | 
| Jessica Paquette | 1cc52a0 | 2018-07-24 17:37:28 +0000 | [diff] [blame] | 972 | Candidate &C = CandidatesForRepeatedSeq.front(); | 
|  | 973 | MachineOptimizationRemarkEmitter MORE(*(C.getMF()), nullptr); | 
|  | 974 | MORE.emit([&]() { | 
|  | 975 | MachineOptimizationRemarkMissed R(DEBUG_TYPE, "NotOutliningCheaper", | 
|  | 976 | C.front()->getDebugLoc(), C.getMBB()); | 
|  | 977 | R << "Did not outline " << NV("Length", StringLen) << " instructions" | 
|  | 978 | << " from " << NV("NumOccurrences", CandidatesForRepeatedSeq.size()) | 
|  | 979 | << " locations." | 
|  | 980 | << " Bytes from outlining all occurrences (" | 
|  | 981 | << NV("OutliningCost", OF.getOutliningCost()) << ")" | 
|  | 982 | << " >= Unoutlined instruction bytes (" | 
|  | 983 | << NV("NotOutliningCost", OF.getNotOutlinedCost()) << ")" | 
|  | 984 | << " (Also found at: "; | 
|  | 985 |  | 
|  | 986 | // Tell the user the other places the candidate was found. | 
|  | 987 | for (unsigned i = 1, e = CandidatesForRepeatedSeq.size(); i < e; i++) { | 
|  | 988 | R << NV((Twine("OtherStartLoc") + Twine(i)).str(), | 
|  | 989 | CandidatesForRepeatedSeq[i].front()->getDebugLoc()); | 
|  | 990 | if (i != e - 1) | 
|  | 991 | R << ", "; | 
|  | 992 | } | 
|  | 993 |  | 
|  | 994 | R << ")"; | 
|  | 995 | return R; | 
|  | 996 | }); | 
|  | 997 | } | 
|  | 998 |  | 
| Jessica Paquette | 58e706a | 2018-07-24 20:20:45 +0000 | [diff] [blame] | 999 | void MachineOutliner::emitOutlinedFunctionRemark(OutlinedFunction &OF) { | 
|  | 1000 | MachineBasicBlock *MBB = &*OF.MF->begin(); | 
|  | 1001 | MachineOptimizationRemarkEmitter MORE(*OF.MF, nullptr); | 
|  | 1002 | MachineOptimizationRemark R(DEBUG_TYPE, "OutlinedFunction", | 
|  | 1003 | MBB->findDebugLoc(MBB->begin()), MBB); | 
|  | 1004 | R << "Saved " << NV("OutliningBenefit", OF.getBenefit()) << " bytes by " | 
| Jessica Paquette | 34b618b | 2018-12-05 17:57:33 +0000 | [diff] [blame] | 1005 | << "outlining " << NV("Length", OF.getNumInstrs()) << " instructions " | 
| Jessica Paquette | 58e706a | 2018-07-24 20:20:45 +0000 | [diff] [blame] | 1006 | << "from " << NV("NumOccurrences", OF.getOccurrenceCount()) | 
|  | 1007 | << " locations. " | 
|  | 1008 | << "(Found at: "; | 
|  | 1009 |  | 
|  | 1010 | // Tell the user the other places the candidate was found. | 
|  | 1011 | for (size_t i = 0, e = OF.Candidates.size(); i < e; i++) { | 
|  | 1012 |  | 
| Jessica Paquette | 58e706a | 2018-07-24 20:20:45 +0000 | [diff] [blame] | 1013 | R << NV((Twine("StartLoc") + Twine(i)).str(), | 
| Jessica Paquette | e18d6ff | 2018-12-05 23:24:22 +0000 | [diff] [blame] | 1014 | OF.Candidates[i].front()->getDebugLoc()); | 
| Jessica Paquette | 58e706a | 2018-07-24 20:20:45 +0000 | [diff] [blame] | 1015 | if (i != e - 1) | 
|  | 1016 | R << ", "; | 
|  | 1017 | } | 
|  | 1018 |  | 
|  | 1019 | R << ")"; | 
|  | 1020 |  | 
|  | 1021 | MORE.emit(R); | 
|  | 1022 | } | 
|  | 1023 |  | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 1024 | void MachineOutliner::findCandidates( | 
|  | 1025 | InstructionMapper &Mapper, std::vector<OutlinedFunction> &FunctionList) { | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 1026 | FunctionList.clear(); | 
| Jessica Paquette | ce3a2dc | 2018-12-05 23:39:07 +0000 | [diff] [blame] | 1027 | SuffixTree ST(Mapper.UnsignedVec); | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 1028 |  | 
| David Tellenbach | fbe7f5e | 2019-10-30 16:28:11 +0000 | [diff] [blame] | 1029 | // First, find all of the repeated substrings in the tree of minimum length | 
| Jessica Paquette | 4e54ef8 | 2018-11-06 21:46:41 +0000 | [diff] [blame] | 1030 | // 2. | 
| Jessica Paquette | d4e7d07 | 2018-12-06 00:04:03 +0000 | [diff] [blame] | 1031 | std::vector<Candidate> CandidatesForRepeatedSeq; | 
| Jessica Paquette | a409cc9 | 2018-11-07 19:20:55 +0000 | [diff] [blame] | 1032 | for (auto It = ST.begin(), Et = ST.end(); It != Et; ++It) { | 
| Jessica Paquette | d4e7d07 | 2018-12-06 00:04:03 +0000 | [diff] [blame] | 1033 | CandidatesForRepeatedSeq.clear(); | 
| Jessica Paquette | a409cc9 | 2018-11-07 19:20:55 +0000 | [diff] [blame] | 1034 | SuffixTree::RepeatedSubstring RS = *It; | 
| Jessica Paquette | 4e54ef8 | 2018-11-06 21:46:41 +0000 | [diff] [blame] | 1035 | unsigned StringLen = RS.Length; | 
|  | 1036 | for (const unsigned &StartIdx : RS.StartIndices) { | 
|  | 1037 | unsigned EndIdx = StartIdx + StringLen - 1; | 
|  | 1038 | // Trick: Discard some candidates that would be incompatible with the | 
|  | 1039 | // ones we've already found for this sequence. This will save us some | 
|  | 1040 | // work in candidate selection. | 
|  | 1041 | // | 
|  | 1042 | // If two candidates overlap, then we can't outline them both. This | 
|  | 1043 | // happens when we have candidates that look like, say | 
|  | 1044 | // | 
|  | 1045 | // AA (where each "A" is an instruction). | 
|  | 1046 | // | 
|  | 1047 | // We might have some portion of the module that looks like this: | 
|  | 1048 | // AAAAAA (6 A's) | 
|  | 1049 | // | 
|  | 1050 | // In this case, there are 5 different copies of "AA" in this range, but | 
|  | 1051 | // at most 3 can be outlined. If only outlining 3 of these is going to | 
|  | 1052 | // be unbeneficial, then we ought to not bother. | 
|  | 1053 | // | 
|  | 1054 | // Note that two things DON'T overlap when they look like this: | 
|  | 1055 | // start1...end1 .... start2...end2 | 
|  | 1056 | // That is, one must either | 
|  | 1057 | // * End before the other starts | 
|  | 1058 | // * Start after the other ends | 
|  | 1059 | if (std::all_of( | 
|  | 1060 | CandidatesForRepeatedSeq.begin(), CandidatesForRepeatedSeq.end(), | 
|  | 1061 | [&StartIdx, &EndIdx](const Candidate &C) { | 
|  | 1062 | return (EndIdx < C.getStartIdx() || StartIdx > C.getEndIdx()); | 
|  | 1063 | })) { | 
|  | 1064 | // It doesn't overlap with anything, so we can outline it. | 
|  | 1065 | // Each sequence is over [StartIt, EndIt]. | 
|  | 1066 | // Save the candidate and its location. | 
| Jessica Paquette | d87f544 | 2017-07-29 02:55:46 +0000 | [diff] [blame] | 1067 |  | 
| Jessica Paquette | 4e54ef8 | 2018-11-06 21:46:41 +0000 | [diff] [blame] | 1068 | MachineBasicBlock::iterator StartIt = Mapper.InstrList[StartIdx]; | 
|  | 1069 | MachineBasicBlock::iterator EndIt = Mapper.InstrList[EndIdx]; | 
| Jessica Paquette | cad864d | 2018-11-13 23:01:34 +0000 | [diff] [blame] | 1070 | MachineBasicBlock *MBB = StartIt->getParent(); | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 1071 |  | 
| Jessica Paquette | 4e54ef8 | 2018-11-06 21:46:41 +0000 | [diff] [blame] | 1072 | CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt, | 
| Jessica Paquette | cad864d | 2018-11-13 23:01:34 +0000 | [diff] [blame] | 1073 | EndIt, MBB, FunctionList.size(), | 
|  | 1074 | Mapper.MBBFlagsMap[MBB]); | 
| Jessica Paquette | 809d708 | 2017-07-28 03:21:58 +0000 | [diff] [blame] | 1075 | } | 
|  | 1076 | } | 
|  | 1077 |  | 
| Jessica Paquette | acc15e1 | 2017-10-03 20:32:55 +0000 | [diff] [blame] | 1078 | // We've found something we might want to outline. | 
|  | 1079 | // Create an OutlinedFunction to store it and check if it'd be beneficial | 
|  | 1080 | // to outline. | 
| Jessica Paquette | ddb039a | 2018-11-15 00:02:24 +0000 | [diff] [blame] | 1081 | if (CandidatesForRepeatedSeq.size() < 2) | 
| Eli Friedman | da08078 | 2018-08-01 00:37:20 +0000 | [diff] [blame] | 1082 | continue; | 
|  | 1083 |  | 
|  | 1084 | // Arbitrarily choose a TII from the first candidate. | 
|  | 1085 | // FIXME: Should getOutliningCandidateInfo move to TargetMachine? | 
|  | 1086 | const TargetInstrInfo *TII = | 
|  | 1087 | CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo(); | 
|  | 1088 |  | 
| Jessica Paquette | 9d93c60 | 2018-07-27 18:21:57 +0000 | [diff] [blame] | 1089 | OutlinedFunction OF = | 
| Eli Friedman | da08078 | 2018-08-01 00:37:20 +0000 | [diff] [blame] | 1090 | TII->getOutliningCandidateInfo(CandidatesForRepeatedSeq); | 
| Jessica Paquette | 9d93c60 | 2018-07-27 18:21:57 +0000 | [diff] [blame] | 1091 |  | 
| Jessica Paquette | b2d53c5 | 2018-11-13 22:16:27 +0000 | [diff] [blame] | 1092 | // If we deleted too many candidates, then there's nothing worth outlining. | 
|  | 1093 | // FIXME: This should take target-specified instruction sizes into account. | 
|  | 1094 | if (OF.Candidates.size() < 2) | 
| Jessica Paquette | 9d93c60 | 2018-07-27 18:21:57 +0000 | [diff] [blame] | 1095 | continue; | 
|  | 1096 |  | 
| Jessica Paquette | ffe4abc | 2017-08-31 21:02:45 +0000 | [diff] [blame] | 1097 | // Is it better to outline this candidate than not? | 
| Jessica Paquette | f94d1d2 | 2018-07-24 17:36:13 +0000 | [diff] [blame] | 1098 | if (OF.getBenefit() < 1) { | 
| Jessica Paquette | 1cc52a0 | 2018-07-24 17:37:28 +0000 | [diff] [blame] | 1099 | emitNotOutliningCheaperRemark(StringLen, CandidatesForRepeatedSeq, OF); | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 1100 | continue; | 
| Jessica Paquette | ffe4abc | 2017-08-31 21:02:45 +0000 | [diff] [blame] | 1101 | } | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 1102 |  | 
| Jessica Paquette | acc15e1 | 2017-10-03 20:32:55 +0000 | [diff] [blame] | 1103 | FunctionList.push_back(OF); | 
| Jessica Paquette | 78681be | 2017-07-27 23:24:43 +0000 | [diff] [blame] | 1104 | } | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1105 | } | 
|  | 1106 |  | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 1107 | MachineFunction *MachineOutliner::createOutlinedFunction( | 
|  | 1108 | Module &M, OutlinedFunction &OF, InstructionMapper &Mapper, unsigned Name) { | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1109 |  | 
| Fangrui Song | ae6c940 | 2019-04-10 14:52:37 +0000 | [diff] [blame] | 1110 | // Create the function name. This should be unique. | 
| Jessica Paquette | a3eb0fa | 2018-11-07 18:36:43 +0000 | [diff] [blame] | 1111 | // FIXME: We should have a better naming scheme. This should be stable, | 
|  | 1112 | // regardless of changes to the outliner's cost model/traversal order. | 
| Puyan Lotfi | 0c4aab2 | 2020-05-05 23:25:13 -0400 | [diff] [blame] | 1113 | std::string FunctionName = "OUTLINED_FUNCTION_"; | 
| Jin Lin | 0d89627 | 2020-03-17 15:40:26 -0700 | [diff] [blame] | 1114 | if (OutlineRepeatedNum > 0) | 
| Puyan Lotfi | 0c4aab2 | 2020-05-05 23:25:13 -0400 | [diff] [blame] | 1115 | FunctionName += std::to_string(OutlineRepeatedNum + 1) + "_"; | 
|  | 1116 | FunctionName += std::to_string(Name); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1117 |  | 
|  | 1118 | // Create the function using an IR-level function. | 
|  | 1119 | LLVMContext &C = M.getContext(); | 
| Fangrui Song | ae6c940 | 2019-04-10 14:52:37 +0000 | [diff] [blame] | 1120 | Function *F = Function::Create(FunctionType::get(Type::getVoidTy(C), false), | 
|  | 1121 | Function::ExternalLinkage, FunctionName, M); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1122 |  | 
|  | 1123 | // NOTE: If this is linkonceodr, then we can take advantage of linker deduping | 
|  | 1124 | // which gives us better results when we outline from linkonceodr functions. | 
| Jessica Paquette | d506bf8 | 2018-04-03 21:36:00 +0000 | [diff] [blame] | 1125 | F->setLinkage(GlobalValue::InternalLinkage); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1126 | F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); | 
|  | 1127 |  | 
| Eli Friedman | 25bef20 | 2018-05-15 23:36:46 +0000 | [diff] [blame] | 1128 | // FIXME: Set nounwind, so we don't generate eh_frame? Haven't verified it's | 
|  | 1129 | // necessary. | 
|  | 1130 |  | 
|  | 1131 | // Set optsize/minsize, so we don't insert padding between outlined | 
|  | 1132 | // functions. | 
|  | 1133 | F->addFnAttr(Attribute::OptimizeForSize); | 
|  | 1134 | F->addFnAttr(Attribute::MinSize); | 
|  | 1135 |  | 
| Jessica Paquette | e3932ee | 2018-10-29 20:27:07 +0000 | [diff] [blame] | 1136 | // Include target features from an arbitrary candidate for the outlined | 
|  | 1137 | // function. This makes sure the outlined function knows what kinds of | 
|  | 1138 | // instructions are going into it. This is fine, since all parent functions | 
|  | 1139 | // must necessarily support the instructions that are in the outlined region. | 
| Jessica Paquette | e18d6ff | 2018-12-05 23:24:22 +0000 | [diff] [blame] | 1140 | Candidate &FirstCand = OF.Candidates.front(); | 
| Jessica Paquette | 34b618b | 2018-12-05 17:57:33 +0000 | [diff] [blame] | 1141 | const Function &ParentFn = FirstCand.getMF()->getFunction(); | 
| Jessica Paquette | e3932ee | 2018-10-29 20:27:07 +0000 | [diff] [blame] | 1142 | if (ParentFn.hasFnAttribute("target-features")) | 
|  | 1143 | F->addFnAttr(ParentFn.getFnAttribute("target-features")); | 
|  | 1144 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1145 | BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F); | 
|  | 1146 | IRBuilder<> Builder(EntryBB); | 
|  | 1147 | Builder.CreateRetVoid(); | 
|  | 1148 |  | 
| Yuanfang Chen | cc382cf | 2019-09-30 17:54:50 +0000 | [diff] [blame] | 1149 | MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI(); | 
| Matthias Braun | 7bda195 | 2017-06-06 00:44:35 +0000 | [diff] [blame] | 1150 | MachineFunction &MF = MMI.getOrCreateMachineFunction(*F); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1151 | MachineBasicBlock &MBB = *MF.CreateMachineBasicBlock(); | 
|  | 1152 | const TargetSubtargetInfo &STI = MF.getSubtarget(); | 
|  | 1153 | const TargetInstrInfo &TII = *STI.getInstrInfo(); | 
|  | 1154 |  | 
|  | 1155 | // Insert the new function into the module. | 
|  | 1156 | MF.insert(MF.begin(), &MBB); | 
|  | 1157 |  | 
| Andrew Litteken | 8d5024f | 2020-04-09 18:06:38 -0700 | [diff] [blame] | 1158 | MachineFunction *OriginalMF = FirstCand.front()->getMF(); | 
|  | 1159 | const std::vector<MCCFIInstruction> &Instrs = | 
|  | 1160 | OriginalMF->getFrameInstructions(); | 
| Jessica Paquette | 34b618b | 2018-12-05 17:57:33 +0000 | [diff] [blame] | 1161 | for (auto I = FirstCand.front(), E = std::next(FirstCand.back()); I != E; | 
|  | 1162 | ++I) { | 
|  | 1163 | MachineInstr *NewMI = MF.CloneMachineInstr(&*I); | 
| Andrew Litteken | 8d5024f | 2020-04-09 18:06:38 -0700 | [diff] [blame] | 1164 | if (I->isCFIInstruction()) { | 
|  | 1165 | unsigned CFIIndex = NewMI->getOperand(0).getCFIIndex(); | 
|  | 1166 | MCCFIInstruction CFI = Instrs[CFIIndex]; | 
|  | 1167 | (void)MF.addFrameInst(CFI); | 
|  | 1168 | } | 
| Chandler Carruth | c73c030 | 2018-08-16 21:30:05 +0000 | [diff] [blame] | 1169 | NewMI->dropMemRefs(MF); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1170 |  | 
|  | 1171 | // Don't keep debug information for outlined instructions. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1172 | NewMI->setDebugLoc(DebugLoc()); | 
|  | 1173 | MBB.insert(MBB.end(), NewMI); | 
|  | 1174 | } | 
|  | 1175 |  | 
| Eli Friedman | 1a78b0b | 2020-04-21 17:40:41 -0700 | [diff] [blame] | 1176 | // Set normal properties for a late MachineFunction. | 
|  | 1177 | MF.getProperties().reset(MachineFunctionProperties::Property::IsSSA); | 
|  | 1178 | MF.getProperties().set(MachineFunctionProperties::Property::NoPHIs); | 
|  | 1179 | MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs); | 
|  | 1180 | MF.getProperties().set(MachineFunctionProperties::Property::TracksLiveness); | 
| Jessica Paquette | cc06a78 | 2018-09-20 18:53:53 +0000 | [diff] [blame] | 1181 | MF.getRegInfo().freezeReservedRegs(MF); | 
|  | 1182 |  | 
| Eli Friedman | 1a78b0b | 2020-04-21 17:40:41 -0700 | [diff] [blame] | 1183 | // Compute live-in set for outlined fn | 
|  | 1184 | const MachineRegisterInfo &MRI = MF.getRegInfo(); | 
|  | 1185 | const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); | 
|  | 1186 | LivePhysRegs LiveIns(TRI); | 
|  | 1187 | for (auto &Cand : OF.Candidates) { | 
|  | 1188 | // Figure out live-ins at the first instruction. | 
|  | 1189 | MachineBasicBlock &OutlineBB = *Cand.front()->getParent(); | 
|  | 1190 | LivePhysRegs CandLiveIns(TRI); | 
|  | 1191 | CandLiveIns.addLiveOuts(OutlineBB); | 
|  | 1192 | for (const MachineInstr &MI : | 
|  | 1193 | reverse(make_range(Cand.front(), OutlineBB.end()))) | 
|  | 1194 | CandLiveIns.stepBackward(MI); | 
|  | 1195 |  | 
|  | 1196 | // The live-in set for the outlined function is the union of the live-ins | 
|  | 1197 | // from all the outlining points. | 
|  | 1198 | for (MCPhysReg Reg : make_range(CandLiveIns.begin(), CandLiveIns.end())) | 
|  | 1199 | LiveIns.addReg(Reg); | 
|  | 1200 | } | 
|  | 1201 | addLiveIns(MBB, LiveIns); | 
|  | 1202 |  | 
|  | 1203 | TII.buildOutlinedFrame(MBB, MF, OF); | 
|  | 1204 |  | 
| Jessica Paquette | a499c3c | 2018-01-19 21:21:49 +0000 | [diff] [blame] | 1205 | // If there's a DISubprogram associated with this outlined function, then | 
|  | 1206 | // emit debug info for the outlined function. | 
| Jessica Paquette | aa08732 | 2018-06-04 21:14:16 +0000 | [diff] [blame] | 1207 | if (DISubprogram *SP = getSubprogramOrNull(OF)) { | 
| Jessica Paquette | a499c3c | 2018-01-19 21:21:49 +0000 | [diff] [blame] | 1208 | // We have a DISubprogram. Get its DICompileUnit. | 
|  | 1209 | DICompileUnit *CU = SP->getUnit(); | 
|  | 1210 | DIBuilder DB(M, true, CU); | 
|  | 1211 | DIFile *Unit = SP->getFile(); | 
|  | 1212 | Mangler Mg; | 
| Jessica Paquette | cc06a78 | 2018-09-20 18:53:53 +0000 | [diff] [blame] | 1213 | // Get the mangled name of the function for the linkage name. | 
|  | 1214 | std::string Dummy; | 
|  | 1215 | llvm::raw_string_ostream MangledNameStream(Dummy); | 
|  | 1216 | Mg.getNameWithPrefix(MangledNameStream, F, false); | 
| Jessica Paquette | a499c3c | 2018-01-19 21:21:49 +0000 | [diff] [blame] | 1217 |  | 
| Jessica Paquette | cc06a78 | 2018-09-20 18:53:53 +0000 | [diff] [blame] | 1218 | DISubprogram *OutlinedSP = DB.createFunction( | 
|  | 1219 | Unit /* Context */, F->getName(), StringRef(MangledNameStream.str()), | 
|  | 1220 | Unit /* File */, | 
|  | 1221 | 0 /* Line 0 is reserved for compiler-generated code. */, | 
|  | 1222 | DB.createSubroutineType(DB.getOrCreateTypeArray(None)), /* void type */ | 
| Paul Robinson | cda5421 | 2018-11-19 18:29:28 +0000 | [diff] [blame] | 1223 | 0, /* Line 0 is reserved for compiler-generated code. */ | 
| Jessica Paquette | cc06a78 | 2018-09-20 18:53:53 +0000 | [diff] [blame] | 1224 | DINode::DIFlags::FlagArtificial /* Compiler-generated code. */, | 
| Paul Robinson | cda5421 | 2018-11-19 18:29:28 +0000 | [diff] [blame] | 1225 | /* Outlined code is optimized code by definition. */ | 
|  | 1226 | DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized); | 
| Jessica Paquette | a499c3c | 2018-01-19 21:21:49 +0000 | [diff] [blame] | 1227 |  | 
| Jessica Paquette | cc06a78 | 2018-09-20 18:53:53 +0000 | [diff] [blame] | 1228 | // Don't add any new variables to the subprogram. | 
|  | 1229 | DB.finalizeSubprogram(OutlinedSP); | 
| Jessica Paquette | a499c3c | 2018-01-19 21:21:49 +0000 | [diff] [blame] | 1230 |  | 
| Jessica Paquette | cc06a78 | 2018-09-20 18:53:53 +0000 | [diff] [blame] | 1231 | // Attach subprogram to the function. | 
|  | 1232 | F->setSubprogram(OutlinedSP); | 
| Jessica Paquette | a499c3c | 2018-01-19 21:21:49 +0000 | [diff] [blame] | 1233 | // We're done with the DIBuilder. | 
|  | 1234 | DB.finalize(); | 
|  | 1235 | } | 
|  | 1236 |  | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1237 | return &MF; | 
|  | 1238 | } | 
|  | 1239 |  | 
| Jessica Paquette | 4ae3b71 | 2018-12-05 22:50:26 +0000 | [diff] [blame] | 1240 | bool MachineOutliner::outline(Module &M, | 
|  | 1241 | std::vector<OutlinedFunction> &FunctionList, | 
| Puyan Lotfi | a51fc8d | 2019-10-28 15:10:21 -0400 | [diff] [blame] | 1242 | InstructionMapper &Mapper, | 
|  | 1243 | unsigned &OutlinedFunctionNum) { | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1244 |  | 
|  | 1245 | bool OutlinedSomething = false; | 
| Jessica Paquette | a3eb0fa | 2018-11-07 18:36:43 +0000 | [diff] [blame] | 1246 |  | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1247 | // Sort by benefit. The most beneficial functions should be outlined first. | 
| Fangrui Song | efd94c5 | 2019-04-23 14:51:27 +0000 | [diff] [blame] | 1248 | llvm::stable_sort(FunctionList, [](const OutlinedFunction &LHS, | 
|  | 1249 | const OutlinedFunction &RHS) { | 
|  | 1250 | return LHS.getBenefit() > RHS.getBenefit(); | 
|  | 1251 | }); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1252 |  | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1253 | // Walk over each function, outlining them as we go along. Functions are | 
|  | 1254 | // outlined greedily, based off the sort above. | 
|  | 1255 | for (OutlinedFunction &OF : FunctionList) { | 
|  | 1256 | // If we outlined something that overlapped with a candidate in a previous | 
|  | 1257 | // step, then we can't outline from it. | 
| Jessica Paquette | e18d6ff | 2018-12-05 23:24:22 +0000 | [diff] [blame] | 1258 | erase_if(OF.Candidates, [&Mapper](Candidate &C) { | 
| Jessica Paquette | d9d9309 | 2018-12-05 22:47:25 +0000 | [diff] [blame] | 1259 | return std::any_of( | 
| Jessica Paquette | e18d6ff | 2018-12-05 23:24:22 +0000 | [diff] [blame] | 1260 | Mapper.UnsignedVec.begin() + C.getStartIdx(), | 
|  | 1261 | Mapper.UnsignedVec.begin() + C.getEndIdx() + 1, | 
| Jessica Paquette | d9d9309 | 2018-12-05 22:47:25 +0000 | [diff] [blame] | 1262 | [](unsigned I) { return (I == static_cast<unsigned>(-1)); }); | 
| Jessica Paquette | 235d877 | 2018-12-05 22:27:38 +0000 | [diff] [blame] | 1263 | }); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1264 |  | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1265 | // If we made it unbeneficial to outline this function, skip it. | 
| Jessica Paquette | 85af63d | 2017-10-17 19:03:23 +0000 | [diff] [blame] | 1266 | if (OF.getBenefit() < 1) | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1267 | continue; | 
|  | 1268 |  | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1269 | // It's beneficial. Create the function and outline its sequence's | 
|  | 1270 | // occurrences. | 
|  | 1271 | OF.MF = createOutlinedFunction(M, OF, Mapper, OutlinedFunctionNum); | 
|  | 1272 | emitOutlinedFunctionRemark(OF); | 
|  | 1273 | FunctionsCreated++; | 
|  | 1274 | OutlinedFunctionNum++; // Created a function, move to the next name. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1275 | MachineFunction *MF = OF.MF; | 
|  | 1276 | const TargetSubtargetInfo &STI = MF->getSubtarget(); | 
|  | 1277 | const TargetInstrInfo &TII = *STI.getInstrInfo(); | 
|  | 1278 |  | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1279 | // Replace occurrences of the sequence with calls to the new function. | 
| Jessica Paquette | e18d6ff | 2018-12-05 23:24:22 +0000 | [diff] [blame] | 1280 | for (Candidate &C : OF.Candidates) { | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1281 | MachineBasicBlock &MBB = *C.getMBB(); | 
|  | 1282 | MachineBasicBlock::iterator StartIt = C.front(); | 
|  | 1283 | MachineBasicBlock::iterator EndIt = C.back(); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1284 |  | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1285 | // Insert the call. | 
|  | 1286 | auto CallInst = TII.insertOutlinedCall(M, MBB, StartIt, *MF, C); | 
| Jessica Paquette | 0b67249 | 2018-04-27 23:36:35 +0000 | [diff] [blame] | 1287 |  | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1288 | // If the caller tracks liveness, then we need to make sure that | 
|  | 1289 | // anything we outline doesn't break liveness assumptions. The outlined | 
|  | 1290 | // functions themselves currently don't track liveness, but we should | 
|  | 1291 | // make sure that the ranges we yank things out of aren't wrong. | 
|  | 1292 | if (MBB.getParent()->getProperties().hasProperty( | 
|  | 1293 | MachineFunctionProperties::Property::TracksLiveness)) { | 
| Jin Lin | fc6fda9 | 2020-03-05 13:54:58 -0800 | [diff] [blame] | 1294 | // The following code is to add implicit def operands to the call | 
| Djordje Todorovic | 71d3869 | 2019-06-27 13:10:29 +0000 | [diff] [blame] | 1295 | // instruction. It also updates call site information for moved | 
|  | 1296 | // code. | 
| Jin Lin | fc6fda9 | 2020-03-05 13:54:58 -0800 | [diff] [blame] | 1297 | SmallSet<Register, 2> UseRegs, DefRegs; | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1298 | // Copy over the defs in the outlined range. | 
|  | 1299 | // First inst in outlined range <-- Anything that's defined in this | 
|  | 1300 | // ...                           .. range has to be added as an | 
|  | 1301 | // implicit Last inst in outlined range  <-- def to the call | 
| Djordje Todorovic | 71d3869 | 2019-06-27 13:10:29 +0000 | [diff] [blame] | 1302 | // instruction. Also remove call site information for outlined block | 
| Jin Lin | fc6fda9 | 2020-03-05 13:54:58 -0800 | [diff] [blame] | 1303 | // of code. The exposed uses need to be copied in the outlined range. | 
| Puyan Lotfi | ffd5e12 | 2020-04-29 03:33:47 -0400 | [diff] [blame] | 1304 | for (MachineBasicBlock::reverse_iterator | 
|  | 1305 | Iter = EndIt.getReverse(), | 
|  | 1306 | Last = std::next(CallInst.getReverse()); | 
| Jin Lin | fc6fda9 | 2020-03-05 13:54:58 -0800 | [diff] [blame] | 1307 | Iter != Last; Iter++) { | 
|  | 1308 | MachineInstr *MI = &*Iter; | 
|  | 1309 | for (MachineOperand &MOP : MI->operands()) { | 
|  | 1310 | // Skip over anything that isn't a register. | 
|  | 1311 | if (!MOP.isReg()) | 
|  | 1312 | continue; | 
|  | 1313 |  | 
|  | 1314 | if (MOP.isDef()) { | 
|  | 1315 | // Introduce DefRegs set to skip the redundant register. | 
|  | 1316 | DefRegs.insert(MOP.getReg()); | 
|  | 1317 | if (UseRegs.count(MOP.getReg())) | 
|  | 1318 | // Since the regiester is modeled as defined, | 
|  | 1319 | // it is not necessary to be put in use register set. | 
|  | 1320 | UseRegs.erase(MOP.getReg()); | 
|  | 1321 | } else if (!MOP.isUndef()) { | 
|  | 1322 | // Any register which is not undefined should | 
|  | 1323 | // be put in the use register set. | 
|  | 1324 | UseRegs.insert(MOP.getReg()); | 
|  | 1325 | } | 
|  | 1326 | } | 
|  | 1327 | if (MI->isCandidateForCallSiteEntry()) | 
|  | 1328 | MI->getMF()->eraseCallSiteInfo(MI); | 
|  | 1329 | } | 
|  | 1330 |  | 
|  | 1331 | for (const Register &I : DefRegs) | 
| Puyan Lotfi | ffd5e12 | 2020-04-29 03:33:47 -0400 | [diff] [blame] | 1332 | // If it's a def, add it to the call instruction. | 
|  | 1333 | CallInst->addOperand( | 
|  | 1334 | MachineOperand::CreateReg(I, true, /* isDef = true */ | 
|  | 1335 | true /* isImp = true */)); | 
| Jin Lin | fc6fda9 | 2020-03-05 13:54:58 -0800 | [diff] [blame] | 1336 |  | 
|  | 1337 | for (const Register &I : UseRegs) | 
|  | 1338 | // If it's a exposed use, add it to the call instruction. | 
|  | 1339 | CallInst->addOperand( | 
|  | 1340 | MachineOperand::CreateReg(I, false, /* isDef = false */ | 
|  | 1341 | true /* isImp = true */)); | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1342 | } | 
|  | 1343 |  | 
|  | 1344 | // Erase from the point after where the call was inserted up to, and | 
|  | 1345 | // including, the final instruction in the sequence. | 
|  | 1346 | // Erase needs one past the end, so we need std::next there too. | 
|  | 1347 | MBB.erase(std::next(StartIt), std::next(EndIt)); | 
| Jessica Paquette | 235d877 | 2018-12-05 22:27:38 +0000 | [diff] [blame] | 1348 |  | 
| Jessica Paquette | d9d9309 | 2018-12-05 22:47:25 +0000 | [diff] [blame] | 1349 | // Keep track of what we removed by marking them all as -1. | 
| Jessica Paquette | 235d877 | 2018-12-05 22:27:38 +0000 | [diff] [blame] | 1350 | std::for_each(Mapper.UnsignedVec.begin() + C.getStartIdx(), | 
|  | 1351 | Mapper.UnsignedVec.begin() + C.getEndIdx() + 1, | 
| Jessica Paquette | d9d9309 | 2018-12-05 22:47:25 +0000 | [diff] [blame] | 1352 | [](unsigned &I) { I = static_cast<unsigned>(-1); }); | 
| Jessica Paquette | 962b3ae | 2018-12-05 21:36:04 +0000 | [diff] [blame] | 1353 | OutlinedSomething = true; | 
|  | 1354 |  | 
|  | 1355 | // Statistics. | 
|  | 1356 | NumOutlined++; | 
| Jessica Paquette | 0b67249 | 2018-04-27 23:36:35 +0000 | [diff] [blame] | 1357 | } | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1358 | } | 
|  | 1359 |  | 
| Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 1360 | LLVM_DEBUG(dbgs() << "OutlinedSomething = " << OutlinedSomething << "\n";); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1361 | return OutlinedSomething; | 
|  | 1362 | } | 
|  | 1363 |  | 
| Jessica Paquette | 050d1ac | 2018-09-11 16:33:46 +0000 | [diff] [blame] | 1364 | void MachineOutliner::populateMapper(InstructionMapper &Mapper, Module &M, | 
|  | 1365 | MachineModuleInfo &MMI) { | 
| Jessica Paquette | df82274 | 2018-03-22 21:07:09 +0000 | [diff] [blame] | 1366 | // Build instruction mappings for each function in the module. Start by | 
|  | 1367 | // iterating over each Function in M. | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1368 | for (Function &F : M) { | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1369 |  | 
| Jessica Paquette | df82274 | 2018-03-22 21:07:09 +0000 | [diff] [blame] | 1370 | // If there's nothing in F, then there's no reason to try and outline from | 
|  | 1371 | // it. | 
|  | 1372 | if (F.empty()) | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1373 | continue; | 
|  | 1374 |  | 
| Jessica Paquette | df82274 | 2018-03-22 21:07:09 +0000 | [diff] [blame] | 1375 | // There's something in F. Check if it has a MachineFunction associated with | 
|  | 1376 | // it. | 
|  | 1377 | MachineFunction *MF = MMI.getMachineFunction(F); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1378 |  | 
| Jessica Paquette | df82274 | 2018-03-22 21:07:09 +0000 | [diff] [blame] | 1379 | // If it doesn't, then there's nothing to outline from. Move to the next | 
|  | 1380 | // Function. | 
|  | 1381 | if (!MF) | 
|  | 1382 | continue; | 
|  | 1383 |  | 
| Eli Friedman | da08078 | 2018-08-01 00:37:20 +0000 | [diff] [blame] | 1384 | const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); | 
|  | 1385 |  | 
| Jessica Paquette | 8bda188 | 2018-06-30 03:56:03 +0000 | [diff] [blame] | 1386 | if (!RunOnAllFunctions && !TII->shouldOutlineFromFunctionByDefault(*MF)) | 
|  | 1387 | continue; | 
|  | 1388 |  | 
| Jessica Paquette | df82274 | 2018-03-22 21:07:09 +0000 | [diff] [blame] | 1389 | // We have a MachineFunction. Ask the target if it's suitable for outlining. | 
|  | 1390 | // If it isn't, then move on to the next Function in the module. | 
|  | 1391 | if (!TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs)) | 
|  | 1392 | continue; | 
|  | 1393 |  | 
|  | 1394 | // We have a function suitable for outlining. Iterate over every | 
|  | 1395 | // MachineBasicBlock in MF and try to map its instructions to a list of | 
|  | 1396 | // unsigned integers. | 
|  | 1397 | for (MachineBasicBlock &MBB : *MF) { | 
|  | 1398 | // If there isn't anything in MBB, then there's no point in outlining from | 
|  | 1399 | // it. | 
| Jessica Paquette | b320ca2 | 2018-09-20 21:53:25 +0000 | [diff] [blame] | 1400 | // If there are fewer than 2 instructions in the MBB, then it can't ever | 
|  | 1401 | // contain something worth outlining. | 
|  | 1402 | // FIXME: This should be based off of the maximum size in B of an outlined | 
|  | 1403 | // call versus the size in B of the MBB. | 
|  | 1404 | if (MBB.empty() || MBB.size() < 2) | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1405 | continue; | 
|  | 1406 |  | 
| Jessica Paquette | df82274 | 2018-03-22 21:07:09 +0000 | [diff] [blame] | 1407 | // Check if MBB could be the target of an indirect branch. If it is, then | 
|  | 1408 | // we don't want to outline from it. | 
|  | 1409 | if (MBB.hasAddressTaken()) | 
|  | 1410 | continue; | 
|  | 1411 |  | 
|  | 1412 | // MBB is suitable for outlining. Map it to a list of unsigneds. | 
| Eli Friedman | da08078 | 2018-08-01 00:37:20 +0000 | [diff] [blame] | 1413 | Mapper.convertToUnsignedVec(MBB, *TII); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1414 | } | 
|  | 1415 | } | 
| Jessica Paquette | 050d1ac | 2018-09-11 16:33:46 +0000 | [diff] [blame] | 1416 | } | 
|  | 1417 |  | 
| Jessica Paquette | 2386eab | 2018-09-11 23:05:34 +0000 | [diff] [blame] | 1418 | void MachineOutliner::initSizeRemarkInfo( | 
|  | 1419 | const Module &M, const MachineModuleInfo &MMI, | 
|  | 1420 | StringMap<unsigned> &FunctionToInstrCount) { | 
|  | 1421 | // Collect instruction counts for every function. We'll use this to emit | 
|  | 1422 | // per-function size remarks later. | 
|  | 1423 | for (const Function &F : M) { | 
|  | 1424 | MachineFunction *MF = MMI.getMachineFunction(F); | 
|  | 1425 |  | 
|  | 1426 | // We only care about MI counts here. If there's no MachineFunction at this | 
|  | 1427 | // point, then there won't be after the outliner runs, so let's move on. | 
|  | 1428 | if (!MF) | 
|  | 1429 | continue; | 
|  | 1430 | FunctionToInstrCount[F.getName().str()] = MF->getInstructionCount(); | 
|  | 1431 | } | 
|  | 1432 | } | 
|  | 1433 |  | 
|  | 1434 | void MachineOutliner::emitInstrCountChangedRemark( | 
|  | 1435 | const Module &M, const MachineModuleInfo &MMI, | 
|  | 1436 | const StringMap<unsigned> &FunctionToInstrCount) { | 
|  | 1437 | // Iterate over each function in the module and emit remarks. | 
|  | 1438 | // Note that we won't miss anything by doing this, because the outliner never | 
|  | 1439 | // deletes functions. | 
|  | 1440 | for (const Function &F : M) { | 
|  | 1441 | MachineFunction *MF = MMI.getMachineFunction(F); | 
|  | 1442 |  | 
|  | 1443 | // The outliner never deletes functions. If we don't have a MF here, then we | 
|  | 1444 | // didn't have one prior to outlining either. | 
|  | 1445 | if (!MF) | 
|  | 1446 | continue; | 
|  | 1447 |  | 
| Benjamin Kramer | adcd026 | 2020-01-28 20:23:46 +0100 | [diff] [blame] | 1448 | std::string Fname = std::string(F.getName()); | 
| Jessica Paquette | 2386eab | 2018-09-11 23:05:34 +0000 | [diff] [blame] | 1449 | unsigned FnCountAfter = MF->getInstructionCount(); | 
|  | 1450 | unsigned FnCountBefore = 0; | 
|  | 1451 |  | 
|  | 1452 | // Check if the function was recorded before. | 
|  | 1453 | auto It = FunctionToInstrCount.find(Fname); | 
|  | 1454 |  | 
|  | 1455 | // Did we have a previously-recorded size? If yes, then set FnCountBefore | 
|  | 1456 | // to that. | 
|  | 1457 | if (It != FunctionToInstrCount.end()) | 
|  | 1458 | FnCountBefore = It->second; | 
|  | 1459 |  | 
|  | 1460 | // Compute the delta and emit a remark if there was a change. | 
|  | 1461 | int64_t FnDelta = static_cast<int64_t>(FnCountAfter) - | 
|  | 1462 | static_cast<int64_t>(FnCountBefore); | 
|  | 1463 | if (FnDelta == 0) | 
|  | 1464 | continue; | 
|  | 1465 |  | 
|  | 1466 | MachineOptimizationRemarkEmitter MORE(*MF, nullptr); | 
|  | 1467 | MORE.emit([&]() { | 
|  | 1468 | MachineOptimizationRemarkAnalysis R("size-info", "FunctionMISizeChange", | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 1469 | DiagnosticLocation(), &MF->front()); | 
| Jessica Paquette | 2386eab | 2018-09-11 23:05:34 +0000 | [diff] [blame] | 1470 | R << DiagnosticInfoOptimizationBase::Argument("Pass", "Machine Outliner") | 
|  | 1471 | << ": Function: " | 
|  | 1472 | << DiagnosticInfoOptimizationBase::Argument("Function", F.getName()) | 
|  | 1473 | << ": MI instruction count changed from " | 
|  | 1474 | << DiagnosticInfoOptimizationBase::Argument("MIInstrsBefore", | 
|  | 1475 | FnCountBefore) | 
|  | 1476 | << " to " | 
|  | 1477 | << DiagnosticInfoOptimizationBase::Argument("MIInstrsAfter", | 
|  | 1478 | FnCountAfter) | 
|  | 1479 | << "; Delta: " | 
|  | 1480 | << DiagnosticInfoOptimizationBase::Argument("Delta", FnDelta); | 
|  | 1481 | return R; | 
|  | 1482 | }); | 
|  | 1483 | } | 
|  | 1484 | } | 
|  | 1485 |  | 
| Puyan Lotfi | ffd5e12 | 2020-04-29 03:33:47 -0400 | [diff] [blame] | 1486 | bool MachineOutliner::runOnModule(Module &M) { | 
| Jessica Paquette | 050d1ac | 2018-09-11 16:33:46 +0000 | [diff] [blame] | 1487 | // Check if there's anything in the module. If it's empty, then there's | 
|  | 1488 | // nothing to outline. | 
|  | 1489 | if (M.empty()) | 
|  | 1490 | return false; | 
|  | 1491 |  | 
| Puyan Lotfi | a51fc8d | 2019-10-28 15:10:21 -0400 | [diff] [blame] | 1492 | // Number to append to the current outlined function. | 
|  | 1493 | unsigned OutlinedFunctionNum = 0; | 
|  | 1494 |  | 
| Puyan Lotfi | ffd5e12 | 2020-04-29 03:33:47 -0400 | [diff] [blame] | 1495 | OutlineRepeatedNum = 0; | 
| Puyan Lotfi | a51fc8d | 2019-10-28 15:10:21 -0400 | [diff] [blame] | 1496 | if (!doOutline(M, OutlinedFunctionNum)) | 
|  | 1497 | return false; | 
| Puyan Lotfi | ffd5e12 | 2020-04-29 03:33:47 -0400 | [diff] [blame] | 1498 |  | 
|  | 1499 | for (unsigned I = 0; I < OutlinerReruns; ++I) { | 
|  | 1500 | OutlinedFunctionNum = 0; | 
|  | 1501 | OutlineRepeatedNum++; | 
|  | 1502 | if (!doOutline(M, OutlinedFunctionNum)) { | 
|  | 1503 | LLVM_DEBUG({ | 
|  | 1504 | dbgs() << "Did not outline on iteration " << I + 2 << " out of " | 
|  | 1505 | << OutlinerReruns + 1 << "\n"; | 
|  | 1506 | }); | 
|  | 1507 | break; | 
|  | 1508 | } | 
|  | 1509 | } | 
|  | 1510 |  | 
| Puyan Lotfi | a51fc8d | 2019-10-28 15:10:21 -0400 | [diff] [blame] | 1511 | return true; | 
|  | 1512 | } | 
|  | 1513 |  | 
|  | 1514 | bool MachineOutliner::doOutline(Module &M, unsigned &OutlinedFunctionNum) { | 
| Yuanfang Chen | cc382cf | 2019-09-30 17:54:50 +0000 | [diff] [blame] | 1515 | MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI(); | 
| Jessica Paquette | 050d1ac | 2018-09-11 16:33:46 +0000 | [diff] [blame] | 1516 |  | 
|  | 1517 | // If the user passed -enable-machine-outliner=always or | 
|  | 1518 | // -enable-machine-outliner, the pass will run on all functions in the module. | 
|  | 1519 | // Otherwise, if the target supports default outlining, it will run on all | 
|  | 1520 | // functions deemed by the target to be worth outlining from by default. Tell | 
|  | 1521 | // the user how the outliner is running. | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 1522 | LLVM_DEBUG({ | 
| Jessica Paquette | 050d1ac | 2018-09-11 16:33:46 +0000 | [diff] [blame] | 1523 | dbgs() << "Machine Outliner: Running on "; | 
|  | 1524 | if (RunOnAllFunctions) | 
|  | 1525 | dbgs() << "all functions"; | 
|  | 1526 | else | 
|  | 1527 | dbgs() << "target-default functions"; | 
| Puyan Lotfi | 6b7615a | 2019-10-28 17:57:51 -0400 | [diff] [blame] | 1528 | dbgs() << "\n"; | 
|  | 1529 | }); | 
| Jessica Paquette | 050d1ac | 2018-09-11 16:33:46 +0000 | [diff] [blame] | 1530 |  | 
|  | 1531 | // If the user specifies that they want to outline from linkonceodrs, set | 
|  | 1532 | // it here. | 
|  | 1533 | OutlineFromLinkOnceODRs = EnableLinkOnceODROutlining; | 
|  | 1534 | InstructionMapper Mapper; | 
|  | 1535 |  | 
|  | 1536 | // Prepare instruction mappings for the suffix tree. | 
|  | 1537 | populateMapper(Mapper, M, MMI); | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1538 | std::vector<OutlinedFunction> FunctionList; | 
|  | 1539 |  | 
| Jessica Paquette | acffa28 | 2017-03-23 21:27:38 +0000 | [diff] [blame] | 1540 | // Find all of the outlining candidates. | 
| Jessica Paquette | ce3a2dc | 2018-12-05 23:39:07 +0000 | [diff] [blame] | 1541 | findCandidates(Mapper, FunctionList); | 
| Jessica Paquette | acffa28 | 2017-03-23 21:27:38 +0000 | [diff] [blame] | 1542 |  | 
| Jessica Paquette | 2386eab | 2018-09-11 23:05:34 +0000 | [diff] [blame] | 1543 | // If we've requested size remarks, then collect the MI counts of every | 
|  | 1544 | // function before outlining, and the MI counts after outlining. | 
|  | 1545 | // FIXME: This shouldn't be in the outliner at all; it should ultimately be | 
|  | 1546 | // the pass manager's responsibility. | 
|  | 1547 | // This could pretty easily be placed in outline instead, but because we | 
|  | 1548 | // really ultimately *don't* want this here, it's done like this for now | 
|  | 1549 | // instead. | 
|  | 1550 |  | 
|  | 1551 | // Check if we want size remarks. | 
|  | 1552 | bool ShouldEmitSizeRemarks = M.shouldEmitInstrCountChangedRemark(); | 
|  | 1553 | StringMap<unsigned> FunctionToInstrCount; | 
|  | 1554 | if (ShouldEmitSizeRemarks) | 
|  | 1555 | initSizeRemarkInfo(M, MMI, FunctionToInstrCount); | 
|  | 1556 |  | 
| Jessica Paquette | acffa28 | 2017-03-23 21:27:38 +0000 | [diff] [blame] | 1557 | // Outline each of the candidates and return true if something was outlined. | 
| Puyan Lotfi | a51fc8d | 2019-10-28 15:10:21 -0400 | [diff] [blame] | 1558 | bool OutlinedSomething = | 
|  | 1559 | outline(M, FunctionList, Mapper, OutlinedFunctionNum); | 
| Jessica Paquette | 729e686 | 2018-01-18 00:00:58 +0000 | [diff] [blame] | 1560 |  | 
| Jessica Paquette | 2386eab | 2018-09-11 23:05:34 +0000 | [diff] [blame] | 1561 | // If we outlined something, we definitely changed the MI count of the | 
|  | 1562 | // module. If we've asked for size remarks, then output them. | 
|  | 1563 | // FIXME: This should be in the pass manager. | 
|  | 1564 | if (ShouldEmitSizeRemarks && OutlinedSomething) | 
|  | 1565 | emitInstrCountChangedRemark(M, MMI, FunctionToInstrCount); | 
|  | 1566 |  | 
| Puyan Lotfi | ffd5e12 | 2020-04-29 03:33:47 -0400 | [diff] [blame] | 1567 | LLVM_DEBUG({ | 
|  | 1568 | if (!OutlinedSomething) | 
|  | 1569 | dbgs() << "Stopped outlining at iteration " << OutlineRepeatedNum | 
|  | 1570 | << " because no changes were found.\n"; | 
|  | 1571 | }); | 
|  | 1572 |  | 
| Jessica Paquette | 729e686 | 2018-01-18 00:00:58 +0000 | [diff] [blame] | 1573 | return OutlinedSomething; | 
| Jessica Paquette | 596f483 | 2017-03-06 21:31:18 +0000 | [diff] [blame] | 1574 | } |