Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

View File

@ -1,155 +0,0 @@
//===- InlineAlways.cpp - Code to inline always_inline functions ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a custom inliner that handles only functions that
// are marked as "always inline".
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/Inliner.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
using namespace llvm;
#define DEBUG_TYPE "inline"
PreservedAnalyses AlwaysInlinerPass::run(Module &M, ModuleAnalysisManager &) {
InlineFunctionInfo IFI;
SmallSetVector<CallSite, 16> Calls;
bool Changed = false;
SmallVector<Function *, 16> InlinedFunctions;
for (Function &F : M)
if (!F.isDeclaration() && F.hasFnAttribute(Attribute::AlwaysInline) &&
isInlineViable(F)) {
Calls.clear();
for (User *U : F.users())
if (auto CS = CallSite(U))
if (CS.getCalledFunction() == &F)
Calls.insert(CS);
for (CallSite CS : Calls)
// FIXME: We really shouldn't be able to fail to inline at this point!
// We should do something to log or check the inline failures here.
Changed |= InlineFunction(CS, IFI);
// Remember to try and delete this function afterward. This both avoids
// re-walking the rest of the module and avoids dealing with any iterator
// invalidation issues while deleting functions.
InlinedFunctions.push_back(&F);
}
// Remove any live functions.
erase_if(InlinedFunctions, [&](Function *F) {
F->removeDeadConstantUsers();
return !F->isDefTriviallyDead();
});
// Delete the non-comdat ones from the module and also from our vector.
auto NonComdatBegin = partition(
InlinedFunctions, [&](Function *F) { return F->hasComdat(); });
for (Function *F : make_range(NonComdatBegin, InlinedFunctions.end()))
M.getFunctionList().erase(F);
InlinedFunctions.erase(NonComdatBegin, InlinedFunctions.end());
if (!InlinedFunctions.empty()) {
// Now we just have the comdat functions. Filter out the ones whose comdats
// are not actually dead.
filterDeadComdatFunctions(M, InlinedFunctions);
// The remaining functions are actually dead.
for (Function *F : InlinedFunctions)
M.getFunctionList().erase(F);
}
return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
}
namespace {
/// Inliner pass which only handles "always inline" functions.
///
/// Unlike the \c AlwaysInlinerPass, this uses the more heavyweight \c Inliner
/// base class to provide several facilities such as array alloca merging.
class AlwaysInlinerLegacyPass : public LegacyInlinerBase {
public:
AlwaysInlinerLegacyPass() : LegacyInlinerBase(ID, /*InsertLifetime*/ true) {
initializeAlwaysInlinerLegacyPassPass(*PassRegistry::getPassRegistry());
}
AlwaysInlinerLegacyPass(bool InsertLifetime)
: LegacyInlinerBase(ID, InsertLifetime) {
initializeAlwaysInlinerLegacyPassPass(*PassRegistry::getPassRegistry());
}
/// Main run interface method. We override here to avoid calling skipSCC().
bool runOnSCC(CallGraphSCC &SCC) override { return inlineCalls(SCC); }
static char ID; // Pass identification, replacement for typeid
InlineCost getInlineCost(CallSite CS) override;
using llvm::Pass::doFinalization;
bool doFinalization(CallGraph &CG) override {
return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/true);
}
};
}
char AlwaysInlinerLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(AlwaysInlinerLegacyPass, "always-inline",
"Inliner for always_inline functions", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(AlwaysInlinerLegacyPass, "always-inline",
"Inliner for always_inline functions", false, false)
Pass *llvm::createAlwaysInlinerLegacyPass(bool InsertLifetime) {
return new AlwaysInlinerLegacyPass(InsertLifetime);
}
/// \brief Get the inline cost for the always-inliner.
///
/// The always inliner *only* handles functions which are marked with the
/// attribute to force inlining. As such, it is dramatically simpler and avoids
/// using the powerful (but expensive) inline cost analysis. Instead it uses
/// a very simple and boring direct walk of the instructions looking for
/// impossible-to-inline constructs.
///
/// Note, it would be possible to go to some lengths to cache the information
/// computed here, but as we only expect to do this for relatively few and
/// small functions which have the explicit attribute to force inlining, it is
/// likely not worth it in practice.
InlineCost AlwaysInlinerLegacyPass::getInlineCost(CallSite CS) {
Function *Callee = CS.getCalledFunction();
// Only inline direct calls to functions with always-inline attributes
// that are viable for inlining. FIXME: We shouldn't even get here for
// declarations.
if (Callee && !Callee->isDeclaration() &&
CS.hasFnAttr(Attribute::AlwaysInline) && isInlineViable(*Callee))
return InlineCost::getAlways();
return InlineCost::getNever();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +0,0 @@
//===- BarrierNoopPass.cpp - A barrier pass for the pass manager ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// NOTE: DO NOT USE THIS IF AVOIDABLE
//
// This pass is a nonce pass intended to allow manipulation of the implicitly
// nesting pass manager. For example, it can be used to cause a CGSCC pass
// manager to be closed prior to running a new collection of function passes.
//
// FIXME: This is a huge HACK. This should be removed when the pass manager's
// nesting is made explicit instead of implicit.
//
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
#include "llvm/Transforms/IPO.h"
using namespace llvm;
namespace {
/// \brief A nonce module pass used to place a barrier in a pass manager.
///
/// There is no mechanism for ending a CGSCC pass manager once one is started.
/// This prevents extension points from having clear deterministic ordering
/// when they are phrased as non-module passes.
class BarrierNoop : public ModulePass {
public:
static char ID; // Pass identification.
BarrierNoop() : ModulePass(ID) {
initializeBarrierNoopPass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override { return false; }
};
}
ModulePass *llvm::createBarrierNoopPass() { return new BarrierNoop(); }
char BarrierNoop::ID = 0;
INITIALIZE_PASS(BarrierNoop, "barrier", "A No-Op Barrier Pass",
false, false)

View File

@ -1,41 +0,0 @@
add_llvm_library(LLVMipo
AlwaysInliner.cpp
ArgumentPromotion.cpp
BarrierNoopPass.cpp
CalledValuePropagation.cpp
ConstantMerge.cpp
CrossDSOCFI.cpp
DeadArgumentElimination.cpp
ElimAvailExtern.cpp
ExtractGV.cpp
ForceFunctionAttrs.cpp
FunctionAttrs.cpp
FunctionImport.cpp
GlobalDCE.cpp
GlobalOpt.cpp
GlobalSplit.cpp
IPConstantPropagation.cpp
IPO.cpp
InferFunctionAttrs.cpp
InlineSimple.cpp
Inliner.cpp
Internalize.cpp
LoopExtractor.cpp
LowerTypeTests.cpp
MergeFunctions.cpp
PartialInlining.cpp
PassManagerBuilder.cpp
PruneEH.cpp
SampleProfile.cpp
StripDeadPrototypes.cpp
StripSymbols.cpp
ThinLTOBitcodeWriter.cpp
WholeProgramDevirt.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms/IPO
DEPENDS
intrinsics_gen
)

View File

@ -1,423 +0,0 @@
//===- CalledValuePropagation.cpp - Propagate called values -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a transformation that attaches !callees metadata to
// indirect call sites. For a given call site, the metadata, if present,
// indicates the set of functions the call site could possibly target at
// run-time. This metadata is added to indirect call sites when the set of
// possible targets can be determined by analysis and is known to be small. The
// analysis driving the transformation is similar to constant propagation and
// makes uses of the generic sparse propagation solver.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/CalledValuePropagation.h"
#include "llvm/Analysis/SparsePropagation.h"
#include "llvm/Analysis/ValueLatticeUtils.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/Transforms/IPO.h"
using namespace llvm;
#define DEBUG_TYPE "called-value-propagation"
/// The maximum number of functions to track per lattice value. Once the number
/// of functions a call site can possibly target exceeds this threshold, it's
/// lattice value becomes overdefined. The number of possible lattice values is
/// bounded by Ch(F, M), where F is the number of functions in the module and M
/// is MaxFunctionsPerValue. As such, this value should be kept very small. We
/// likely can't do anything useful for call sites with a large number of
/// possible targets, anyway.
static cl::opt<unsigned> MaxFunctionsPerValue(
"cvp-max-functions-per-value", cl::Hidden, cl::init(4),
cl::desc("The maximum number of functions to track per lattice value"));
namespace {
/// To enable interprocedural analysis, we assign LLVM values to the following
/// groups. The register group represents SSA registers, the return group
/// represents the return values of functions, and the memory group represents
/// in-memory values. An LLVM Value can technically be in more than one group.
/// It's necessary to distinguish these groups so we can, for example, track a
/// global variable separately from the value stored at its location.
enum class IPOGrouping { Register, Return, Memory };
/// Our LatticeKeys are PointerIntPairs composed of LLVM values and groupings.
using CVPLatticeKey = PointerIntPair<Value *, 2, IPOGrouping>;
/// The lattice value type used by our custom lattice function. It holds the
/// lattice state, and a set of functions.
class CVPLatticeVal {
public:
/// The states of the lattice values. Only the FunctionSet state is
/// interesting. It indicates the set of functions to which an LLVM value may
/// refer.
enum CVPLatticeStateTy { Undefined, FunctionSet, Overdefined, Untracked };
/// Comparator for sorting the functions set. We want to keep the order
/// deterministic for testing, etc.
struct Compare {
bool operator()(const Function *LHS, const Function *RHS) const {
return LHS->getName() < RHS->getName();
}
};
CVPLatticeVal() : LatticeState(Undefined) {}
CVPLatticeVal(CVPLatticeStateTy LatticeState) : LatticeState(LatticeState) {}
CVPLatticeVal(std::set<Function *, Compare> &&Functions)
: LatticeState(FunctionSet), Functions(Functions) {}
/// Get a reference to the functions held by this lattice value. The number
/// of functions will be zero for states other than FunctionSet.
const std::set<Function *, Compare> &getFunctions() const {
return Functions;
}
/// Returns true if the lattice value is in the FunctionSet state.
bool isFunctionSet() const { return LatticeState == FunctionSet; }
bool operator==(const CVPLatticeVal &RHS) const {
return LatticeState == RHS.LatticeState && Functions == RHS.Functions;
}
bool operator!=(const CVPLatticeVal &RHS) const {
return LatticeState != RHS.LatticeState || Functions != RHS.Functions;
}
private:
/// Holds the state this lattice value is in.
CVPLatticeStateTy LatticeState;
/// Holds functions indicating the possible targets of call sites. This set
/// is empty for lattice values in the undefined, overdefined, and untracked
/// states. The maximum size of the set is controlled by
/// MaxFunctionsPerValue. Since most LLVM values are expected to be in
/// uninteresting states (i.e., overdefined), CVPLatticeVal objects should be
/// small and efficiently copyable.
std::set<Function *, Compare> Functions;
};
/// The custom lattice function used by the generic sparse propagation solver.
/// It handles merging lattice values and computing new lattice values for
/// constants, arguments, values returned from trackable functions, and values
/// located in trackable global variables. It also computes the lattice values
/// that change as a result of executing instructions.
class CVPLatticeFunc
: public AbstractLatticeFunction<CVPLatticeKey, CVPLatticeVal> {
public:
CVPLatticeFunc()
: AbstractLatticeFunction(CVPLatticeVal(CVPLatticeVal::Undefined),
CVPLatticeVal(CVPLatticeVal::Overdefined),
CVPLatticeVal(CVPLatticeVal::Untracked)) {}
/// Compute and return a CVPLatticeVal for the given CVPLatticeKey.
CVPLatticeVal ComputeLatticeVal(CVPLatticeKey Key) override {
switch (Key.getInt()) {
case IPOGrouping::Register:
if (isa<Instruction>(Key.getPointer())) {
return getUndefVal();
} else if (auto *A = dyn_cast<Argument>(Key.getPointer())) {
if (canTrackArgumentsInterprocedurally(A->getParent()))
return getUndefVal();
} else if (auto *C = dyn_cast<Constant>(Key.getPointer())) {
return computeConstant(C);
}
return getOverdefinedVal();
case IPOGrouping::Memory:
case IPOGrouping::Return:
if (auto *GV = dyn_cast<GlobalVariable>(Key.getPointer())) {
if (canTrackGlobalVariableInterprocedurally(GV))
return computeConstant(GV->getInitializer());
} else if (auto *F = cast<Function>(Key.getPointer()))
if (canTrackReturnsInterprocedurally(F))
return getUndefVal();
}
return getOverdefinedVal();
}
/// Merge the two given lattice values. The interesting cases are merging two
/// FunctionSet values and a FunctionSet value with an Undefined value. For
/// these cases, we simply union the function sets. If the size of the union
/// is greater than the maximum functions we track, the merged value is
/// overdefined.
CVPLatticeVal MergeValues(CVPLatticeVal X, CVPLatticeVal Y) override {
if (X == getOverdefinedVal() || Y == getOverdefinedVal())
return getOverdefinedVal();
if (X == getUndefVal() && Y == getUndefVal())
return getUndefVal();
std::set<Function *, CVPLatticeVal::Compare> Union;
std::set_union(X.getFunctions().begin(), X.getFunctions().end(),
Y.getFunctions().begin(), Y.getFunctions().end(),
std::inserter(Union, Union.begin()),
CVPLatticeVal::Compare{});
if (Union.size() > MaxFunctionsPerValue)
return getOverdefinedVal();
return CVPLatticeVal(std::move(Union));
}
/// Compute the lattice values that change as a result of executing the given
/// instruction. The changed values are stored in \p ChangedValues. We handle
/// just a few kinds of instructions since we're only propagating values that
/// can be called.
void ComputeInstructionState(
Instruction &I, DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues,
SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) override {
switch (I.getOpcode()) {
case Instruction::Call:
return visitCallSite(cast<CallInst>(&I), ChangedValues, SS);
case Instruction::Invoke:
return visitCallSite(cast<InvokeInst>(&I), ChangedValues, SS);
case Instruction::Load:
return visitLoad(*cast<LoadInst>(&I), ChangedValues, SS);
case Instruction::Ret:
return visitReturn(*cast<ReturnInst>(&I), ChangedValues, SS);
case Instruction::Select:
return visitSelect(*cast<SelectInst>(&I), ChangedValues, SS);
case Instruction::Store:
return visitStore(*cast<StoreInst>(&I), ChangedValues, SS);
default:
return visitInst(I, ChangedValues, SS);
}
}
/// Print the given CVPLatticeVal to the specified stream.
void PrintLatticeVal(CVPLatticeVal LV, raw_ostream &OS) override {
if (LV == getUndefVal())
OS << "Undefined ";
else if (LV == getOverdefinedVal())
OS << "Overdefined";
else if (LV == getUntrackedVal())
OS << "Untracked ";
else
OS << "FunctionSet";
}
/// Print the given CVPLatticeKey to the specified stream.
void PrintLatticeKey(CVPLatticeKey Key, raw_ostream &OS) override {
if (Key.getInt() == IPOGrouping::Register)
OS << "<reg> ";
else if (Key.getInt() == IPOGrouping::Memory)
OS << "<mem> ";
else if (Key.getInt() == IPOGrouping::Return)
OS << "<ret> ";
if (isa<Function>(Key.getPointer()))
OS << Key.getPointer()->getName();
else
OS << *Key.getPointer();
}
/// We collect a set of indirect calls when visiting call sites. This method
/// returns a reference to that set.
SmallPtrSetImpl<Instruction *> &getIndirectCalls() { return IndirectCalls; }
private:
/// Holds the indirect calls we encounter during the analysis. We will attach
/// metadata to these calls after the analysis indicating the functions the
/// calls can possibly target.
SmallPtrSet<Instruction *, 32> IndirectCalls;
/// Compute a new lattice value for the given constant. The constant, after
/// stripping any pointer casts, should be a Function. We ignore null
/// pointers as an optimization, since calling these values is undefined
/// behavior.
CVPLatticeVal computeConstant(Constant *C) {
if (isa<ConstantPointerNull>(C))
return CVPLatticeVal(CVPLatticeVal::FunctionSet);
if (auto *F = dyn_cast<Function>(C->stripPointerCasts()))
return CVPLatticeVal({F});
return getOverdefinedVal();
}
/// Handle return instructions. The function's return state is the merge of
/// the returned value state and the function's return state.
void visitReturn(ReturnInst &I,
DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues,
SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {
Function *F = I.getParent()->getParent();
if (F->getReturnType()->isVoidTy())
return;
auto RegI = CVPLatticeKey(I.getReturnValue(), IPOGrouping::Register);
auto RetF = CVPLatticeKey(F, IPOGrouping::Return);
ChangedValues[RetF] =
MergeValues(SS.getValueState(RegI), SS.getValueState(RetF));
}
/// Handle call sites. The state of a called function's formal arguments is
/// the merge of the argument state with the call sites corresponding actual
/// argument state. The call site state is the merge of the call site state
/// with the returned value state of the called function.
void visitCallSite(CallSite CS,
DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues,
SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {
Function *F = CS.getCalledFunction();
Instruction *I = CS.getInstruction();
auto RegI = CVPLatticeKey(I, IPOGrouping::Register);
// If this is an indirect call, save it so we can quickly revisit it when
// attaching metadata.
if (!F)
IndirectCalls.insert(I);
// If we can't track the function's return values, there's nothing to do.
if (!F || !canTrackReturnsInterprocedurally(F)) {
ChangedValues[RegI] = getOverdefinedVal();
return;
}
// Inform the solver that the called function is executable, and perform
// the merges for the arguments and return value.
SS.MarkBlockExecutable(&F->front());
auto RetF = CVPLatticeKey(F, IPOGrouping::Return);
for (Argument &A : F->args()) {
auto RegFormal = CVPLatticeKey(&A, IPOGrouping::Register);
auto RegActual =
CVPLatticeKey(CS.getArgument(A.getArgNo()), IPOGrouping::Register);
ChangedValues[RegFormal] =
MergeValues(SS.getValueState(RegFormal), SS.getValueState(RegActual));
}
ChangedValues[RegI] =
MergeValues(SS.getValueState(RegI), SS.getValueState(RetF));
}
/// Handle select instructions. The select instruction state is the merge the
/// true and false value states.
void visitSelect(SelectInst &I,
DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues,
SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {
auto RegI = CVPLatticeKey(&I, IPOGrouping::Register);
auto RegT = CVPLatticeKey(I.getTrueValue(), IPOGrouping::Register);
auto RegF = CVPLatticeKey(I.getFalseValue(), IPOGrouping::Register);
ChangedValues[RegI] =
MergeValues(SS.getValueState(RegT), SS.getValueState(RegF));
}
/// Handle load instructions. If the pointer operand of the load is a global
/// variable, we attempt to track the value. The loaded value state is the
/// merge of the loaded value state with the global variable state.
void visitLoad(LoadInst &I,
DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues,
SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {
auto RegI = CVPLatticeKey(&I, IPOGrouping::Register);
if (auto *GV = dyn_cast<GlobalVariable>(I.getPointerOperand())) {
auto MemGV = CVPLatticeKey(GV, IPOGrouping::Memory);
ChangedValues[RegI] =
MergeValues(SS.getValueState(RegI), SS.getValueState(MemGV));
} else {
ChangedValues[RegI] = getOverdefinedVal();
}
}
/// Handle store instructions. If the pointer operand of the store is a
/// global variable, we attempt to track the value. The global variable state
/// is the merge of the stored value state with the global variable state.
void visitStore(StoreInst &I,
DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues,
SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {
auto *GV = dyn_cast<GlobalVariable>(I.getPointerOperand());
if (!GV)
return;
auto RegI = CVPLatticeKey(I.getValueOperand(), IPOGrouping::Register);
auto MemGV = CVPLatticeKey(GV, IPOGrouping::Memory);
ChangedValues[MemGV] =
MergeValues(SS.getValueState(RegI), SS.getValueState(MemGV));
}
/// Handle all other instructions. All other instructions are marked
/// overdefined.
void visitInst(Instruction &I,
DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues,
SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {
auto RegI = CVPLatticeKey(&I, IPOGrouping::Register);
ChangedValues[RegI] = getOverdefinedVal();
}
};
} // namespace
namespace llvm {
/// A specialization of LatticeKeyInfo for CVPLatticeKeys. The generic solver
/// must translate between LatticeKeys and LLVM Values when adding Values to
/// its work list and inspecting the state of control-flow related values.
template <> struct LatticeKeyInfo<CVPLatticeKey> {
static inline Value *getValueFromLatticeKey(CVPLatticeKey Key) {
return Key.getPointer();
}
static inline CVPLatticeKey getLatticeKeyFromValue(Value *V) {
return CVPLatticeKey(V, IPOGrouping::Register);
}
};
} // namespace llvm
static bool runCVP(Module &M) {
// Our custom lattice function and generic sparse propagation solver.
CVPLatticeFunc Lattice;
SparseSolver<CVPLatticeKey, CVPLatticeVal> Solver(&Lattice);
// For each function in the module, if we can't track its arguments, let the
// generic solver assume it is executable.
for (Function &F : M)
if (!F.isDeclaration() && !canTrackArgumentsInterprocedurally(&F))
Solver.MarkBlockExecutable(&F.front());
// Solver our custom lattice. In doing so, we will also build a set of
// indirect call sites.
Solver.Solve();
// Attach metadata to the indirect call sites that were collected indicating
// the set of functions they can possibly target.
bool Changed = false;
MDBuilder MDB(M.getContext());
for (Instruction *C : Lattice.getIndirectCalls()) {
CallSite CS(C);
auto RegI = CVPLatticeKey(CS.getCalledValue(), IPOGrouping::Register);
CVPLatticeVal LV = Solver.getExistingValueState(RegI);
if (!LV.isFunctionSet() || LV.getFunctions().empty())
continue;
MDNode *Callees = MDB.createCallees(SmallVector<Function *, 4>(
LV.getFunctions().begin(), LV.getFunctions().end()));
C->setMetadata(LLVMContext::MD_callees, Callees);
Changed = true;
}
return Changed;
}
PreservedAnalyses CalledValuePropagationPass::run(Module &M,
ModuleAnalysisManager &) {
runCVP(M);
return PreservedAnalyses::all();
}
namespace {
class CalledValuePropagationLegacyPass : public ModulePass {
public:
static char ID;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
CalledValuePropagationLegacyPass() : ModulePass(ID) {
initializeCalledValuePropagationLegacyPassPass(
*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
return runCVP(M);
}
};
} // namespace
char CalledValuePropagationLegacyPass::ID = 0;
INITIALIZE_PASS(CalledValuePropagationLegacyPass, "called-value-propagation",
"Called Value Propagation", false, false)
ModulePass *llvm::createCalledValuePropagationPass() {
return new CalledValuePropagationLegacyPass();
}

View File

@ -1,260 +0,0 @@
//===- ConstantMerge.cpp - Merge duplicate global constants ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface to a pass that merges duplicate global
// constants together into a single constant that is shared. This is useful
// because some passes (ie TraceValues) insert a lot of string constants into
// the program, regardless of whether or not an existing string is available.
//
// Algorithm: ConstantMerge is designed to build up a map of available constants
// and eliminate duplicates when it is initialized.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/ConstantMerge.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Transforms/IPO.h"
#include <algorithm>
#include <cassert>
#include <utility>
using namespace llvm;
#define DEBUG_TYPE "constmerge"
STATISTIC(NumMerged, "Number of global constants merged");
/// Find values that are marked as llvm.used.
static void FindUsedValues(GlobalVariable *LLVMUsed,
SmallPtrSetImpl<const GlobalValue*> &UsedValues) {
if (!LLVMUsed) return;
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) {
Value *Operand = Inits->getOperand(i)->stripPointerCastsNoFollowAliases();
GlobalValue *GV = cast<GlobalValue>(Operand);
UsedValues.insert(GV);
}
}
// True if A is better than B.
static bool IsBetterCanonical(const GlobalVariable &A,
const GlobalVariable &B) {
if (!A.hasLocalLinkage() && B.hasLocalLinkage())
return true;
if (A.hasLocalLinkage() && !B.hasLocalLinkage())
return false;
return A.hasGlobalUnnamedAddr();
}
static bool hasMetadataOtherThanDebugLoc(const GlobalVariable *GV) {
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
GV->getAllMetadata(MDs);
for (const auto &V : MDs)
if (V.first != LLVMContext::MD_dbg)
return true;
return false;
}
static void copyDebugLocMetadata(const GlobalVariable *From,
GlobalVariable *To) {
SmallVector<DIGlobalVariableExpression *, 1> MDs;
From->getDebugInfo(MDs);
for (auto MD : MDs)
To->addDebugInfo(MD);
}
static unsigned getAlignment(GlobalVariable *GV) {
unsigned Align = GV->getAlignment();
if (Align)
return Align;
return GV->getParent()->getDataLayout().getPreferredAlignment(GV);
}
static bool mergeConstants(Module &M) {
// Find all the globals that are marked "used". These cannot be merged.
SmallPtrSet<const GlobalValue*, 8> UsedGlobals;
FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals);
FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals);
// Map unique constants to globals.
DenseMap<Constant *, GlobalVariable *> CMap;
// Replacements - This vector contains a list of replacements to perform.
SmallVector<std::pair<GlobalVariable*, GlobalVariable*>, 32> Replacements;
bool MadeChange = false;
// Iterate constant merging while we are still making progress. Merging two
// constants together may allow us to merge other constants together if the
// second level constants have initializers which point to the globals that
// were just merged.
while (true) {
// First: Find the canonical constants others will be merged with.
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
GVI != E; ) {
GlobalVariable *GV = &*GVI++;
// If this GV is dead, remove it.
GV->removeDeadConstantUsers();
if (GV->use_empty() && GV->hasLocalLinkage()) {
GV->eraseFromParent();
continue;
}
// Only process constants with initializers in the default address space.
if (!GV->isConstant() || !GV->hasDefinitiveInitializer() ||
GV->getType()->getAddressSpace() != 0 || GV->hasSection() ||
// Don't touch values marked with attribute(used).
UsedGlobals.count(GV))
continue;
// This transformation is legal for weak ODR globals in the sense it
// doesn't change semantics, but we really don't want to perform it
// anyway; it's likely to pessimize code generation, and some tools
// (like the Darwin linker in cases involving CFString) don't expect it.
if (GV->isWeakForLinker())
continue;
// Don't touch globals with metadata other then !dbg.
if (hasMetadataOtherThanDebugLoc(GV))
continue;
Constant *Init = GV->getInitializer();
// Check to see if the initializer is already known.
GlobalVariable *&Slot = CMap[Init];
// If this is the first constant we find or if the old one is local,
// replace with the current one. If the current is externally visible
// it cannot be replace, but can be the canonical constant we merge with.
if (!Slot || IsBetterCanonical(*GV, *Slot))
Slot = GV;
}
// Second: identify all globals that can be merged together, filling in
// the Replacements vector. We cannot do the replacement in this pass
// because doing so may cause initializers of other globals to be rewritten,
// invalidating the Constant* pointers in CMap.
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
GVI != E; ) {
GlobalVariable *GV = &*GVI++;
// Only process constants with initializers in the default address space.
if (!GV->isConstant() || !GV->hasDefinitiveInitializer() ||
GV->getType()->getAddressSpace() != 0 || GV->hasSection() ||
// Don't touch values marked with attribute(used).
UsedGlobals.count(GV))
continue;
// We can only replace constant with local linkage.
if (!GV->hasLocalLinkage())
continue;
Constant *Init = GV->getInitializer();
// Check to see if the initializer is already known.
GlobalVariable *Slot = CMap[Init];
if (!Slot || Slot == GV)
continue;
if (!Slot->hasGlobalUnnamedAddr() && !GV->hasGlobalUnnamedAddr())
continue;
if (hasMetadataOtherThanDebugLoc(GV))
continue;
if (!GV->hasGlobalUnnamedAddr())
Slot->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
// Make all uses of the duplicate constant use the canonical version.
Replacements.push_back(std::make_pair(GV, Slot));
}
if (Replacements.empty())
return MadeChange;
CMap.clear();
// Now that we have figured out which replacements must be made, do them all
// now. This avoid invalidating the pointers in CMap, which are unneeded
// now.
for (unsigned i = 0, e = Replacements.size(); i != e; ++i) {
// Bump the alignment if necessary.
if (Replacements[i].first->getAlignment() ||
Replacements[i].second->getAlignment()) {
Replacements[i].second->setAlignment(
std::max(getAlignment(Replacements[i].first),
getAlignment(Replacements[i].second)));
}
copyDebugLocMetadata(Replacements[i].first, Replacements[i].second);
// Eliminate any uses of the dead global.
Replacements[i].first->replaceAllUsesWith(Replacements[i].second);
// Delete the global value from the module.
assert(Replacements[i].first->hasLocalLinkage() &&
"Refusing to delete an externally visible global variable.");
Replacements[i].first->eraseFromParent();
}
NumMerged += Replacements.size();
Replacements.clear();
}
}
PreservedAnalyses ConstantMergePass::run(Module &M, ModuleAnalysisManager &) {
if (!mergeConstants(M))
return PreservedAnalyses::all();
return PreservedAnalyses::none();
}
namespace {
struct ConstantMergeLegacyPass : public ModulePass {
static char ID; // Pass identification, replacement for typeid
ConstantMergeLegacyPass() : ModulePass(ID) {
initializeConstantMergeLegacyPassPass(*PassRegistry::getPassRegistry());
}
// For this pass, process all of the globals in the module, eliminating
// duplicate constants.
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
return mergeConstants(M);
}
};
} // end anonymous namespace
char ConstantMergeLegacyPass::ID = 0;
INITIALIZE_PASS(ConstantMergeLegacyPass, "constmerge",
"Merge Duplicate Global Constants", false, false)
ModulePass *llvm::createConstantMergePass() {
return new ConstantMergeLegacyPass();
}

View File

@ -1,182 +0,0 @@
//===-- CrossDSOCFI.cpp - Externalize this module's CFI checks ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass exports all llvm.bitset's found in the module in the form of a
// __cfi_check function, which can be used to verify cross-DSO call targets.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/CrossDSOCFI.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
using namespace llvm;
#define DEBUG_TYPE "cross-dso-cfi"
STATISTIC(NumTypeIds, "Number of unique type identifiers");
namespace {
struct CrossDSOCFI : public ModulePass {
static char ID;
CrossDSOCFI() : ModulePass(ID) {
initializeCrossDSOCFIPass(*PassRegistry::getPassRegistry());
}
MDNode *VeryLikelyWeights;
ConstantInt *extractNumericTypeId(MDNode *MD);
void buildCFICheck(Module &M);
bool runOnModule(Module &M) override;
};
} // anonymous namespace
INITIALIZE_PASS_BEGIN(CrossDSOCFI, "cross-dso-cfi", "Cross-DSO CFI", false,
false)
INITIALIZE_PASS_END(CrossDSOCFI, "cross-dso-cfi", "Cross-DSO CFI", false, false)
char CrossDSOCFI::ID = 0;
ModulePass *llvm::createCrossDSOCFIPass() { return new CrossDSOCFI; }
/// Extracts a numeric type identifier from an MDNode containing type metadata.
ConstantInt *CrossDSOCFI::extractNumericTypeId(MDNode *MD) {
// This check excludes vtables for classes inside anonymous namespaces.
auto TM = dyn_cast<ValueAsMetadata>(MD->getOperand(1));
if (!TM)
return nullptr;
auto C = dyn_cast_or_null<ConstantInt>(TM->getValue());
if (!C) return nullptr;
// We are looking for i64 constants.
if (C->getBitWidth() != 64) return nullptr;
return C;
}
/// buildCFICheck - emits __cfi_check for the current module.
void CrossDSOCFI::buildCFICheck(Module &M) {
// FIXME: verify that __cfi_check ends up near the end of the code section,
// but before the jump slots created in LowerTypeTests.
SetVector<uint64_t> TypeIds;
SmallVector<MDNode *, 2> Types;
for (GlobalObject &GO : M.global_objects()) {
Types.clear();
GO.getMetadata(LLVMContext::MD_type, Types);
for (MDNode *Type : Types) {
// Sanity check. GO must not be a function declaration.
assert(!isa<Function>(&GO) || !cast<Function>(&GO)->isDeclaration());
if (ConstantInt *TypeId = extractNumericTypeId(Type))
TypeIds.insert(TypeId->getZExtValue());
}
}
NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
if (CfiFunctionsMD) {
for (auto Func : CfiFunctionsMD->operands()) {
assert(Func->getNumOperands() >= 2);
for (unsigned I = 2; I < Func->getNumOperands(); ++I)
if (ConstantInt *TypeId =
extractNumericTypeId(cast<MDNode>(Func->getOperand(I).get())))
TypeIds.insert(TypeId->getZExtValue());
}
}
LLVMContext &Ctx = M.getContext();
Constant *C = M.getOrInsertFunction(
"__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx),
Type::getInt8PtrTy(Ctx), Type::getInt8PtrTy(Ctx));
Function *F = dyn_cast<Function>(C);
// Take over the existing function. The frontend emits a weak stub so that the
// linker knows about the symbol; this pass replaces the function body.
F->deleteBody();
F->setAlignment(4096);
Triple T(M.getTargetTriple());
if (T.isARM() || T.isThumb())
F->addFnAttr("target-features", "+thumb-mode");
auto args = F->arg_begin();
Value &CallSiteTypeId = *(args++);
CallSiteTypeId.setName("CallSiteTypeId");
Value &Addr = *(args++);
Addr.setName("Addr");
Value &CFICheckFailData = *(args++);
CFICheckFailData.setName("CFICheckFailData");
assert(args == F->arg_end());
BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
BasicBlock *TrapBB = BasicBlock::Create(Ctx, "fail", F);
IRBuilder<> IRBFail(TrapBB);
Constant *CFICheckFailFn = M.getOrInsertFunction(
"__cfi_check_fail", Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx),
Type::getInt8PtrTy(Ctx));
IRBFail.CreateCall(CFICheckFailFn, {&CFICheckFailData, &Addr});
IRBFail.CreateBr(ExitBB);
IRBuilder<> IRBExit(ExitBB);
IRBExit.CreateRetVoid();
IRBuilder<> IRB(BB);
SwitchInst *SI = IRB.CreateSwitch(&CallSiteTypeId, TrapBB, TypeIds.size());
for (uint64_t TypeId : TypeIds) {
ConstantInt *CaseTypeId = ConstantInt::get(Type::getInt64Ty(Ctx), TypeId);
BasicBlock *TestBB = BasicBlock::Create(Ctx, "test", F);
IRBuilder<> IRBTest(TestBB);
Function *BitsetTestFn = Intrinsic::getDeclaration(&M, Intrinsic::type_test);
Value *Test = IRBTest.CreateCall(
BitsetTestFn, {&Addr, MetadataAsValue::get(
Ctx, ConstantAsMetadata::get(CaseTypeId))});
BranchInst *BI = IRBTest.CreateCondBr(Test, ExitBB, TrapBB);
BI->setMetadata(LLVMContext::MD_prof, VeryLikelyWeights);
SI->addCase(CaseTypeId, TestBB);
++NumTypeIds;
}
}
bool CrossDSOCFI::runOnModule(Module &M) {
if (skipModule(M))
return false;
VeryLikelyWeights =
MDBuilder(M.getContext()).createBranchWeights((1U << 20) - 1, 1);
if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
return false;
buildCFICheck(M);
return true;
}
PreservedAnalyses CrossDSOCFIPass::run(Module &M, ModuleAnalysisManager &AM) {
CrossDSOCFI Impl;
bool Changed = Impl.runOnModule(M);
if (!Changed)
return PreservedAnalyses::all();
return PreservedAnalyses::none();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,102 +0,0 @@
//===- ElimAvailExtern.cpp - DCE unreachable internal functions -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This transform is designed to eliminate available external global
// definitions from the program, turning them into declarations.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/ElimAvailExtern.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
using namespace llvm;
#define DEBUG_TYPE "elim-avail-extern"
STATISTIC(NumFunctions, "Number of functions removed");
STATISTIC(NumVariables, "Number of global variables removed");
static bool eliminateAvailableExternally(Module &M) {
bool Changed = false;
// Drop initializers of available externally global variables.
for (GlobalVariable &GV : M.globals()) {
if (!GV.hasAvailableExternallyLinkage())
continue;
if (GV.hasInitializer()) {
Constant *Init = GV.getInitializer();
GV.setInitializer(nullptr);
if (isSafeToDestroyConstant(Init))
Init->destroyConstant();
}
GV.removeDeadConstantUsers();
GV.setLinkage(GlobalValue::ExternalLinkage);
NumVariables++;
Changed = true;
}
// Drop the bodies of available externally functions.
for (Function &F : M) {
if (!F.hasAvailableExternallyLinkage())
continue;
if (!F.isDeclaration())
// This will set the linkage to external
F.deleteBody();
F.removeDeadConstantUsers();
NumFunctions++;
Changed = true;
}
return Changed;
}
PreservedAnalyses
EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
if (!eliminateAvailableExternally(M))
return PreservedAnalyses::all();
return PreservedAnalyses::none();
}
namespace {
struct EliminateAvailableExternallyLegacyPass : public ModulePass {
static char ID; // Pass identification, replacement for typeid
EliminateAvailableExternallyLegacyPass() : ModulePass(ID) {
initializeEliminateAvailableExternallyLegacyPassPass(
*PassRegistry::getPassRegistry());
}
// run - Do the EliminateAvailableExternally pass on the specified module,
// optionally updating the specified callgraph to reflect the changes.
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
return eliminateAvailableExternally(M);
}
};
} // end anonymous namespace
char EliminateAvailableExternallyLegacyPass::ID = 0;
INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
"Eliminate Available Externally Globals", false, false)
ModulePass *llvm::createEliminateAvailableExternallyPass() {
return new EliminateAvailableExternallyLegacyPass();
}

View File

@ -1,161 +0,0 @@
//===-- ExtractGV.cpp - Global Value extraction pass ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass extracts global values
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SetVector.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/IPO.h"
#include <algorithm>
using namespace llvm;
/// Make sure GV is visible from both modules. Delete is true if it is
/// being deleted from this module.
/// This also makes sure GV cannot be dropped so that references from
/// the split module remain valid.
static void makeVisible(GlobalValue &GV, bool Delete) {
bool Local = GV.hasLocalLinkage();
if (Local || Delete) {
GV.setLinkage(GlobalValue::ExternalLinkage);
if (Local)
GV.setVisibility(GlobalValue::HiddenVisibility);
return;
}
if (!GV.hasLinkOnceLinkage()) {
assert(!GV.isDiscardableIfUnused());
return;
}
// Map linkonce* to weak* so that llvm doesn't drop this GV.
switch(GV.getLinkage()) {
default:
llvm_unreachable("Unexpected linkage");
case GlobalValue::LinkOnceAnyLinkage:
GV.setLinkage(GlobalValue::WeakAnyLinkage);
return;
case GlobalValue::LinkOnceODRLinkage:
GV.setLinkage(GlobalValue::WeakODRLinkage);
return;
}
}
namespace {
/// @brief A pass to extract specific global values and their dependencies.
class GVExtractorPass : public ModulePass {
SetVector<GlobalValue *> Named;
bool deleteStuff;
public:
static char ID; // Pass identification, replacement for typeid
/// If deleteS is true, this pass deletes the specified global values.
/// Otherwise, it deletes as much of the module as possible, except for the
/// global values specified.
explicit GVExtractorPass(std::vector<GlobalValue*> &GVs,
bool deleteS = true)
: ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {}
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
// Visit the global inline asm.
if (!deleteStuff)
M.setModuleInlineAsm("");
// For simplicity, just give all GlobalValues ExternalLinkage. A trickier
// implementation could figure out which GlobalValues are actually
// referenced by the Named set, and which GlobalValues in the rest of
// the module are referenced by the NamedSet, and get away with leaving
// more internal and private things internal and private. But for now,
// be conservative and simple.
// Visit the GlobalVariables.
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
bool Delete =
deleteStuff == (bool)Named.count(&*I) && !I->isDeclaration();
if (!Delete) {
if (I->hasAvailableExternallyLinkage())
continue;
if (I->getName() == "llvm.global_ctors")
continue;
}
makeVisible(*I, Delete);
if (Delete) {
// Make this a declaration and drop it's comdat.
I->setInitializer(nullptr);
I->setComdat(nullptr);
}
}
// Visit the Functions.
for (Function &F : M) {
bool Delete =
deleteStuff == (bool)Named.count(&F) && !F.isDeclaration();
if (!Delete) {
if (F.hasAvailableExternallyLinkage())
continue;
}
makeVisible(F, Delete);
if (Delete) {
// Make this a declaration and drop it's comdat.
F.deleteBody();
F.setComdat(nullptr);
}
}
// Visit the Aliases.
for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
I != E;) {
Module::alias_iterator CurI = I;
++I;
bool Delete = deleteStuff == (bool)Named.count(&*CurI);
makeVisible(*CurI, Delete);
if (Delete) {
Type *Ty = CurI->getValueType();
CurI->removeFromParent();
llvm::Value *Declaration;
if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage,
CurI->getName(), &M);
} else {
Declaration =
new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage,
nullptr, CurI->getName());
}
CurI->replaceAllUsesWith(Declaration);
delete &*CurI;
}
}
return true;
}
};
char GVExtractorPass::ID = 0;
}
ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue *> &GVs,
bool deleteFn) {
return new GVExtractorPass(GVs, deleteFn);
}

View File

@ -1,124 +0,0 @@
//===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "forceattrs"
static cl::list<std::string>
ForceAttributes("force-attribute", cl::Hidden,
cl::desc("Add an attribute to a function. This should be a "
"pair of 'function-name:attribute-name', for "
"example -force-attribute=foo:noinline. This "
"option can be specified multiple times."));
static Attribute::AttrKind parseAttrKind(StringRef Kind) {
return StringSwitch<Attribute::AttrKind>(Kind)
.Case("alwaysinline", Attribute::AlwaysInline)
.Case("builtin", Attribute::Builtin)
.Case("cold", Attribute::Cold)
.Case("convergent", Attribute::Convergent)
.Case("inlinehint", Attribute::InlineHint)
.Case("jumptable", Attribute::JumpTable)
.Case("minsize", Attribute::MinSize)
.Case("naked", Attribute::Naked)
.Case("nobuiltin", Attribute::NoBuiltin)
.Case("noduplicate", Attribute::NoDuplicate)
.Case("noimplicitfloat", Attribute::NoImplicitFloat)
.Case("noinline", Attribute::NoInline)
.Case("nonlazybind", Attribute::NonLazyBind)
.Case("noredzone", Attribute::NoRedZone)
.Case("noreturn", Attribute::NoReturn)
.Case("norecurse", Attribute::NoRecurse)
.Case("nounwind", Attribute::NoUnwind)
.Case("optnone", Attribute::OptimizeNone)
.Case("optsize", Attribute::OptimizeForSize)
.Case("readnone", Attribute::ReadNone)
.Case("readonly", Attribute::ReadOnly)
.Case("argmemonly", Attribute::ArgMemOnly)
.Case("returns_twice", Attribute::ReturnsTwice)
.Case("safestack", Attribute::SafeStack)
.Case("sanitize_address", Attribute::SanitizeAddress)
.Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
.Case("sanitize_memory", Attribute::SanitizeMemory)
.Case("sanitize_thread", Attribute::SanitizeThread)
.Case("ssp", Attribute::StackProtect)
.Case("sspreq", Attribute::StackProtectReq)
.Case("sspstrong", Attribute::StackProtectStrong)
.Case("strictfp", Attribute::StrictFP)
.Case("uwtable", Attribute::UWTable)
.Default(Attribute::None);
}
/// If F has any forced attributes given on the command line, add them.
static void addForcedAttributes(Function &F) {
for (auto &S : ForceAttributes) {
auto KV = StringRef(S).split(':');
if (KV.first != F.getName())
continue;
auto Kind = parseAttrKind(KV.second);
if (Kind == Attribute::None) {
DEBUG(dbgs() << "ForcedAttribute: " << KV.second
<< " unknown or not handled!\n");
continue;
}
if (F.hasFnAttribute(Kind))
continue;
F.addFnAttr(Kind);
}
}
PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,
ModuleAnalysisManager &) {
if (ForceAttributes.empty())
return PreservedAnalyses::all();
for (Function &F : M.functions())
addForcedAttributes(F);
// Just conservatively invalidate analyses, this isn't likely to be important.
return PreservedAnalyses::none();
}
namespace {
struct ForceFunctionAttrsLegacyPass : public ModulePass {
static char ID; // Pass identification, replacement for typeid
ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
initializeForceFunctionAttrsLegacyPassPass(
*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
if (ForceAttributes.empty())
return false;
for (Function &F : M.functions())
addForcedAttributes(F);
// Conservatively assume we changed something.
return true;
}
};
}
char ForceFunctionAttrsLegacyPass::ID = 0;
INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
"Force set function attributes", false, false)
Pass *llvm::createForceFunctionAttrsLegacyPass() {
return new ForceFunctionAttrsLegacyPass();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,293 +0,0 @@
//===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This transform is designed to eliminate unreachable internal globals from the
// program. It uses an aggressive algorithm, searching out globals that are
// known to be alive. After it finds all of the globals which are needed, it
// deletes whatever is left over. This allows it to delete recursive chunks of
// the program which are unreachable.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/GlobalDCE.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/CtorUtils.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
using namespace llvm;
#define DEBUG_TYPE "globaldce"
STATISTIC(NumAliases , "Number of global aliases removed");
STATISTIC(NumFunctions, "Number of functions removed");
STATISTIC(NumIFuncs, "Number of indirect functions removed");
STATISTIC(NumVariables, "Number of global variables removed");
namespace {
class GlobalDCELegacyPass : public ModulePass {
public:
static char ID; // Pass identification, replacement for typeid
GlobalDCELegacyPass() : ModulePass(ID) {
initializeGlobalDCELegacyPassPass(*PassRegistry::getPassRegistry());
}
// run - Do the GlobalDCE pass on the specified module, optionally updating
// the specified callgraph to reflect the changes.
//
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
// We need a minimally functional dummy module analysis manager. It needs
// to at least know about the possibility of proxying a function analysis
// manager.
FunctionAnalysisManager DummyFAM;
ModuleAnalysisManager DummyMAM;
DummyMAM.registerPass(
[&] { return FunctionAnalysisManagerModuleProxy(DummyFAM); });
auto PA = Impl.run(M, DummyMAM);
return !PA.areAllPreserved();
}
private:
GlobalDCEPass Impl;
};
}
char GlobalDCELegacyPass::ID = 0;
INITIALIZE_PASS(GlobalDCELegacyPass, "globaldce",
"Dead Global Elimination", false, false)
// Public interface to the GlobalDCEPass.
ModulePass *llvm::createGlobalDCEPass() {
return new GlobalDCELegacyPass();
}
/// Returns true if F contains only a single "ret" instruction.
static bool isEmptyFunction(Function *F) {
BasicBlock &Entry = F->getEntryBlock();
if (Entry.size() != 1 || !isa<ReturnInst>(Entry.front()))
return false;
ReturnInst &RI = cast<ReturnInst>(Entry.front());
return RI.getReturnValue() == nullptr;
}
/// Compute the set of GlobalValue that depends from V.
/// The recursion stops as soon as a GlobalValue is met.
void GlobalDCEPass::ComputeDependencies(Value *V,
SmallPtrSetImpl<GlobalValue *> &Deps) {
if (auto *I = dyn_cast<Instruction>(V)) {
Function *Parent = I->getParent()->getParent();
Deps.insert(Parent);
} else if (auto *GV = dyn_cast<GlobalValue>(V)) {
Deps.insert(GV);
} else if (auto *CE = dyn_cast<Constant>(V)) {
// Avoid walking the whole tree of a big ConstantExprs multiple times.
auto Where = ConstantDependenciesCache.find(CE);
if (Where != ConstantDependenciesCache.end()) {
auto const &K = Where->second;
Deps.insert(K.begin(), K.end());
} else {
SmallPtrSetImpl<GlobalValue *> &LocalDeps = ConstantDependenciesCache[CE];
for (User *CEUser : CE->users())
ComputeDependencies(CEUser, LocalDeps);
Deps.insert(LocalDeps.begin(), LocalDeps.end());
}
}
}
void GlobalDCEPass::UpdateGVDependencies(GlobalValue &GV) {
SmallPtrSet<GlobalValue *, 8> Deps;
for (User *User : GV.users())
ComputeDependencies(User, Deps);
Deps.erase(&GV); // Remove self-reference.
for (GlobalValue *GVU : Deps) {
GVDependencies[GVU].insert(&GV);
}
}
/// Mark Global value as Live
void GlobalDCEPass::MarkLive(GlobalValue &GV,
SmallVectorImpl<GlobalValue *> *Updates) {
auto const Ret = AliveGlobals.insert(&GV);
if (!Ret.second)
return;
if (Updates)
Updates->push_back(&GV);
if (Comdat *C = GV.getComdat()) {
for (auto &&CM : make_range(ComdatMembers.equal_range(C)))
MarkLive(*CM.second, Updates); // Recursion depth is only two because only
// globals in the same comdat are visited.
}
}
PreservedAnalyses GlobalDCEPass::run(Module &M, ModuleAnalysisManager &MAM) {
bool Changed = false;
// The algorithm first computes the set L of global variables that are
// trivially live. Then it walks the initialization of these variables to
// compute the globals used to initialize them, which effectively builds a
// directed graph where nodes are global variables, and an edge from A to B
// means B is used to initialize A. Finally, it propagates the liveness
// information through the graph starting from the nodes in L. Nodes note
// marked as alive are discarded.
// Remove empty functions from the global ctors list.
Changed |= optimizeGlobalCtorsList(M, isEmptyFunction);
// Collect the set of members for each comdat.
for (Function &F : M)
if (Comdat *C = F.getComdat())
ComdatMembers.insert(std::make_pair(C, &F));
for (GlobalVariable &GV : M.globals())
if (Comdat *C = GV.getComdat())
ComdatMembers.insert(std::make_pair(C, &GV));
for (GlobalAlias &GA : M.aliases())
if (Comdat *C = GA.getComdat())
ComdatMembers.insert(std::make_pair(C, &GA));
// Loop over the module, adding globals which are obviously necessary.
for (GlobalObject &GO : M.global_objects()) {
Changed |= RemoveUnusedGlobalValue(GO);
// Functions with external linkage are needed if they have a body.
// Externally visible & appending globals are needed, if they have an
// initializer.
if (!GO.isDeclaration() && !GO.hasAvailableExternallyLinkage())
if (!GO.isDiscardableIfUnused())
MarkLive(GO);
UpdateGVDependencies(GO);
}
// Compute direct dependencies of aliases.
for (GlobalAlias &GA : M.aliases()) {
Changed |= RemoveUnusedGlobalValue(GA);
// Externally visible aliases are needed.
if (!GA.isDiscardableIfUnused())
MarkLive(GA);
UpdateGVDependencies(GA);
}
// Compute direct dependencies of ifuncs.
for (GlobalIFunc &GIF : M.ifuncs()) {
Changed |= RemoveUnusedGlobalValue(GIF);
// Externally visible ifuncs are needed.
if (!GIF.isDiscardableIfUnused())
MarkLive(GIF);
UpdateGVDependencies(GIF);
}
// Propagate liveness from collected Global Values through the computed
// dependencies.
SmallVector<GlobalValue *, 8> NewLiveGVs{AliveGlobals.begin(),
AliveGlobals.end()};
while (!NewLiveGVs.empty()) {
GlobalValue *LGV = NewLiveGVs.pop_back_val();
for (auto *GVD : GVDependencies[LGV])
MarkLive(*GVD, &NewLiveGVs);
}
// Now that all globals which are needed are in the AliveGlobals set, we loop
// through the program, deleting those which are not alive.
//
// The first pass is to drop initializers of global variables which are dead.
std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals
for (GlobalVariable &GV : M.globals())
if (!AliveGlobals.count(&GV)) {
DeadGlobalVars.push_back(&GV); // Keep track of dead globals
if (GV.hasInitializer()) {
Constant *Init = GV.getInitializer();
GV.setInitializer(nullptr);
if (isSafeToDestroyConstant(Init))
Init->destroyConstant();
}
}
// The second pass drops the bodies of functions which are dead...
std::vector<Function *> DeadFunctions;
for (Function &F : M)
if (!AliveGlobals.count(&F)) {
DeadFunctions.push_back(&F); // Keep track of dead globals
if (!F.isDeclaration())
F.deleteBody();
}
// The third pass drops targets of aliases which are dead...
std::vector<GlobalAlias*> DeadAliases;
for (GlobalAlias &GA : M.aliases())
if (!AliveGlobals.count(&GA)) {
DeadAliases.push_back(&GA);
GA.setAliasee(nullptr);
}
// The fourth pass drops targets of ifuncs which are dead...
std::vector<GlobalIFunc*> DeadIFuncs;
for (GlobalIFunc &GIF : M.ifuncs())
if (!AliveGlobals.count(&GIF)) {
DeadIFuncs.push_back(&GIF);
GIF.setResolver(nullptr);
}
// Now that all interferences have been dropped, delete the actual objects
// themselves.
auto EraseUnusedGlobalValue = [&](GlobalValue *GV) {
RemoveUnusedGlobalValue(*GV);
GV->eraseFromParent();
Changed = true;
};
NumFunctions += DeadFunctions.size();
for (Function *F : DeadFunctions)
EraseUnusedGlobalValue(F);
NumVariables += DeadGlobalVars.size();
for (GlobalVariable *GV : DeadGlobalVars)
EraseUnusedGlobalValue(GV);
NumAliases += DeadAliases.size();
for (GlobalAlias *GA : DeadAliases)
EraseUnusedGlobalValue(GA);
NumIFuncs += DeadIFuncs.size();
for (GlobalIFunc *GIF : DeadIFuncs)
EraseUnusedGlobalValue(GIF);
// Make sure that all memory is released
AliveGlobals.clear();
ConstantDependenciesCache.clear();
GVDependencies.clear();
ComdatMembers.clear();
if (Changed)
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}
// RemoveUnusedGlobalValue - Loop over all of the uses of the specified
// GlobalValue, looking for the constant pointer ref that may be pointing to it.
// If found, check to see if the constant pointer ref is safe to destroy, and if
// so, nuke it. This will reduce the reference count on the global value, which
// might make it deader.
//
bool GlobalDCEPass::RemoveUnusedGlobalValue(GlobalValue &GV) {
if (GV.use_empty())
return false;
GV.removeDeadConstantUsers();
return GV.use_empty();
}

View File

@ -1 +0,0 @@
e0bbf45d316aaf0b6cca9720829810e0970d8e86

View File

@ -1,193 +0,0 @@
//===- GlobalSplit.cpp - global variable splitter -------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass uses inrange annotations on GEP indices to split globals where
// beneficial. Clang currently attaches these annotations to references to
// virtual table globals under the Itanium ABI for the benefit of the
// whole-program virtual call optimization and control flow integrity passes.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/GlobalSplit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Transforms/IPO.h"
#include <cstdint>
#include <vector>
using namespace llvm;
static bool splitGlobal(GlobalVariable &GV) {
// If the address of the global is taken outside of the module, we cannot
// apply this transformation.
if (!GV.hasLocalLinkage())
return false;
// We currently only know how to split ConstantStructs.
auto *Init = dyn_cast_or_null<ConstantStruct>(GV.getInitializer());
if (!Init)
return false;
// Verify that each user of the global is an inrange getelementptr constant.
// From this it follows that any loads from or stores to that global must use
// a pointer derived from an inrange getelementptr constant, which is
// sufficient to allow us to apply the splitting transform.
for (User *U : GV.users()) {
if (!isa<Constant>(U))
return false;
auto *GEP = dyn_cast<GEPOperator>(U);
if (!GEP || !GEP->getInRangeIndex() || *GEP->getInRangeIndex() != 1 ||
!isa<ConstantInt>(GEP->getOperand(1)) ||
!cast<ConstantInt>(GEP->getOperand(1))->isZero() ||
!isa<ConstantInt>(GEP->getOperand(2)))
return false;
}
SmallVector<MDNode *, 2> Types;
GV.getMetadata(LLVMContext::MD_type, Types);
const DataLayout &DL = GV.getParent()->getDataLayout();
const StructLayout *SL = DL.getStructLayout(Init->getType());
IntegerType *Int32Ty = Type::getInt32Ty(GV.getContext());
std::vector<GlobalVariable *> SplitGlobals(Init->getNumOperands());
for (unsigned I = 0; I != Init->getNumOperands(); ++I) {
// Build a global representing this split piece.
auto *SplitGV =
new GlobalVariable(*GV.getParent(), Init->getOperand(I)->getType(),
GV.isConstant(), GlobalValue::PrivateLinkage,
Init->getOperand(I), GV.getName() + "." + utostr(I));
SplitGlobals[I] = SplitGV;
unsigned SplitBegin = SL->getElementOffset(I);
unsigned SplitEnd = (I == Init->getNumOperands() - 1)
? SL->getSizeInBytes()
: SL->getElementOffset(I + 1);
// Rebuild type metadata, adjusting by the split offset.
// FIXME: See if we can use DW_OP_piece to preserve debug metadata here.
for (MDNode *Type : Types) {
uint64_t ByteOffset = cast<ConstantInt>(
cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
->getZExtValue();
// Type metadata may be attached one byte after the end of the vtable, for
// classes without virtual methods in Itanium ABI. AFAIK, it is never
// attached to the first byte of a vtable. Subtract one to get the right
// slice.
// This is making an assumption that vtable groups are the only kinds of
// global variables that !type metadata can be attached to, and that they
// are either Itanium ABI vtable groups or contain a single vtable (i.e.
// Microsoft ABI vtables).
uint64_t AttachedTo = (ByteOffset == 0) ? ByteOffset : ByteOffset - 1;
if (AttachedTo < SplitBegin || AttachedTo >= SplitEnd)
continue;
SplitGV->addMetadata(
LLVMContext::MD_type,
*MDNode::get(GV.getContext(),
{ConstantAsMetadata::get(
ConstantInt::get(Int32Ty, ByteOffset - SplitBegin)),
Type->getOperand(1)}));
}
}
for (User *U : GV.users()) {
auto *GEP = cast<GEPOperator>(U);
unsigned I = cast<ConstantInt>(GEP->getOperand(2))->getZExtValue();
if (I >= SplitGlobals.size())
continue;
SmallVector<Value *, 4> Ops;
Ops.push_back(ConstantInt::get(Int32Ty, 0));
for (unsigned I = 3; I != GEP->getNumOperands(); ++I)
Ops.push_back(GEP->getOperand(I));
auto *NewGEP = ConstantExpr::getGetElementPtr(
SplitGlobals[I]->getInitializer()->getType(), SplitGlobals[I], Ops,
GEP->isInBounds());
GEP->replaceAllUsesWith(NewGEP);
}
// Finally, remove the original global. Any remaining uses refer to invalid
// elements of the global, so replace with undef.
if (!GV.use_empty())
GV.replaceAllUsesWith(UndefValue::get(GV.getType()));
GV.eraseFromParent();
return true;
}
static bool splitGlobals(Module &M) {
// First, see if the module uses either of the llvm.type.test or
// llvm.type.checked.load intrinsics, which indicates that splitting globals
// may be beneficial.
Function *TypeTestFunc =
M.getFunction(Intrinsic::getName(Intrinsic::type_test));
Function *TypeCheckedLoadFunc =
M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load));
if ((!TypeTestFunc || TypeTestFunc->use_empty()) &&
(!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty()))
return false;
bool Changed = false;
for (auto I = M.global_begin(); I != M.global_end();) {
GlobalVariable &GV = *I;
++I;
Changed |= splitGlobal(GV);
}
return Changed;
}
namespace {
struct GlobalSplit : public ModulePass {
static char ID;
GlobalSplit() : ModulePass(ID) {
initializeGlobalSplitPass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
return splitGlobals(M);
}
};
} // end anonymous namespace
char GlobalSplit::ID = 0;
INITIALIZE_PASS(GlobalSplit, "globalsplit", "Global splitter", false, false)
ModulePass *llvm::createGlobalSplitPass() {
return new GlobalSplit;
}
PreservedAnalyses GlobalSplitPass::run(Module &M, ModuleAnalysisManager &AM) {
if (!splitGlobals(M))
return PreservedAnalyses::all();
return PreservedAnalyses::none();
}

View File

@ -1,286 +0,0 @@
//===-- IPConstantPropagation.cpp - Propagate constants through calls -----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass implements an _extremely_ simple interprocedural constant
// propagation pass. It could certainly be improved in many different ways,
// like using a worklist. This pass makes arguments dead, but does not remove
// them. The existing dead argument elimination pass should be run after this
// to clean up the mess.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/IPO.h"
using namespace llvm;
#define DEBUG_TYPE "ipconstprop"
STATISTIC(NumArgumentsProped, "Number of args turned into constants");
STATISTIC(NumReturnValProped, "Number of return values turned into constants");
namespace {
/// IPCP - The interprocedural constant propagation pass
///
struct IPCP : public ModulePass {
static char ID; // Pass identification, replacement for typeid
IPCP() : ModulePass(ID) {
initializeIPCPPass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override;
};
}
/// PropagateConstantsIntoArguments - Look at all uses of the specified
/// function. If all uses are direct call sites, and all pass a particular
/// constant in for an argument, propagate that constant in as the argument.
///
static bool PropagateConstantsIntoArguments(Function &F) {
if (F.arg_empty() || F.use_empty()) return false; // No arguments? Early exit.
// For each argument, keep track of its constant value and whether it is a
// constant or not. The bool is driven to true when found to be non-constant.
SmallVector<std::pair<Constant*, bool>, 16> ArgumentConstants;
ArgumentConstants.resize(F.arg_size());
unsigned NumNonconstant = 0;
for (Use &U : F.uses()) {
User *UR = U.getUser();
// Ignore blockaddress uses.
if (isa<BlockAddress>(UR)) continue;
// Used by a non-instruction, or not the callee of a function, do not
// transform.
if (!isa<CallInst>(UR) && !isa<InvokeInst>(UR))
return false;
CallSite CS(cast<Instruction>(UR));
if (!CS.isCallee(&U))
return false;
// Check out all of the potentially constant arguments. Note that we don't
// inspect varargs here.
CallSite::arg_iterator AI = CS.arg_begin();
Function::arg_iterator Arg = F.arg_begin();
for (unsigned i = 0, e = ArgumentConstants.size(); i != e;
++i, ++AI, ++Arg) {
// If this argument is known non-constant, ignore it.
if (ArgumentConstants[i].second)
continue;
Constant *C = dyn_cast<Constant>(*AI);
if (C && ArgumentConstants[i].first == nullptr) {
ArgumentConstants[i].first = C; // First constant seen.
} else if (C && ArgumentConstants[i].first == C) {
// Still the constant value we think it is.
} else if (*AI == &*Arg) {
// Ignore recursive calls passing argument down.
} else {
// Argument became non-constant. If all arguments are non-constant now,
// give up on this function.
if (++NumNonconstant == ArgumentConstants.size())
return false;
ArgumentConstants[i].second = true;
}
}
}
// If we got to this point, there is a constant argument!
assert(NumNonconstant != ArgumentConstants.size());
bool MadeChange = false;
Function::arg_iterator AI = F.arg_begin();
for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI) {
// Do we have a constant argument?
if (ArgumentConstants[i].second || AI->use_empty() ||
AI->hasInAllocaAttr() || (AI->hasByValAttr() && !F.onlyReadsMemory()))
continue;
Value *V = ArgumentConstants[i].first;
if (!V) V = UndefValue::get(AI->getType());
AI->replaceAllUsesWith(V);
++NumArgumentsProped;
MadeChange = true;
}
return MadeChange;
}
// Check to see if this function returns one or more constants. If so, replace
// all callers that use those return values with the constant value. This will
// leave in the actual return values and instructions, but deadargelim will
// clean that up.
//
// Additionally if a function always returns one of its arguments directly,
// callers will be updated to use the value they pass in directly instead of
// using the return value.
static bool PropagateConstantReturn(Function &F) {
if (F.getReturnType()->isVoidTy())
return false; // No return value.
// We can infer and propagate the return value only when we know that the
// definition we'll get at link time is *exactly* the definition we see now.
// For more details, see GlobalValue::mayBeDerefined.
if (!F.isDefinitionExact())
return false;
// Don't touch naked functions. The may contain asm returning
// value we don't see, so we may end up interprocedurally propagating
// the return value incorrectly.
if (F.hasFnAttribute(Attribute::Naked))
return false;
// Check to see if this function returns a constant.
SmallVector<Value *,4> RetVals;
StructType *STy = dyn_cast<StructType>(F.getReturnType());
if (STy)
for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i)
RetVals.push_back(UndefValue::get(STy->getElementType(i)));
else
RetVals.push_back(UndefValue::get(F.getReturnType()));
unsigned NumNonConstant = 0;
for (BasicBlock &BB : F)
if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
for (unsigned i = 0, e = RetVals.size(); i != e; ++i) {
// Already found conflicting return values?
Value *RV = RetVals[i];
if (!RV)
continue;
// Find the returned value
Value *V;
if (!STy)
V = RI->getOperand(0);
else
V = FindInsertedValue(RI->getOperand(0), i);
if (V) {
// Ignore undefs, we can change them into anything
if (isa<UndefValue>(V))
continue;
// Try to see if all the rets return the same constant or argument.
if (isa<Constant>(V) || isa<Argument>(V)) {
if (isa<UndefValue>(RV)) {
// No value found yet? Try the current one.
RetVals[i] = V;
continue;
}
// Returning the same value? Good.
if (RV == V)
continue;
}
}
// Different or no known return value? Don't propagate this return
// value.
RetVals[i] = nullptr;
// All values non-constant? Stop looking.
if (++NumNonConstant == RetVals.size())
return false;
}
}
// If we got here, the function returns at least one constant value. Loop
// over all users, replacing any uses of the return value with the returned
// constant.
bool MadeChange = false;
for (Use &U : F.uses()) {
CallSite CS(U.getUser());
Instruction* Call = CS.getInstruction();
// Not a call instruction or a call instruction that's not calling F
// directly?
if (!Call || !CS.isCallee(&U))
continue;
// Call result not used?
if (Call->use_empty())
continue;
MadeChange = true;
if (!STy) {
Value* New = RetVals[0];
if (Argument *A = dyn_cast<Argument>(New))
// Was an argument returned? Then find the corresponding argument in
// the call instruction and use that.
New = CS.getArgument(A->getArgNo());
Call->replaceAllUsesWith(New);
continue;
}
for (auto I = Call->user_begin(), E = Call->user_end(); I != E;) {
Instruction *Ins = cast<Instruction>(*I);
// Increment now, so we can remove the use
++I;
// Find the index of the retval to replace with
int index = -1;
if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Ins))
if (EV->hasIndices())
index = *EV->idx_begin();
// If this use uses a specific return value, and we have a replacement,
// replace it.
if (index != -1) {
Value *New = RetVals[index];
if (New) {
if (Argument *A = dyn_cast<Argument>(New))
// Was an argument returned? Then find the corresponding argument in
// the call instruction and use that.
New = CS.getArgument(A->getArgNo());
Ins->replaceAllUsesWith(New);
Ins->eraseFromParent();
}
}
}
}
if (MadeChange) ++NumReturnValProped;
return MadeChange;
}
char IPCP::ID = 0;
INITIALIZE_PASS(IPCP, "ipconstprop",
"Interprocedural constant propagation", false, false)
ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); }
bool IPCP::runOnModule(Module &M) {
if (skipModule(M))
return false;
bool Changed = false;
bool LocalChange = true;
// FIXME: instead of using smart algorithms, we just iterate until we stop
// making changes.
while (LocalChange) {
LocalChange = false;
for (Function &F : M)
if (!F.isDeclaration()) {
// Delete any klingons.
F.removeDeadConstantUsers();
if (F.hasLocalLinkage())
LocalChange |= PropagateConstantsIntoArguments(F);
Changed |= PropagateConstantReturn(F);
}
Changed |= LocalChange;
}
return Changed;
}

View File

@ -1,128 +0,0 @@
//===-- IPO.cpp -----------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the common infrastructure (including C bindings) for
// libLLVMIPO.a, which implements several transformations over the LLVM
// intermediate representation.
//
//===----------------------------------------------------------------------===//
#include "llvm-c/Transforms/IPO.h"
#include "llvm-c/Initialization.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/InitializePasses.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include "llvm/Transforms/IPO/FunctionAttrs.h"
using namespace llvm;
void llvm::initializeIPO(PassRegistry &Registry) {
initializeArgPromotionPass(Registry);
initializeCalledValuePropagationLegacyPassPass(Registry);
initializeConstantMergeLegacyPassPass(Registry);
initializeCrossDSOCFIPass(Registry);
initializeDAEPass(Registry);
initializeDAHPass(Registry);
initializeForceFunctionAttrsLegacyPassPass(Registry);
initializeGlobalDCELegacyPassPass(Registry);
initializeGlobalOptLegacyPassPass(Registry);
initializeGlobalSplitPass(Registry);
initializeIPCPPass(Registry);
initializeAlwaysInlinerLegacyPassPass(Registry);
initializeSimpleInlinerPass(Registry);
initializeInferFunctionAttrsLegacyPassPass(Registry);
initializeInternalizeLegacyPassPass(Registry);
initializeLoopExtractorPass(Registry);
initializeBlockExtractorPassPass(Registry);
initializeSingleLoopExtractorPass(Registry);
initializeLowerTypeTestsPass(Registry);
initializeMergeFunctionsPass(Registry);
initializePartialInlinerLegacyPassPass(Registry);
initializePostOrderFunctionAttrsLegacyPassPass(Registry);
initializeReversePostOrderFunctionAttrsLegacyPassPass(Registry);
initializePruneEHPass(Registry);
initializeStripDeadPrototypesLegacyPassPass(Registry);
initializeStripSymbolsPass(Registry);
initializeStripDebugDeclarePass(Registry);
initializeStripDeadDebugInfoPass(Registry);
initializeStripNonDebugSymbolsPass(Registry);
initializeBarrierNoopPass(Registry);
initializeEliminateAvailableExternallyLegacyPassPass(Registry);
initializeSampleProfileLoaderLegacyPassPass(Registry);
initializeFunctionImportLegacyPassPass(Registry);
initializeWholeProgramDevirtPass(Registry);
}
void LLVMInitializeIPO(LLVMPassRegistryRef R) {
initializeIPO(*unwrap(R));
}
void LLVMAddArgumentPromotionPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createArgumentPromotionPass());
}
void LLVMAddCalledValuePropagationPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createCalledValuePropagationPass());
}
void LLVMAddConstantMergePass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createConstantMergePass());
}
void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createDeadArgEliminationPass());
}
void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createPostOrderFunctionAttrsLegacyPass());
}
void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createFunctionInliningPass());
}
void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(llvm::createAlwaysInlinerLegacyPass());
}
void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createGlobalDCEPass());
}
void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createGlobalOptimizerPass());
}
void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createIPConstantPropagationPass());
}
void LLVMAddPruneEHPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createPruneEHPass());
}
void LLVMAddIPSCCPPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createIPSCCPPass());
}
void LLVMAddInternalizePass(LLVMPassManagerRef PM, unsigned AllButMain) {
auto PreserveMain = [=](const GlobalValue &GV) {
return AllButMain && GV.getName() == "main";
};
unwrap(PM)->add(createInternalizePass(PreserveMain));
}
void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createStripDeadPrototypesPass());
}
void LLVMAddStripSymbolsPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createStripSymbolsPass());
}

View File

@ -1,79 +0,0 @@
//===- InferFunctionAttrs.cpp - Infer implicit function attributes --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/InferFunctionAttrs.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
using namespace llvm;
#define DEBUG_TYPE "inferattrs"
static bool inferAllPrototypeAttributes(Module &M,
const TargetLibraryInfo &TLI) {
bool Changed = false;
for (Function &F : M.functions())
// We only infer things using the prototype and the name; we don't need
// definitions.
if (F.isDeclaration() && !F.hasFnAttribute((Attribute::OptimizeNone)))
Changed |= inferLibFuncAttributes(F, TLI);
return Changed;
}
PreservedAnalyses InferFunctionAttrsPass::run(Module &M,
ModuleAnalysisManager &AM) {
auto &TLI = AM.getResult<TargetLibraryAnalysis>(M);
if (!inferAllPrototypeAttributes(M, TLI))
// If we didn't infer anything, preserve all analyses.
return PreservedAnalyses::all();
// Otherwise, we may have changed fundamental function attributes, so clear
// out all the passes.
return PreservedAnalyses::none();
}
namespace {
struct InferFunctionAttrsLegacyPass : public ModulePass {
static char ID; // Pass identification, replacement for typeid
InferFunctionAttrsLegacyPass() : ModulePass(ID) {
initializeInferFunctionAttrsLegacyPassPass(
*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<TargetLibraryInfoWrapperPass>();
}
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
return inferAllPrototypeAttributes(M, TLI);
}
};
}
char InferFunctionAttrsLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(InferFunctionAttrsLegacyPass, "inferattrs",
"Infer set function attributes", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(InferFunctionAttrsLegacyPass, "inferattrs",
"Infer set function attributes", false, false)
Pass *llvm::createInferFunctionAttrsLegacyPass() {
return new InferFunctionAttrsLegacyPass();
}

View File

@ -1,125 +0,0 @@
//===- InlineSimple.cpp - Code to perform simple function inlining --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements bottom-up inlining of functions into callees.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/Inliner.h"
using namespace llvm;
#define DEBUG_TYPE "inline"
namespace {
/// \brief Actual inliner pass implementation.
///
/// The common implementation of the inlining logic is shared between this
/// inliner pass and the always inliner pass. The two passes use different cost
/// analyses to determine when to inline.
class SimpleInliner : public LegacyInlinerBase {
InlineParams Params;
public:
SimpleInliner() : LegacyInlinerBase(ID), Params(llvm::getInlineParams()) {
initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
}
explicit SimpleInliner(InlineParams Params)
: LegacyInlinerBase(ID), Params(std::move(Params)) {
initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
}
static char ID; // Pass identification, replacement for typeid
InlineCost getInlineCost(CallSite CS) override {
Function *Callee = CS.getCalledFunction();
TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
bool RemarksEnabled = false;
const auto &BBs = CS.getCaller()->getBasicBlockList();
if (!BBs.empty()) {
auto DI = OptimizationRemark(DEBUG_TYPE, "", DebugLoc(), &BBs.front());
if (DI.isEnabled())
RemarksEnabled = true;
}
OptimizationRemarkEmitter ORE(CS.getCaller());
std::function<AssumptionCache &(Function &)> GetAssumptionCache =
[&](Function &F) -> AssumptionCache & {
return ACT->getAssumptionCache(F);
};
return llvm::getInlineCost(CS, Params, TTI, GetAssumptionCache,
/*GetBFI=*/None, PSI,
RemarksEnabled ? &ORE : nullptr);
}
bool runOnSCC(CallGraphSCC &SCC) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
private:
TargetTransformInfoWrapperPass *TTIWP;
};
} // end anonymous namespace
char SimpleInliner::ID = 0;
INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", "Function Integration/Inlining",
false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(SimpleInliner, "inline", "Function Integration/Inlining",
false, false)
Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); }
Pass *llvm::createFunctionInliningPass(int Threshold) {
return new SimpleInliner(llvm::getInlineParams(Threshold));
}
Pass *llvm::createFunctionInliningPass(unsigned OptLevel,
unsigned SizeOptLevel,
bool DisableInlineHotCallSite) {
auto Param = llvm::getInlineParams(OptLevel, SizeOptLevel);
if (DisableInlineHotCallSite)
Param.HotCallSiteThreshold = 0;
return new SimpleInliner(Param);
}
Pass *llvm::createFunctionInliningPass(InlineParams &Params) {
return new SimpleInliner(Params);
}
bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) {
TTIWP = &getAnalysis<TargetTransformInfoWrapperPass>();
return LegacyInlinerBase::runOnSCC(SCC);
}
void SimpleInliner::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetTransformInfoWrapperPass>();
LegacyInlinerBase::getAnalysisUsage(AU);
}

Some files were not shown because too many files have changed in this diff Show More