Yi Kong | 8328301 | 2023-12-13 12:57:00 +0900 | [diff] [blame^] | 1 | //===- FunctionImportUtils.h - Importing support utilities -----*- 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 | // This file defines the FunctionImportGlobalProcessing class which is used |
| 10 | // to perform the necessary global value handling for function importing. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_TRANSFORMS_UTILS_FUNCTIONIMPORTUTILS_H |
| 15 | #define LLVM_TRANSFORMS_UTILS_FUNCTIONIMPORTUTILS_H |
| 16 | |
| 17 | #include "llvm/ADT/SetVector.h" |
| 18 | #include "llvm/IR/ModuleSummaryIndex.h" |
| 19 | |
| 20 | namespace llvm { |
| 21 | class Module; |
| 22 | |
| 23 | /// Class to handle necessary GlobalValue changes required by ThinLTO |
| 24 | /// function importing, including linkage changes and any necessary renaming. |
| 25 | class FunctionImportGlobalProcessing { |
| 26 | /// The Module which we are exporting or importing functions from. |
| 27 | Module &M; |
| 28 | |
| 29 | /// Module summary index passed in for function importing/exporting handling. |
| 30 | const ModuleSummaryIndex &ImportIndex; |
| 31 | |
| 32 | /// Globals to import from this module, all other functions will be |
| 33 | /// imported as declarations instead of definitions. |
| 34 | SetVector<GlobalValue *> *GlobalsToImport; |
| 35 | |
| 36 | /// Set to true if the given ModuleSummaryIndex contains any functions |
| 37 | /// from this source module, in which case we must conservatively assume |
| 38 | /// that any of its functions may be imported into another module |
| 39 | /// as part of a different backend compilation process. |
| 40 | bool HasExportedFunctions = false; |
| 41 | |
| 42 | /// Set to true (only applicatable to ELF -fpic) if dso_local should be |
| 43 | /// dropped for a declaration. |
| 44 | /// |
| 45 | /// On ELF, the assembler is conservative and assumes a global default |
| 46 | /// visibility symbol can be interposable. No direct access relocation is |
| 47 | /// allowed, if the definition is not in the translation unit, even if the |
| 48 | /// definition is available in the linkage unit. Thus we need to clear |
| 49 | /// dso_local to disable direct access. |
| 50 | /// |
| 51 | /// This flag should not be set for -fno-pic or -fpie, which would |
| 52 | /// unnecessarily disable direct access. |
| 53 | bool ClearDSOLocalOnDeclarations; |
| 54 | |
| 55 | /// Set of llvm.*used values, in order to validate that we don't try |
| 56 | /// to promote any non-renamable values. |
| 57 | SmallPtrSet<GlobalValue *, 4> Used; |
| 58 | |
| 59 | /// Keep track of any COMDATs that require renaming (because COMDAT |
| 60 | /// leader was promoted and renamed). Maps from original COMDAT to one |
| 61 | /// with new name. |
| 62 | DenseMap<const Comdat *, Comdat *> RenamedComdats; |
| 63 | |
| 64 | /// Check if we should promote the given local value to global scope. |
| 65 | bool shouldPromoteLocalToGlobal(const GlobalValue *SGV, ValueInfo VI); |
| 66 | |
| 67 | #ifndef NDEBUG |
| 68 | /// Check if the given value is a local that can't be renamed (promoted). |
| 69 | /// Only used in assertion checking, and disabled under NDEBUG since the Used |
| 70 | /// set will not be populated. |
| 71 | bool isNonRenamableLocal(const GlobalValue &GV) const; |
| 72 | #endif |
| 73 | |
| 74 | /// Helper methods to check if we are importing from or potentially |
| 75 | /// exporting from the current source module. |
| 76 | bool isPerformingImport() const { return GlobalsToImport != nullptr; } |
| 77 | bool isModuleExporting() const { return HasExportedFunctions; } |
| 78 | |
| 79 | /// If we are importing from the source module, checks if we should |
| 80 | /// import SGV as a definition, otherwise import as a declaration. |
| 81 | bool doImportAsDefinition(const GlobalValue *SGV); |
| 82 | |
| 83 | /// Get the name for a local SGV that should be promoted and renamed to global |
| 84 | /// scope in the linked destination module. |
| 85 | std::string getPromotedName(const GlobalValue *SGV); |
| 86 | |
| 87 | /// Process globals so that they can be used in ThinLTO. This includes |
| 88 | /// promoting local variables so that they can be reference externally by |
| 89 | /// thin lto imported globals and converting strong external globals to |
| 90 | /// available_externally. |
| 91 | void processGlobalsForThinLTO(); |
| 92 | void processGlobalForThinLTO(GlobalValue &GV); |
| 93 | |
| 94 | /// Get the new linkage for SGV that should be used in the linked destination |
| 95 | /// module. Specifically, for ThinLTO importing or exporting it may need |
| 96 | /// to be adjusted. When \p DoPromote is true then we must adjust the |
| 97 | /// linkage for a required promotion of a local to global scope. |
| 98 | GlobalValue::LinkageTypes getLinkage(const GlobalValue *SGV, bool DoPromote); |
| 99 | |
| 100 | public: |
| 101 | FunctionImportGlobalProcessing(Module &M, const ModuleSummaryIndex &Index, |
| 102 | SetVector<GlobalValue *> *GlobalsToImport, |
| 103 | bool ClearDSOLocalOnDeclarations) |
| 104 | : M(M), ImportIndex(Index), GlobalsToImport(GlobalsToImport), |
| 105 | ClearDSOLocalOnDeclarations(ClearDSOLocalOnDeclarations) { |
| 106 | // If we have a ModuleSummaryIndex but no function to import, |
| 107 | // then this is the primary module being compiled in a ThinLTO |
| 108 | // backend compilation, and we need to see if it has functions that |
| 109 | // may be exported to another backend compilation. |
| 110 | if (!GlobalsToImport) |
| 111 | HasExportedFunctions = ImportIndex.hasExportedFunctions(M); |
| 112 | |
| 113 | #ifndef NDEBUG |
| 114 | SmallVector<GlobalValue *, 4> Vec; |
| 115 | // First collect those in the llvm.used set. |
| 116 | collectUsedGlobalVariables(M, Vec, /*CompilerUsed=*/false); |
| 117 | // Next collect those in the llvm.compiler.used set. |
| 118 | collectUsedGlobalVariables(M, Vec, /*CompilerUsed=*/true); |
| 119 | Used = {Vec.begin(), Vec.end()}; |
| 120 | #endif |
| 121 | } |
| 122 | |
| 123 | bool run(); |
| 124 | }; |
| 125 | |
| 126 | /// Perform in-place global value handling on the given Module for |
| 127 | /// exported local functions renamed and promoted for ThinLTO. |
| 128 | bool renameModuleForThinLTO( |
| 129 | Module &M, const ModuleSummaryIndex &Index, |
| 130 | bool ClearDSOLocalOnDeclarations, |
| 131 | SetVector<GlobalValue *> *GlobalsToImport = nullptr); |
| 132 | |
| 133 | } // End llvm namespace |
| 134 | |
| 135 | #endif |