mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
ae65e281f3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
133 lines
4.5 KiB
C++
133 lines
4.5 KiB
C++
//==-LTOInternalize.cpp - LLVM Link Time Optimizer Internalization Utility -==//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines a helper to run the internalization part of LTO.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/LTO/legacy/UpdateCompilerUsed.h"
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
#include "llvm/CodeGen/TargetLowering.h"
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
|
#include "llvm/IR/LegacyPassManager.h"
|
|
#include "llvm/IR/Mangler.h"
|
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
// Helper class that collects AsmUsed and user supplied libcalls.
|
|
class PreserveLibCallsAndAsmUsed {
|
|
public:
|
|
PreserveLibCallsAndAsmUsed(const StringSet<> &AsmUndefinedRefs,
|
|
const TargetMachine &TM,
|
|
std::vector<GlobalValue *> &LLVMUsed)
|
|
: AsmUndefinedRefs(AsmUndefinedRefs), TM(TM), LLVMUsed(LLVMUsed) {}
|
|
|
|
void findInModule(Module &TheModule) {
|
|
initializeLibCalls(TheModule);
|
|
for (Function &F : TheModule)
|
|
findLibCallsAndAsm(F);
|
|
for (GlobalVariable &GV : TheModule.globals())
|
|
findLibCallsAndAsm(GV);
|
|
for (GlobalAlias &GA : TheModule.aliases())
|
|
findLibCallsAndAsm(GA);
|
|
}
|
|
|
|
private:
|
|
// Inputs
|
|
const StringSet<> &AsmUndefinedRefs;
|
|
const TargetMachine &TM;
|
|
|
|
// Temps
|
|
llvm::Mangler Mangler;
|
|
StringSet<> Libcalls;
|
|
|
|
// Output
|
|
std::vector<GlobalValue *> &LLVMUsed;
|
|
|
|
// Collect names of runtime library functions. User-defined functions with the
|
|
// same names are added to llvm.compiler.used to prevent them from being
|
|
// deleted by optimizations.
|
|
void initializeLibCalls(const Module &TheModule) {
|
|
TargetLibraryInfoImpl TLII(Triple(TM.getTargetTriple()));
|
|
TargetLibraryInfo TLI(TLII);
|
|
|
|
// TargetLibraryInfo has info on C runtime library calls on the current
|
|
// target.
|
|
for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs);
|
|
I != E; ++I) {
|
|
LibFunc F = static_cast<LibFunc>(I);
|
|
if (TLI.has(F))
|
|
Libcalls.insert(TLI.getName(F));
|
|
}
|
|
|
|
SmallPtrSet<const TargetLowering *, 1> TLSet;
|
|
|
|
for (const Function &F : TheModule) {
|
|
const TargetLowering *Lowering =
|
|
TM.getSubtargetImpl(F)->getTargetLowering();
|
|
|
|
if (Lowering && TLSet.insert(Lowering).second)
|
|
// TargetLowering has info on library calls that CodeGen expects to be
|
|
// available, both from the C runtime and compiler-rt.
|
|
for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL);
|
|
I != E; ++I)
|
|
if (const char *Name =
|
|
Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I)))
|
|
Libcalls.insert(Name);
|
|
}
|
|
}
|
|
|
|
void findLibCallsAndAsm(GlobalValue &GV) {
|
|
// There are no restrictions to apply to declarations.
|
|
if (GV.isDeclaration())
|
|
return;
|
|
|
|
// There is nothing more restrictive than private linkage.
|
|
if (GV.hasPrivateLinkage())
|
|
return;
|
|
|
|
// Conservatively append user-supplied runtime library functions (supplied
|
|
// either directly, or via a function alias) to llvm.compiler.used. These
|
|
// could be internalized and deleted by optimizations like -globalopt,
|
|
// causing problems when later optimizations add new library calls (e.g.,
|
|
// llvm.memset => memset and printf => puts).
|
|
// Leave it to the linker to remove any dead code (e.g. with -dead_strip).
|
|
GlobalValue *FuncAliasee = nullptr;
|
|
if (isa<GlobalAlias>(GV)) {
|
|
auto *A = cast<GlobalAlias>(&GV);
|
|
FuncAliasee = dyn_cast<Function>(A->getAliasee());
|
|
}
|
|
if ((isa<Function>(GV) || FuncAliasee) && Libcalls.count(GV.getName())) {
|
|
LLVMUsed.push_back(&GV);
|
|
return;
|
|
}
|
|
|
|
SmallString<64> Buffer;
|
|
TM.getNameWithPrefix(Buffer, &GV, Mangler);
|
|
if (AsmUndefinedRefs.count(Buffer))
|
|
LLVMUsed.push_back(&GV);
|
|
}
|
|
};
|
|
|
|
} // namespace anonymous
|
|
|
|
void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM,
|
|
const StringSet<> &AsmUndefinedRefs) {
|
|
std::vector<GlobalValue *> UsedValues;
|
|
PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues)
|
|
.findInModule(TheModule);
|
|
|
|
if (UsedValues.empty())
|
|
return;
|
|
|
|
appendToCompilerUsed(TheModule, UsedValues);
|
|
}
|