MachineOutliner.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. //===---- MachineOutliner.cpp - Outline instructions -----------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \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. ///
  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
  27. /// * buildOutlinedFrame
  28. /// * insertOutlinedCall
  29. /// * isFunctionSafeToOutlineFrom
  30. ///
  31. /// in order to make use of the MachineOutliner.
  32. ///
  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. //===----------------------------------------------------------------------===//
  57. #include "llvm/CodeGen/MachineOutliner.h"
  58. #include "llvm/ADT/DenseMap.h"
  59. #include "llvm/ADT/SmallSet.h"
  60. #include "llvm/ADT/Statistic.h"
  61. #include "llvm/ADT/Twine.h"
  62. #include "llvm/CodeGen/MachineModuleInfo.h"
  63. #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
  64. #include "llvm/CodeGen/Passes.h"
  65. #include "llvm/CodeGen/TargetInstrInfo.h"
  66. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  67. #include "llvm/IR/DIBuilder.h"
  68. #include "llvm/IR/IRBuilder.h"
  69. #include "llvm/IR/Mangler.h"
  70. #include "llvm/InitializePasses.h"
  71. #include "llvm/Support/CommandLine.h"
  72. #include "llvm/Support/Debug.h"
  73. #include "llvm/Support/SuffixTree.h"
  74. #include "llvm/Support/raw_ostream.h"
  75. #include <functional>
  76. #include <tuple>
  77. #include <vector>
  78. #define DEBUG_TYPE "machine-outliner"
  79. using namespace llvm;
  80. using namespace ore;
  81. using namespace outliner;
  82. STATISTIC(NumOutlined, "Number of candidates outlined");
  83. STATISTIC(FunctionsCreated, "Number of functions created");
  84. // Set to true if the user wants the outliner to run on linkonceodr linkage
  85. // functions. This is false by default because the linker can dedupe linkonceodr
  86. // functions. Since the outliner is confined to a single module (modulo LTO),
  87. // this is off by default. It should, however, be the default behaviour in
  88. // LTO.
  89. static cl::opt<bool> EnableLinkOnceODROutlining(
  90. "enable-linkonceodr-outlining", cl::Hidden,
  91. cl::desc("Enable the machine outliner on linkonceodr functions"),
  92. cl::init(false));
  93. /// Number of times to re-run the outliner. This is not the total number of runs
  94. /// as the outliner will run at least one time. The default value is set to 0,
  95. /// meaning the outliner will run one time and rerun zero times after that.
  96. static cl::opt<unsigned> OutlinerReruns(
  97. "machine-outliner-reruns", cl::init(0), cl::Hidden,
  98. cl::desc(
  99. "Number of times to rerun the outliner after the initial outline"));
  100. namespace {
  101. /// Maps \p MachineInstrs to unsigned integers and stores the mappings.
  102. struct InstructionMapper {
  103. /// The next available integer to assign to a \p MachineInstr that
  104. /// cannot be outlined.
  105. ///
  106. /// Set to -3 for compatability with \p DenseMapInfo<unsigned>.
  107. unsigned IllegalInstrNumber = -3;
  108. /// The next available integer to assign to a \p MachineInstr that can
  109. /// be outlined.
  110. unsigned LegalInstrNumber = 0;
  111. /// Correspondence from \p MachineInstrs to unsigned integers.
  112. DenseMap<MachineInstr *, unsigned, MachineInstrExpressionTrait>
  113. InstructionIntegerMap;
  114. /// Correspondence between \p MachineBasicBlocks and target-defined flags.
  115. DenseMap<MachineBasicBlock *, unsigned> MBBFlagsMap;
  116. /// The vector of unsigned integers that the module is mapped to.
  117. std::vector<unsigned> UnsignedVec;
  118. /// Stores the location of the instruction associated with the integer
  119. /// at index i in \p UnsignedVec for each index i.
  120. std::vector<MachineBasicBlock::iterator> InstrList;
  121. // Set if we added an illegal number in the previous step.
  122. // Since each illegal number is unique, we only need one of them between
  123. // each range of legal numbers. This lets us make sure we don't add more
  124. // than one illegal number per range.
  125. bool AddedIllegalLastTime = false;
  126. /// Maps \p *It to a legal integer.
  127. ///
  128. /// Updates \p CanOutlineWithPrevInstr, \p HaveLegalRange, \p InstrListForMBB,
  129. /// \p UnsignedVecForMBB, \p InstructionIntegerMap, and \p LegalInstrNumber.
  130. ///
  131. /// \returns The integer that \p *It was mapped to.
  132. unsigned mapToLegalUnsigned(
  133. MachineBasicBlock::iterator &It, bool &CanOutlineWithPrevInstr,
  134. bool &HaveLegalRange, unsigned &NumLegalInBlock,
  135. std::vector<unsigned> &UnsignedVecForMBB,
  136. std::vector<MachineBasicBlock::iterator> &InstrListForMBB) {
  137. // We added something legal, so we should unset the AddedLegalLastTime
  138. // flag.
  139. AddedIllegalLastTime = false;
  140. // If we have at least two adjacent legal instructions (which may have
  141. // invisible instructions in between), remember that.
  142. if (CanOutlineWithPrevInstr)
  143. HaveLegalRange = true;
  144. CanOutlineWithPrevInstr = true;
  145. // Keep track of the number of legal instructions we insert.
  146. NumLegalInBlock++;
  147. // Get the integer for this instruction or give it the current
  148. // LegalInstrNumber.
  149. InstrListForMBB.push_back(It);
  150. MachineInstr &MI = *It;
  151. bool WasInserted;
  152. DenseMap<MachineInstr *, unsigned, MachineInstrExpressionTrait>::iterator
  153. ResultIt;
  154. std::tie(ResultIt, WasInserted) =
  155. InstructionIntegerMap.insert(std::make_pair(&MI, LegalInstrNumber));
  156. unsigned MINumber = ResultIt->second;
  157. // There was an insertion.
  158. if (WasInserted)
  159. LegalInstrNumber++;
  160. UnsignedVecForMBB.push_back(MINumber);
  161. // Make sure we don't overflow or use any integers reserved by the DenseMap.
  162. if (LegalInstrNumber >= IllegalInstrNumber)
  163. report_fatal_error("Instruction mapping overflow!");
  164. assert(LegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() &&
  165. "Tried to assign DenseMap tombstone or empty key to instruction.");
  166. assert(LegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() &&
  167. "Tried to assign DenseMap tombstone or empty key to instruction.");
  168. return MINumber;
  169. }
  170. /// Maps \p *It to an illegal integer.
  171. ///
  172. /// Updates \p InstrListForMBB, \p UnsignedVecForMBB, and \p
  173. /// IllegalInstrNumber.
  174. ///
  175. /// \returns The integer that \p *It was mapped to.
  176. unsigned mapToIllegalUnsigned(
  177. MachineBasicBlock::iterator &It, bool &CanOutlineWithPrevInstr,
  178. std::vector<unsigned> &UnsignedVecForMBB,
  179. std::vector<MachineBasicBlock::iterator> &InstrListForMBB) {
  180. // Can't outline an illegal instruction. Set the flag.
  181. CanOutlineWithPrevInstr = false;
  182. // Only add one illegal number per range of legal numbers.
  183. if (AddedIllegalLastTime)
  184. return IllegalInstrNumber;
  185. // Remember that we added an illegal number last time.
  186. AddedIllegalLastTime = true;
  187. unsigned MINumber = IllegalInstrNumber;
  188. InstrListForMBB.push_back(It);
  189. UnsignedVecForMBB.push_back(IllegalInstrNumber);
  190. IllegalInstrNumber--;
  191. assert(LegalInstrNumber < IllegalInstrNumber &&
  192. "Instruction mapping overflow!");
  193. assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() &&
  194. "IllegalInstrNumber cannot be DenseMap tombstone or empty key!");
  195. assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() &&
  196. "IllegalInstrNumber cannot be DenseMap tombstone or empty key!");
  197. return MINumber;
  198. }
  199. /// Transforms a \p MachineBasicBlock into a \p vector of \p unsigneds
  200. /// and appends it to \p UnsignedVec and \p InstrList.
  201. ///
  202. /// Two instructions are assigned the same integer if they are identical.
  203. /// If an instruction is deemed unsafe to outline, then it will be assigned an
  204. /// unique integer. The resulting mapping is placed into a suffix tree and
  205. /// queried for candidates.
  206. ///
  207. /// \param MBB The \p MachineBasicBlock to be translated into integers.
  208. /// \param TII \p TargetInstrInfo for the function.
  209. void convertToUnsignedVec(MachineBasicBlock &MBB,
  210. const TargetInstrInfo &TII) {
  211. unsigned Flags = 0;
  212. // Don't even map in this case.
  213. if (!TII.isMBBSafeToOutlineFrom(MBB, Flags))
  214. return;
  215. // Store info for the MBB for later outlining.
  216. MBBFlagsMap[&MBB] = Flags;
  217. MachineBasicBlock::iterator It = MBB.begin();
  218. // The number of instructions in this block that will be considered for
  219. // outlining.
  220. unsigned NumLegalInBlock = 0;
  221. // True if we have at least two legal instructions which aren't separated
  222. // by an illegal instruction.
  223. bool HaveLegalRange = false;
  224. // True if we can perform outlining given the last mapped (non-invisible)
  225. // instruction. This lets us know if we have a legal range.
  226. bool CanOutlineWithPrevInstr = false;
  227. // FIXME: Should this all just be handled in the target, rather than using
  228. // repeated calls to getOutliningType?
  229. std::vector<unsigned> UnsignedVecForMBB;
  230. std::vector<MachineBasicBlock::iterator> InstrListForMBB;
  231. for (MachineBasicBlock::iterator Et = MBB.end(); It != Et; ++It) {
  232. // Keep track of where this instruction is in the module.
  233. switch (TII.getOutliningType(It, Flags)) {
  234. case InstrType::Illegal:
  235. mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
  236. InstrListForMBB);
  237. break;
  238. case InstrType::Legal:
  239. mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
  240. NumLegalInBlock, UnsignedVecForMBB, InstrListForMBB);
  241. break;
  242. case InstrType::LegalTerminator:
  243. mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
  244. NumLegalInBlock, UnsignedVecForMBB, InstrListForMBB);
  245. // The instruction also acts as a terminator, so we have to record that
  246. // in the string.
  247. mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
  248. InstrListForMBB);
  249. break;
  250. case InstrType::Invisible:
  251. // Normally this is set by mapTo(Blah)Unsigned, but we just want to
  252. // skip this instruction. So, unset the flag here.
  253. AddedIllegalLastTime = false;
  254. break;
  255. }
  256. }
  257. // Are there enough legal instructions in the block for outlining to be
  258. // possible?
  259. if (HaveLegalRange) {
  260. // After we're done every insertion, uniquely terminate this part of the
  261. // "string". This makes sure we won't match across basic block or function
  262. // boundaries since the "end" is encoded uniquely and thus appears in no
  263. // repeated substring.
  264. mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
  265. InstrListForMBB);
  266. llvm::append_range(InstrList, InstrListForMBB);
  267. llvm::append_range(UnsignedVec, UnsignedVecForMBB);
  268. }
  269. }
  270. InstructionMapper() {
  271. // Make sure that the implementation of DenseMapInfo<unsigned> hasn't
  272. // changed.
  273. assert(DenseMapInfo<unsigned>::getEmptyKey() == (unsigned)-1 &&
  274. "DenseMapInfo<unsigned>'s empty key isn't -1!");
  275. assert(DenseMapInfo<unsigned>::getTombstoneKey() == (unsigned)-2 &&
  276. "DenseMapInfo<unsigned>'s tombstone key isn't -2!");
  277. }
  278. };
  279. /// An interprocedural pass which finds repeated sequences of
  280. /// instructions and replaces them with calls to functions.
  281. ///
  282. /// Each instruction is mapped to an unsigned integer and placed in a string.
  283. /// The resulting mapping is then placed in a \p SuffixTree. The \p SuffixTree
  284. /// is then repeatedly queried for repeated sequences of instructions. Each
  285. /// non-overlapping repeated sequence is then placed in its own
  286. /// \p MachineFunction and each instance is then replaced with a call to that
  287. /// function.
  288. struct MachineOutliner : public ModulePass {
  289. static char ID;
  290. /// Set to true if the outliner should consider functions with
  291. /// linkonceodr linkage.
  292. bool OutlineFromLinkOnceODRs = false;
  293. /// The current repeat number of machine outlining.
  294. unsigned OutlineRepeatedNum = 0;
  295. /// Set to true if the outliner should run on all functions in the module
  296. /// considered safe for outlining.
  297. /// Set to true by default for compatibility with llc's -run-pass option.
  298. /// Set when the pass is constructed in TargetPassConfig.
  299. bool RunOnAllFunctions = true;
  300. StringRef getPassName() const override { return "Machine Outliner"; }
  301. void getAnalysisUsage(AnalysisUsage &AU) const override {
  302. AU.addRequired<MachineModuleInfoWrapperPass>();
  303. AU.addPreserved<MachineModuleInfoWrapperPass>();
  304. AU.setPreservesAll();
  305. ModulePass::getAnalysisUsage(AU);
  306. }
  307. MachineOutliner() : ModulePass(ID) {
  308. initializeMachineOutlinerPass(*PassRegistry::getPassRegistry());
  309. }
  310. /// Remark output explaining that not outlining a set of candidates would be
  311. /// better than outlining that set.
  312. void emitNotOutliningCheaperRemark(
  313. unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq,
  314. OutlinedFunction &OF);
  315. /// Remark output explaining that a function was outlined.
  316. void emitOutlinedFunctionRemark(OutlinedFunction &OF);
  317. /// Find all repeated substrings that satisfy the outlining cost model by
  318. /// constructing a suffix tree.
  319. ///
  320. /// If a substring appears at least twice, then it must be represented by
  321. /// an internal node which appears in at least two suffixes. Each suffix
  322. /// is represented by a leaf node. To do this, we visit each internal node
  323. /// in the tree, using the leaf children of each internal node. If an
  324. /// internal node represents a beneficial substring, then we use each of
  325. /// its leaf children to find the locations of its substring.
  326. ///
  327. /// \param Mapper Contains outlining mapping information.
  328. /// \param[out] FunctionList Filled with a list of \p OutlinedFunctions
  329. /// each type of candidate.
  330. void findCandidates(InstructionMapper &Mapper,
  331. std::vector<OutlinedFunction> &FunctionList);
  332. /// Replace the sequences of instructions represented by \p OutlinedFunctions
  333. /// with calls to functions.
  334. ///
  335. /// \param M The module we are outlining from.
  336. /// \param FunctionList A list of functions to be inserted into the module.
  337. /// \param Mapper Contains the instruction mappings for the module.
  338. bool outline(Module &M, std::vector<OutlinedFunction> &FunctionList,
  339. InstructionMapper &Mapper, unsigned &OutlinedFunctionNum);
  340. /// Creates a function for \p OF and inserts it into the module.
  341. MachineFunction *createOutlinedFunction(Module &M, OutlinedFunction &OF,
  342. InstructionMapper &Mapper,
  343. unsigned Name);
  344. /// Calls 'doOutline()' 1 + OutlinerReruns times.
  345. bool runOnModule(Module &M) override;
  346. /// Construct a suffix tree on the instructions in \p M and outline repeated
  347. /// strings from that tree.
  348. bool doOutline(Module &M, unsigned &OutlinedFunctionNum);
  349. /// Return a DISubprogram for OF if one exists, and null otherwise. Helper
  350. /// function for remark emission.
  351. DISubprogram *getSubprogramOrNull(const OutlinedFunction &OF) {
  352. for (const Candidate &C : OF.Candidates)
  353. if (MachineFunction *MF = C.getMF())
  354. if (DISubprogram *SP = MF->getFunction().getSubprogram())
  355. return SP;
  356. return nullptr;
  357. }
  358. /// Populate and \p InstructionMapper with instruction-to-integer mappings.
  359. /// These are used to construct a suffix tree.
  360. void populateMapper(InstructionMapper &Mapper, Module &M,
  361. MachineModuleInfo &MMI);
  362. /// Initialize information necessary to output a size remark.
  363. /// FIXME: This should be handled by the pass manager, not the outliner.
  364. /// FIXME: This is nearly identical to the initSizeRemarkInfo in the legacy
  365. /// pass manager.
  366. void initSizeRemarkInfo(const Module &M, const MachineModuleInfo &MMI,
  367. StringMap<unsigned> &FunctionToInstrCount);
  368. /// Emit the remark.
  369. // FIXME: This should be handled by the pass manager, not the outliner.
  370. void
  371. emitInstrCountChangedRemark(const Module &M, const MachineModuleInfo &MMI,
  372. const StringMap<unsigned> &FunctionToInstrCount);
  373. };
  374. } // Anonymous namespace.
  375. char MachineOutliner::ID = 0;
  376. namespace llvm {
  377. ModulePass *createMachineOutlinerPass(bool RunOnAllFunctions) {
  378. MachineOutliner *OL = new MachineOutliner();
  379. OL->RunOnAllFunctions = RunOnAllFunctions;
  380. return OL;
  381. }
  382. } // namespace llvm
  383. INITIALIZE_PASS(MachineOutliner, DEBUG_TYPE, "Machine Function Outliner", false,
  384. false)
  385. void MachineOutliner::emitNotOutliningCheaperRemark(
  386. unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq,
  387. OutlinedFunction &OF) {
  388. // FIXME: Right now, we arbitrarily choose some Candidate from the
  389. // OutlinedFunction. This isn't necessarily fixed, nor does it have to be.
  390. // We should probably sort these by function name or something to make sure
  391. // the remarks are stable.
  392. Candidate &C = CandidatesForRepeatedSeq.front();
  393. MachineOptimizationRemarkEmitter MORE(*(C.getMF()), nullptr);
  394. MORE.emit([&]() {
  395. MachineOptimizationRemarkMissed R(DEBUG_TYPE, "NotOutliningCheaper",
  396. C.front()->getDebugLoc(), C.getMBB());
  397. R << "Did not outline " << NV("Length", StringLen) << " instructions"
  398. << " from " << NV("NumOccurrences", CandidatesForRepeatedSeq.size())
  399. << " locations."
  400. << " Bytes from outlining all occurrences ("
  401. << NV("OutliningCost", OF.getOutliningCost()) << ")"
  402. << " >= Unoutlined instruction bytes ("
  403. << NV("NotOutliningCost", OF.getNotOutlinedCost()) << ")"
  404. << " (Also found at: ";
  405. // Tell the user the other places the candidate was found.
  406. for (unsigned i = 1, e = CandidatesForRepeatedSeq.size(); i < e; i++) {
  407. R << NV((Twine("OtherStartLoc") + Twine(i)).str(),
  408. CandidatesForRepeatedSeq[i].front()->getDebugLoc());
  409. if (i != e - 1)
  410. R << ", ";
  411. }
  412. R << ")";
  413. return R;
  414. });
  415. }
  416. void MachineOutliner::emitOutlinedFunctionRemark(OutlinedFunction &OF) {
  417. MachineBasicBlock *MBB = &*OF.MF->begin();
  418. MachineOptimizationRemarkEmitter MORE(*OF.MF, nullptr);
  419. MachineOptimizationRemark R(DEBUG_TYPE, "OutlinedFunction",
  420. MBB->findDebugLoc(MBB->begin()), MBB);
  421. R << "Saved " << NV("OutliningBenefit", OF.getBenefit()) << " bytes by "
  422. << "outlining " << NV("Length", OF.getNumInstrs()) << " instructions "
  423. << "from " << NV("NumOccurrences", OF.getOccurrenceCount())
  424. << " locations. "
  425. << "(Found at: ";
  426. // Tell the user the other places the candidate was found.
  427. for (size_t i = 0, e = OF.Candidates.size(); i < e; i++) {
  428. R << NV((Twine("StartLoc") + Twine(i)).str(),
  429. OF.Candidates[i].front()->getDebugLoc());
  430. if (i != e - 1)
  431. R << ", ";
  432. }
  433. R << ")";
  434. MORE.emit(R);
  435. }
  436. void MachineOutliner::findCandidates(
  437. InstructionMapper &Mapper, std::vector<OutlinedFunction> &FunctionList) {
  438. FunctionList.clear();
  439. SuffixTree ST(Mapper.UnsignedVec);
  440. // First, find all of the repeated substrings in the tree of minimum length
  441. // 2.
  442. std::vector<Candidate> CandidatesForRepeatedSeq;
  443. for (const SuffixTree::RepeatedSubstring &RS : ST) {
  444. CandidatesForRepeatedSeq.clear();
  445. unsigned StringLen = RS.Length;
  446. for (const unsigned &StartIdx : RS.StartIndices) {
  447. unsigned EndIdx = StartIdx + StringLen - 1;
  448. // Trick: Discard some candidates that would be incompatible with the
  449. // ones we've already found for this sequence. This will save us some
  450. // work in candidate selection.
  451. //
  452. // If two candidates overlap, then we can't outline them both. This
  453. // happens when we have candidates that look like, say
  454. //
  455. // AA (where each "A" is an instruction).
  456. //
  457. // We might have some portion of the module that looks like this:
  458. // AAAAAA (6 A's)
  459. //
  460. // In this case, there are 5 different copies of "AA" in this range, but
  461. // at most 3 can be outlined. If only outlining 3 of these is going to
  462. // be unbeneficial, then we ought to not bother.
  463. //
  464. // Note that two things DON'T overlap when they look like this:
  465. // start1...end1 .... start2...end2
  466. // That is, one must either
  467. // * End before the other starts
  468. // * Start after the other ends
  469. if (llvm::all_of(CandidatesForRepeatedSeq, [&StartIdx,
  470. &EndIdx](const Candidate &C) {
  471. return (EndIdx < C.getStartIdx() || StartIdx > C.getEndIdx());
  472. })) {
  473. // It doesn't overlap with anything, so we can outline it.
  474. // Each sequence is over [StartIt, EndIt].
  475. // Save the candidate and its location.
  476. MachineBasicBlock::iterator StartIt = Mapper.InstrList[StartIdx];
  477. MachineBasicBlock::iterator EndIt = Mapper.InstrList[EndIdx];
  478. MachineBasicBlock *MBB = StartIt->getParent();
  479. CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt,
  480. EndIt, MBB, FunctionList.size(),
  481. Mapper.MBBFlagsMap[MBB]);
  482. }
  483. }
  484. // We've found something we might want to outline.
  485. // Create an OutlinedFunction to store it and check if it'd be beneficial
  486. // to outline.
  487. if (CandidatesForRepeatedSeq.size() < 2)
  488. continue;
  489. // Arbitrarily choose a TII from the first candidate.
  490. // FIXME: Should getOutliningCandidateInfo move to TargetMachine?
  491. const TargetInstrInfo *TII =
  492. CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo();
  493. OutlinedFunction OF =
  494. TII->getOutliningCandidateInfo(CandidatesForRepeatedSeq);
  495. // If we deleted too many candidates, then there's nothing worth outlining.
  496. // FIXME: This should take target-specified instruction sizes into account.
  497. if (OF.Candidates.size() < 2)
  498. continue;
  499. // Is it better to outline this candidate than not?
  500. if (OF.getBenefit() < 1) {
  501. emitNotOutliningCheaperRemark(StringLen, CandidatesForRepeatedSeq, OF);
  502. continue;
  503. }
  504. FunctionList.push_back(OF);
  505. }
  506. }
  507. MachineFunction *MachineOutliner::createOutlinedFunction(
  508. Module &M, OutlinedFunction &OF, InstructionMapper &Mapper, unsigned Name) {
  509. // Create the function name. This should be unique.
  510. // FIXME: We should have a better naming scheme. This should be stable,
  511. // regardless of changes to the outliner's cost model/traversal order.
  512. std::string FunctionName = "OUTLINED_FUNCTION_";
  513. if (OutlineRepeatedNum > 0)
  514. FunctionName += std::to_string(OutlineRepeatedNum + 1) + "_";
  515. FunctionName += std::to_string(Name);
  516. // Create the function using an IR-level function.
  517. LLVMContext &C = M.getContext();
  518. Function *F = Function::Create(FunctionType::get(Type::getVoidTy(C), false),
  519. Function::ExternalLinkage, FunctionName, M);
  520. // NOTE: If this is linkonceodr, then we can take advantage of linker deduping
  521. // which gives us better results when we outline from linkonceodr functions.
  522. F->setLinkage(GlobalValue::InternalLinkage);
  523. F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
  524. // Set optsize/minsize, so we don't insert padding between outlined
  525. // functions.
  526. F->addFnAttr(Attribute::OptimizeForSize);
  527. F->addFnAttr(Attribute::MinSize);
  528. Candidate &FirstCand = OF.Candidates.front();
  529. const TargetInstrInfo &TII =
  530. *FirstCand.getMF()->getSubtarget().getInstrInfo();
  531. TII.mergeOutliningCandidateAttributes(*F, OF.Candidates);
  532. BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
  533. IRBuilder<> Builder(EntryBB);
  534. Builder.CreateRetVoid();
  535. MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
  536. MachineFunction &MF = MMI.getOrCreateMachineFunction(*F);
  537. MachineBasicBlock &MBB = *MF.CreateMachineBasicBlock();
  538. // Insert the new function into the module.
  539. MF.insert(MF.begin(), &MBB);
  540. MachineFunction *OriginalMF = FirstCand.front()->getMF();
  541. const std::vector<MCCFIInstruction> &Instrs =
  542. OriginalMF->getFrameInstructions();
  543. for (auto I = FirstCand.front(), E = std::next(FirstCand.back()); I != E;
  544. ++I) {
  545. if (I->isDebugInstr())
  546. continue;
  547. MachineInstr *NewMI = MF.CloneMachineInstr(&*I);
  548. if (I->isCFIInstruction()) {
  549. unsigned CFIIndex = NewMI->getOperand(0).getCFIIndex();
  550. MCCFIInstruction CFI = Instrs[CFIIndex];
  551. (void)MF.addFrameInst(CFI);
  552. }
  553. NewMI->dropMemRefs(MF);
  554. // Don't keep debug information for outlined instructions.
  555. NewMI->setDebugLoc(DebugLoc());
  556. MBB.insert(MBB.end(), NewMI);
  557. }
  558. // Set normal properties for a late MachineFunction.
  559. MF.getProperties().reset(MachineFunctionProperties::Property::IsSSA);
  560. MF.getProperties().set(MachineFunctionProperties::Property::NoPHIs);
  561. MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
  562. MF.getProperties().set(MachineFunctionProperties::Property::TracksLiveness);
  563. MF.getRegInfo().freezeReservedRegs(MF);
  564. // Compute live-in set for outlined fn
  565. const MachineRegisterInfo &MRI = MF.getRegInfo();
  566. const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
  567. LivePhysRegs LiveIns(TRI);
  568. for (auto &Cand : OF.Candidates) {
  569. // Figure out live-ins at the first instruction.
  570. MachineBasicBlock &OutlineBB = *Cand.front()->getParent();
  571. LivePhysRegs CandLiveIns(TRI);
  572. CandLiveIns.addLiveOuts(OutlineBB);
  573. for (const MachineInstr &MI :
  574. reverse(make_range(Cand.front(), OutlineBB.end())))
  575. CandLiveIns.stepBackward(MI);
  576. // The live-in set for the outlined function is the union of the live-ins
  577. // from all the outlining points.
  578. for (MCPhysReg Reg : CandLiveIns)
  579. LiveIns.addReg(Reg);
  580. }
  581. addLiveIns(MBB, LiveIns);
  582. TII.buildOutlinedFrame(MBB, MF, OF);
  583. // If there's a DISubprogram associated with this outlined function, then
  584. // emit debug info for the outlined function.
  585. if (DISubprogram *SP = getSubprogramOrNull(OF)) {
  586. // We have a DISubprogram. Get its DICompileUnit.
  587. DICompileUnit *CU = SP->getUnit();
  588. DIBuilder DB(M, true, CU);
  589. DIFile *Unit = SP->getFile();
  590. Mangler Mg;
  591. // Get the mangled name of the function for the linkage name.
  592. std::string Dummy;
  593. llvm::raw_string_ostream MangledNameStream(Dummy);
  594. Mg.getNameWithPrefix(MangledNameStream, F, false);
  595. DISubprogram *OutlinedSP = DB.createFunction(
  596. Unit /* Context */, F->getName(), StringRef(MangledNameStream.str()),
  597. Unit /* File */,
  598. 0 /* Line 0 is reserved for compiler-generated code. */,
  599. DB.createSubroutineType(DB.getOrCreateTypeArray(None)), /* void type */
  600. 0, /* Line 0 is reserved for compiler-generated code. */
  601. DINode::DIFlags::FlagArtificial /* Compiler-generated code. */,
  602. /* Outlined code is optimized code by definition. */
  603. DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
  604. // Don't add any new variables to the subprogram.
  605. DB.finalizeSubprogram(OutlinedSP);
  606. // Attach subprogram to the function.
  607. F->setSubprogram(OutlinedSP);
  608. // We're done with the DIBuilder.
  609. DB.finalize();
  610. }
  611. return &MF;
  612. }
  613. bool MachineOutliner::outline(Module &M,
  614. std::vector<OutlinedFunction> &FunctionList,
  615. InstructionMapper &Mapper,
  616. unsigned &OutlinedFunctionNum) {
  617. bool OutlinedSomething = false;
  618. // Sort by benefit. The most beneficial functions should be outlined first.
  619. llvm::stable_sort(FunctionList, [](const OutlinedFunction &LHS,
  620. const OutlinedFunction &RHS) {
  621. return LHS.getBenefit() > RHS.getBenefit();
  622. });
  623. // Walk over each function, outlining them as we go along. Functions are
  624. // outlined greedily, based off the sort above.
  625. for (OutlinedFunction &OF : FunctionList) {
  626. // If we outlined something that overlapped with a candidate in a previous
  627. // step, then we can't outline from it.
  628. erase_if(OF.Candidates, [&Mapper](Candidate &C) {
  629. return std::any_of(
  630. Mapper.UnsignedVec.begin() + C.getStartIdx(),
  631. Mapper.UnsignedVec.begin() + C.getEndIdx() + 1,
  632. [](unsigned I) { return (I == static_cast<unsigned>(-1)); });
  633. });
  634. // If we made it unbeneficial to outline this function, skip it.
  635. if (OF.getBenefit() < 1)
  636. continue;
  637. // It's beneficial. Create the function and outline its sequence's
  638. // occurrences.
  639. OF.MF = createOutlinedFunction(M, OF, Mapper, OutlinedFunctionNum);
  640. emitOutlinedFunctionRemark(OF);
  641. FunctionsCreated++;
  642. OutlinedFunctionNum++; // Created a function, move to the next name.
  643. MachineFunction *MF = OF.MF;
  644. const TargetSubtargetInfo &STI = MF->getSubtarget();
  645. const TargetInstrInfo &TII = *STI.getInstrInfo();
  646. // Replace occurrences of the sequence with calls to the new function.
  647. for (Candidate &C : OF.Candidates) {
  648. MachineBasicBlock &MBB = *C.getMBB();
  649. MachineBasicBlock::iterator StartIt = C.front();
  650. MachineBasicBlock::iterator EndIt = C.back();
  651. // Insert the call.
  652. auto CallInst = TII.insertOutlinedCall(M, MBB, StartIt, *MF, C);
  653. // If the caller tracks liveness, then we need to make sure that
  654. // anything we outline doesn't break liveness assumptions. The outlined
  655. // functions themselves currently don't track liveness, but we should
  656. // make sure that the ranges we yank things out of aren't wrong.
  657. if (MBB.getParent()->getProperties().hasProperty(
  658. MachineFunctionProperties::Property::TracksLiveness)) {
  659. // The following code is to add implicit def operands to the call
  660. // instruction. It also updates call site information for moved
  661. // code.
  662. SmallSet<Register, 2> UseRegs, DefRegs;
  663. // Copy over the defs in the outlined range.
  664. // First inst in outlined range <-- Anything that's defined in this
  665. // ... .. range has to be added as an
  666. // implicit Last inst in outlined range <-- def to the call
  667. // instruction. Also remove call site information for outlined block
  668. // of code. The exposed uses need to be copied in the outlined range.
  669. for (MachineBasicBlock::reverse_iterator
  670. Iter = EndIt.getReverse(),
  671. Last = std::next(CallInst.getReverse());
  672. Iter != Last; Iter++) {
  673. MachineInstr *MI = &*Iter;
  674. SmallSet<Register, 2> InstrUseRegs;
  675. for (MachineOperand &MOP : MI->operands()) {
  676. // Skip over anything that isn't a register.
  677. if (!MOP.isReg())
  678. continue;
  679. if (MOP.isDef()) {
  680. // Introduce DefRegs set to skip the redundant register.
  681. DefRegs.insert(MOP.getReg());
  682. if (UseRegs.count(MOP.getReg()) &&
  683. !InstrUseRegs.count(MOP.getReg()))
  684. // Since the regiester is modeled as defined,
  685. // it is not necessary to be put in use register set.
  686. UseRegs.erase(MOP.getReg());
  687. } else if (!MOP.isUndef()) {
  688. // Any register which is not undefined should
  689. // be put in the use register set.
  690. UseRegs.insert(MOP.getReg());
  691. InstrUseRegs.insert(MOP.getReg());
  692. }
  693. }
  694. if (MI->isCandidateForCallSiteEntry())
  695. MI->getMF()->eraseCallSiteInfo(MI);
  696. }
  697. for (const Register &I : DefRegs)
  698. // If it's a def, add it to the call instruction.
  699. CallInst->addOperand(
  700. MachineOperand::CreateReg(I, true, /* isDef = true */
  701. true /* isImp = true */));
  702. for (const Register &I : UseRegs)
  703. // If it's a exposed use, add it to the call instruction.
  704. CallInst->addOperand(
  705. MachineOperand::CreateReg(I, false, /* isDef = false */
  706. true /* isImp = true */));
  707. }
  708. // Erase from the point after where the call was inserted up to, and
  709. // including, the final instruction in the sequence.
  710. // Erase needs one past the end, so we need std::next there too.
  711. MBB.erase(std::next(StartIt), std::next(EndIt));
  712. // Keep track of what we removed by marking them all as -1.
  713. std::for_each(Mapper.UnsignedVec.begin() + C.getStartIdx(),
  714. Mapper.UnsignedVec.begin() + C.getEndIdx() + 1,
  715. [](unsigned &I) { I = static_cast<unsigned>(-1); });
  716. OutlinedSomething = true;
  717. // Statistics.
  718. NumOutlined++;
  719. }
  720. }
  721. LLVM_DEBUG(dbgs() << "OutlinedSomething = " << OutlinedSomething << "\n";);
  722. return OutlinedSomething;
  723. }
  724. void MachineOutliner::populateMapper(InstructionMapper &Mapper, Module &M,
  725. MachineModuleInfo &MMI) {
  726. // Build instruction mappings for each function in the module. Start by
  727. // iterating over each Function in M.
  728. for (Function &F : M) {
  729. // If there's nothing in F, then there's no reason to try and outline from
  730. // it.
  731. if (F.empty())
  732. continue;
  733. // There's something in F. Check if it has a MachineFunction associated with
  734. // it.
  735. MachineFunction *MF = MMI.getMachineFunction(F);
  736. // If it doesn't, then there's nothing to outline from. Move to the next
  737. // Function.
  738. if (!MF)
  739. continue;
  740. const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
  741. if (!RunOnAllFunctions && !TII->shouldOutlineFromFunctionByDefault(*MF))
  742. continue;
  743. // We have a MachineFunction. Ask the target if it's suitable for outlining.
  744. // If it isn't, then move on to the next Function in the module.
  745. if (!TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs))
  746. continue;
  747. // We have a function suitable for outlining. Iterate over every
  748. // MachineBasicBlock in MF and try to map its instructions to a list of
  749. // unsigned integers.
  750. for (MachineBasicBlock &MBB : *MF) {
  751. // If there isn't anything in MBB, then there's no point in outlining from
  752. // it.
  753. // If there are fewer than 2 instructions in the MBB, then it can't ever
  754. // contain something worth outlining.
  755. // FIXME: This should be based off of the maximum size in B of an outlined
  756. // call versus the size in B of the MBB.
  757. if (MBB.empty() || MBB.size() < 2)
  758. continue;
  759. // Check if MBB could be the target of an indirect branch. If it is, then
  760. // we don't want to outline from it.
  761. if (MBB.hasAddressTaken())
  762. continue;
  763. // MBB is suitable for outlining. Map it to a list of unsigneds.
  764. Mapper.convertToUnsignedVec(MBB, *TII);
  765. }
  766. }
  767. }
  768. void MachineOutliner::initSizeRemarkInfo(
  769. const Module &M, const MachineModuleInfo &MMI,
  770. StringMap<unsigned> &FunctionToInstrCount) {
  771. // Collect instruction counts for every function. We'll use this to emit
  772. // per-function size remarks later.
  773. for (const Function &F : M) {
  774. MachineFunction *MF = MMI.getMachineFunction(F);
  775. // We only care about MI counts here. If there's no MachineFunction at this
  776. // point, then there won't be after the outliner runs, so let's move on.
  777. if (!MF)
  778. continue;
  779. FunctionToInstrCount[F.getName().str()] = MF->getInstructionCount();
  780. }
  781. }
  782. void MachineOutliner::emitInstrCountChangedRemark(
  783. const Module &M, const MachineModuleInfo &MMI,
  784. const StringMap<unsigned> &FunctionToInstrCount) {
  785. // Iterate over each function in the module and emit remarks.
  786. // Note that we won't miss anything by doing this, because the outliner never
  787. // deletes functions.
  788. for (const Function &F : M) {
  789. MachineFunction *MF = MMI.getMachineFunction(F);
  790. // The outliner never deletes functions. If we don't have a MF here, then we
  791. // didn't have one prior to outlining either.
  792. if (!MF)
  793. continue;
  794. std::string Fname = std::string(F.getName());
  795. unsigned FnCountAfter = MF->getInstructionCount();
  796. unsigned FnCountBefore = 0;
  797. // Check if the function was recorded before.
  798. auto It = FunctionToInstrCount.find(Fname);
  799. // Did we have a previously-recorded size? If yes, then set FnCountBefore
  800. // to that.
  801. if (It != FunctionToInstrCount.end())
  802. FnCountBefore = It->second;
  803. // Compute the delta and emit a remark if there was a change.
  804. int64_t FnDelta = static_cast<int64_t>(FnCountAfter) -
  805. static_cast<int64_t>(FnCountBefore);
  806. if (FnDelta == 0)
  807. continue;
  808. MachineOptimizationRemarkEmitter MORE(*MF, nullptr);
  809. MORE.emit([&]() {
  810. MachineOptimizationRemarkAnalysis R("size-info", "FunctionMISizeChange",
  811. DiagnosticLocation(), &MF->front());
  812. R << DiagnosticInfoOptimizationBase::Argument("Pass", "Machine Outliner")
  813. << ": Function: "
  814. << DiagnosticInfoOptimizationBase::Argument("Function", F.getName())
  815. << ": MI instruction count changed from "
  816. << DiagnosticInfoOptimizationBase::Argument("MIInstrsBefore",
  817. FnCountBefore)
  818. << " to "
  819. << DiagnosticInfoOptimizationBase::Argument("MIInstrsAfter",
  820. FnCountAfter)
  821. << "; Delta: "
  822. << DiagnosticInfoOptimizationBase::Argument("Delta", FnDelta);
  823. return R;
  824. });
  825. }
  826. }
  827. bool MachineOutliner::runOnModule(Module &M) {
  828. // Check if there's anything in the module. If it's empty, then there's
  829. // nothing to outline.
  830. if (M.empty())
  831. return false;
  832. // Number to append to the current outlined function.
  833. unsigned OutlinedFunctionNum = 0;
  834. OutlineRepeatedNum = 0;
  835. if (!doOutline(M, OutlinedFunctionNum))
  836. return false;
  837. for (unsigned I = 0; I < OutlinerReruns; ++I) {
  838. OutlinedFunctionNum = 0;
  839. OutlineRepeatedNum++;
  840. if (!doOutline(M, OutlinedFunctionNum)) {
  841. LLVM_DEBUG({
  842. dbgs() << "Did not outline on iteration " << I + 2 << " out of "
  843. << OutlinerReruns + 1 << "\n";
  844. });
  845. break;
  846. }
  847. }
  848. return true;
  849. }
  850. bool MachineOutliner::doOutline(Module &M, unsigned &OutlinedFunctionNum) {
  851. MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
  852. // If the user passed -enable-machine-outliner=always or
  853. // -enable-machine-outliner, the pass will run on all functions in the module.
  854. // Otherwise, if the target supports default outlining, it will run on all
  855. // functions deemed by the target to be worth outlining from by default. Tell
  856. // the user how the outliner is running.
  857. LLVM_DEBUG({
  858. dbgs() << "Machine Outliner: Running on ";
  859. if (RunOnAllFunctions)
  860. dbgs() << "all functions";
  861. else
  862. dbgs() << "target-default functions";
  863. dbgs() << "\n";
  864. });
  865. // If the user specifies that they want to outline from linkonceodrs, set
  866. // it here.
  867. OutlineFromLinkOnceODRs = EnableLinkOnceODROutlining;
  868. InstructionMapper Mapper;
  869. // Prepare instruction mappings for the suffix tree.
  870. populateMapper(Mapper, M, MMI);
  871. std::vector<OutlinedFunction> FunctionList;
  872. // Find all of the outlining candidates.
  873. findCandidates(Mapper, FunctionList);
  874. // If we've requested size remarks, then collect the MI counts of every
  875. // function before outlining, and the MI counts after outlining.
  876. // FIXME: This shouldn't be in the outliner at all; it should ultimately be
  877. // the pass manager's responsibility.
  878. // This could pretty easily be placed in outline instead, but because we
  879. // really ultimately *don't* want this here, it's done like this for now
  880. // instead.
  881. // Check if we want size remarks.
  882. bool ShouldEmitSizeRemarks = M.shouldEmitInstrCountChangedRemark();
  883. StringMap<unsigned> FunctionToInstrCount;
  884. if (ShouldEmitSizeRemarks)
  885. initSizeRemarkInfo(M, MMI, FunctionToInstrCount);
  886. // Outline each of the candidates and return true if something was outlined.
  887. bool OutlinedSomething =
  888. outline(M, FunctionList, Mapper, OutlinedFunctionNum);
  889. // If we outlined something, we definitely changed the MI count of the
  890. // module. If we've asked for size remarks, then output them.
  891. // FIXME: This should be in the pass manager.
  892. if (ShouldEmitSizeRemarks && OutlinedSomething)
  893. emitInstrCountChangedRemark(M, MMI, FunctionToInstrCount);
  894. LLVM_DEBUG({
  895. if (!OutlinedSomething)
  896. dbgs() << "Stopped outlining at iteration " << OutlineRepeatedNum
  897. << " because no changes were found.\n";
  898. });
  899. return OutlinedSomething;
  900. }