Skip to content

Commit 3adb89b

Browse files
committed
[ThinLTO] Make cloneUsedGlobalVariables deterministic
Iterating on `SmallPtrSet<GlobalValue *, 8>` with more than 8 elements is not deterministic. Use a SmallVector instead because `Used` is guaranteed to contain unique elements. While here, decrease inline element counts from 8 to 4. The number of `llvm.used`/`llvm.compiler.used` elements is usually 0 or 1. For full LTO/hybrid LTO, the number may be large, so we need to be careful. According to tejohnson's analysis https://reviews.llvm.org/D97128#2582399 , 4 is good for a large project with WholeProgramDevirt, when available_externally vtables are placed in the llvm.compiler.used set. Differential Revision: https://reviews.llvm.org/D97128
1 parent 0a5949d commit 3adb89b

File tree

3 files changed

+25
-7
lines changed

3 files changed

+25
-7
lines changed

llvm/include/llvm/IR/Module.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,12 @@ class Module {
893893
GlobalVariable *collectUsedGlobalVariables(const Module &M,
894894
SmallPtrSetImpl<GlobalValue *> &Set,
895895
bool CompilerUsed);
896+
/// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the
897+
/// initializer elements of that global in a SmallVector and return the global
898+
/// itself.
899+
GlobalVariable *collectUsedGlobalVariables(const Module &M,
900+
SmallVectorImpl<GlobalValue *> &Vec,
901+
bool CompilerUsed);
896902

897903
/// An raw_ostream inserter for modules.
898904
inline raw_ostream &operator<<(raw_ostream &O, const Module &M) {

llvm/lib/IR/Module.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,21 @@ VersionTuple Module::getSDKVersion() const {
658658
return Result;
659659
}
660660

661+
GlobalVariable *llvm::collectUsedGlobalVariables(
662+
const Module &M, SmallVectorImpl<GlobalValue *> &Vec, bool CompilerUsed) {
663+
const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
664+
GlobalVariable *GV = M.getGlobalVariable(Name);
665+
if (!GV || !GV->hasInitializer())
666+
return GV;
667+
668+
const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
669+
for (Value *Op : Init->operands()) {
670+
GlobalValue *G = cast<GlobalValue>(Op->stripPointerCasts());
671+
Vec.push_back(G);
672+
}
673+
return GV;
674+
}
675+
661676
GlobalVariable *llvm::collectUsedGlobalVariables(
662677
const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed) {
663678
const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";

llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,23 +199,20 @@ void forEachVirtualFunction(Constant *C, function_ref<void(Function *)> Fn) {
199199
// values whose defs were cloned into that module.
200200
static void cloneUsedGlobalVariables(const Module &SrcM, Module &DestM,
201201
bool CompilerUsed) {
202-
SmallPtrSet<GlobalValue *, 8> Used;
203-
SmallPtrSet<GlobalValue *, 8> NewUsed;
202+
SmallVector<GlobalValue *, 4> Used, NewUsed;
204203
// First collect those in the llvm[.compiler].used set.
205204
collectUsedGlobalVariables(SrcM, Used, CompilerUsed);
206205
// Next build a set of the equivalent values defined in DestM.
207206
for (auto *V : Used) {
208207
auto *GV = DestM.getNamedValue(V->getName());
209208
if (GV && !GV->isDeclaration())
210-
NewUsed.insert(GV);
209+
NewUsed.push_back(GV);
211210
}
212211
// Finally, add them to a llvm[.compiler].used variable in DestM.
213212
if (CompilerUsed)
214-
appendToCompilerUsed(
215-
DestM, std::vector<GlobalValue *>(NewUsed.begin(), NewUsed.end()));
213+
appendToCompilerUsed(DestM, NewUsed);
216214
else
217-
appendToUsed(DestM,
218-
std::vector<GlobalValue *>(NewUsed.begin(), NewUsed.end()));
215+
appendToUsed(DestM, NewUsed);
219216
}
220217

221218
// If it's possible to split M into regular and thin LTO parts, do so and write

0 commit comments

Comments
 (0)