[Transforms] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC).
llvm-svn: 315383
This commit is contained in:
parent
bb0e316dc7
commit
e9ea08a097
|
@ -20,16 +20,18 @@
|
||||||
#ifndef LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
|
#ifndef LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
|
||||||
#define LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
|
#define LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
|
||||||
|
|
||||||
#include "llvm/IR/Module.h"
|
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
|
||||||
/// A pass that merges duplicate global constants into a single constant.
|
/// A pass that merges duplicate global constants into a single constant.
|
||||||
class ConstantMergePass : public PassInfoMixin<ConstantMergePass> {
|
class ConstantMergePass : public PassInfoMixin<ConstantMergePass> {
|
||||||
public:
|
public:
|
||||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
|
#endif // LLVM_TRANSFORMS_IPO_CONSTANTMERGE_H
|
||||||
|
|
|
@ -20,15 +20,21 @@
|
||||||
#ifndef LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
|
#ifndef LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
|
||||||
#define LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
|
#define LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
|
||||||
|
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/ADT/Twine.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
class Use;
|
||||||
|
class Value;
|
||||||
|
|
||||||
/// Eliminate dead arguments (and return values) from functions.
|
/// Eliminate dead arguments (and return values) from functions.
|
||||||
class DeadArgumentEliminationPass
|
class DeadArgumentEliminationPass
|
||||||
: public PassInfoMixin<DeadArgumentEliminationPass> {
|
: public PassInfoMixin<DeadArgumentEliminationPass> {
|
||||||
|
@ -37,12 +43,13 @@ public:
|
||||||
/// argument. Used so that arguments and return values can be used
|
/// argument. Used so that arguments and return values can be used
|
||||||
/// interchangeably.
|
/// interchangeably.
|
||||||
struct RetOrArg {
|
struct RetOrArg {
|
||||||
RetOrArg(const Function *F, unsigned Idx, bool IsArg)
|
|
||||||
: F(F), Idx(Idx), IsArg(IsArg) {}
|
|
||||||
const Function *F;
|
const Function *F;
|
||||||
unsigned Idx;
|
unsigned Idx;
|
||||||
bool IsArg;
|
bool IsArg;
|
||||||
|
|
||||||
|
RetOrArg(const Function *F, unsigned Idx, bool IsArg)
|
||||||
|
: F(F), Idx(Idx), IsArg(IsArg) {}
|
||||||
|
|
||||||
/// Make RetOrArg comparable, so we can put it into a map.
|
/// Make RetOrArg comparable, so we can put it into a map.
|
||||||
bool operator<(const RetOrArg &O) const {
|
bool operator<(const RetOrArg &O) const {
|
||||||
return std::tie(F, Idx, IsArg) < std::tie(O.F, O.Idx, O.IsArg);
|
return std::tie(F, Idx, IsArg) < std::tie(O.F, O.Idx, O.IsArg);
|
||||||
|
@ -67,16 +74,23 @@ public:
|
||||||
/// thus become dead in the end.
|
/// thus become dead in the end.
|
||||||
enum Liveness { Live, MaybeLive };
|
enum Liveness { Live, MaybeLive };
|
||||||
|
|
||||||
|
DeadArgumentEliminationPass(bool ShouldHackArguments_ = false)
|
||||||
|
: ShouldHackArguments(ShouldHackArguments_) {}
|
||||||
|
|
||||||
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
|
||||||
|
|
||||||
/// Convenience wrapper
|
/// Convenience wrapper
|
||||||
RetOrArg CreateRet(const Function *F, unsigned Idx) {
|
RetOrArg CreateRet(const Function *F, unsigned Idx) {
|
||||||
return RetOrArg(F, Idx, false);
|
return RetOrArg(F, Idx, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience wrapper
|
/// Convenience wrapper
|
||||||
RetOrArg CreateArg(const Function *F, unsigned Idx) {
|
RetOrArg CreateArg(const Function *F, unsigned Idx) {
|
||||||
return RetOrArg(F, Idx, true);
|
return RetOrArg(F, Idx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::multimap<RetOrArg, RetOrArg> UseMap;
|
using UseMap = std::multimap<RetOrArg, RetOrArg>;
|
||||||
|
|
||||||
/// This maps a return value or argument to any MaybeLive return values or
|
/// This maps a return value or argument to any MaybeLive return values or
|
||||||
/// arguments it uses. This allows the MaybeLive values to be marked live
|
/// arguments it uses. This allows the MaybeLive values to be marked live
|
||||||
/// when any of its users is marked live.
|
/// when any of its users is marked live.
|
||||||
|
@ -93,25 +107,21 @@ public:
|
||||||
/// directly to F.
|
/// directly to F.
|
||||||
UseMap Uses;
|
UseMap Uses;
|
||||||
|
|
||||||
typedef std::set<RetOrArg> LiveSet;
|
using LiveSet = std::set<RetOrArg>;
|
||||||
typedef std::set<const Function *> LiveFuncSet;
|
using LiveFuncSet = std::set<const Function *>;
|
||||||
|
|
||||||
/// This set contains all values that have been determined to be live.
|
/// This set contains all values that have been determined to be live.
|
||||||
LiveSet LiveValues;
|
LiveSet LiveValues;
|
||||||
|
|
||||||
/// This set contains all values that are cannot be changed in any way.
|
/// This set contains all values that are cannot be changed in any way.
|
||||||
LiveFuncSet LiveFunctions;
|
LiveFuncSet LiveFunctions;
|
||||||
|
|
||||||
typedef SmallVector<RetOrArg, 5> UseVector;
|
using UseVector = SmallVector<RetOrArg, 5>;
|
||||||
|
|
||||||
/// This allows this pass to do double-duty as the dead arg hacking pass
|
/// This allows this pass to do double-duty as the dead arg hacking pass
|
||||||
/// (used only by bugpoint).
|
/// (used only by bugpoint).
|
||||||
bool ShouldHackArguments = false;
|
bool ShouldHackArguments = false;
|
||||||
|
|
||||||
public:
|
|
||||||
DeadArgumentEliminationPass(bool ShouldHackArguments_ = false)
|
|
||||||
: ShouldHackArguments(ShouldHackArguments_) {}
|
|
||||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Liveness MarkIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses);
|
Liveness MarkIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses);
|
||||||
Liveness SurveyUse(const Use *U, UseVector &MaybeLiveUses,
|
Liveness SurveyUse(const Use *U, UseVector &MaybeLiveUses,
|
||||||
|
@ -128,6 +138,7 @@ private:
|
||||||
bool DeleteDeadVarargs(Function &Fn);
|
bool DeleteDeadVarargs(Function &Fn);
|
||||||
bool RemoveDeadArgumentsFromCallers(Function &Fn);
|
bool RemoveDeadArgumentsFromCallers(Function &Fn);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
|
#endif // LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
|
||||||
|
|
|
@ -15,17 +15,19 @@
|
||||||
#ifndef LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
|
#ifndef LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
|
||||||
#define LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
|
#define LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
|
||||||
|
|
||||||
#include "llvm/IR/Module.h"
|
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
|
||||||
/// A pass that transforms external global definitions into declarations.
|
/// A pass that transforms external global definitions into declarations.
|
||||||
class EliminateAvailableExternallyPass
|
class EliminateAvailableExternallyPass
|
||||||
: public PassInfoMixin<EliminateAvailableExternallyPass> {
|
: public PassInfoMixin<EliminateAvailableExternallyPass> {
|
||||||
public:
|
public:
|
||||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
|
#endif // LLVM_TRANSFORMS_IPO_ELIMAVAILEXTERN_H
|
||||||
|
|
|
@ -7,23 +7,26 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_FUNCTIONIMPORT_H
|
#ifndef LLVM_TRANSFORMS_IPO_FUNCTIONIMPORT_H
|
||||||
#define LLVM_FUNCTIONIMPORT_H
|
#define LLVM_TRANSFORMS_IPO_FUNCTIONIMPORT_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/IR/GlobalValue.h"
|
#include "llvm/IR/GlobalValue.h"
|
||||||
#include "llvm/IR/ModuleSummaryIndex.h"
|
#include "llvm/IR/ModuleSummaryIndex.h"
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <system_error>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class LLVMContext;
|
|
||||||
class GlobalValueSummary;
|
|
||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
/// The function importer is automatically importing function from other modules
|
/// The function importer is automatically importing function from other modules
|
||||||
|
@ -34,19 +37,19 @@ public:
|
||||||
/// containing all the functions to import for a source module.
|
/// containing all the functions to import for a source module.
|
||||||
/// The keys is the GUID identifying a function to import, and the value
|
/// The keys is the GUID identifying a function to import, and the value
|
||||||
/// is the threshold applied when deciding to import it.
|
/// is the threshold applied when deciding to import it.
|
||||||
typedef std::map<GlobalValue::GUID, unsigned> FunctionsToImportTy;
|
using FunctionsToImportTy = std::map<GlobalValue::GUID, unsigned>;
|
||||||
|
|
||||||
/// The map contains an entry for every module to import from, the key being
|
/// The map contains an entry for every module to import from, the key being
|
||||||
/// the module identifier to pass to the ModuleLoader. The value is the set of
|
/// the module identifier to pass to the ModuleLoader. The value is the set of
|
||||||
/// functions to import.
|
/// functions to import.
|
||||||
typedef StringMap<FunctionsToImportTy> ImportMapTy;
|
using ImportMapTy = StringMap<FunctionsToImportTy>;
|
||||||
|
|
||||||
/// The set contains an entry for every global value the module exports.
|
/// The set contains an entry for every global value the module exports.
|
||||||
typedef std::unordered_set<GlobalValue::GUID> ExportSetTy;
|
using ExportSetTy = std::unordered_set<GlobalValue::GUID>;
|
||||||
|
|
||||||
/// A function of this type is used to load modules referenced by the index.
|
/// A function of this type is used to load modules referenced by the index.
|
||||||
typedef std::function<Expected<std::unique_ptr<Module>>(StringRef Identifier)>
|
using ModuleLoaderTy =
|
||||||
ModuleLoaderTy;
|
std::function<Expected<std::unique_ptr<Module>>(StringRef Identifier)>;
|
||||||
|
|
||||||
/// Create a Function Importer.
|
/// Create a Function Importer.
|
||||||
FunctionImporter(const ModuleSummaryIndex &Index, ModuleLoaderTy ModuleLoader)
|
FunctionImporter(const ModuleSummaryIndex &Index, ModuleLoaderTy ModuleLoader)
|
||||||
|
@ -132,6 +135,7 @@ void thinLTOResolveWeakForLinkerModule(Module &TheModule,
|
||||||
/// during global summary-based analysis.
|
/// during global summary-based analysis.
|
||||||
void thinLTOInternalizeModule(Module &TheModule,
|
void thinLTOInternalizeModule(Module &TheModule,
|
||||||
const GVSummaryMapTy &DefinedGlobals);
|
const GVSummaryMapTy &DefinedGlobals);
|
||||||
}
|
|
||||||
|
|
||||||
#endif // LLVM_FUNCTIONIMPORT_H
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif // LLVM_TRANSFORMS_IPO_FUNCTIONIMPORT_H
|
||||||
|
|
|
@ -16,17 +16,18 @@
|
||||||
#ifndef LLVM_TRANSFORMS_IPO_GLOBALOPT_H
|
#ifndef LLVM_TRANSFORMS_IPO_GLOBALOPT_H
|
||||||
#define LLVM_TRANSFORMS_IPO_GLOBALOPT_H
|
#define LLVM_TRANSFORMS_IPO_GLOBALOPT_H
|
||||||
|
|
||||||
#include "llvm/IR/Module.h"
|
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
|
||||||
/// Optimize globals that never have their address taken.
|
/// Optimize globals that never have their address taken.
|
||||||
class GlobalOptPass : public PassInfoMixin<GlobalOptPass> {
|
class GlobalOptPass : public PassInfoMixin<GlobalOptPass> {
|
||||||
public:
|
public:
|
||||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_TRANSFORMS_IPO_GLOBALOPT_H
|
#endif // LLVM_TRANSFORMS_IPO_GLOBALOPT_H
|
||||||
|
|
|
@ -17,14 +17,18 @@
|
||||||
#ifndef LLVM_TRANSFORMS_IPO_GLOBALSPLIT_H
|
#ifndef LLVM_TRANSFORMS_IPO_GLOBALSPLIT_H
|
||||||
#define LLVM_TRANSFORMS_IPO_GLOBALSPLIT_H
|
#define LLVM_TRANSFORMS_IPO_GLOBALSPLIT_H
|
||||||
|
|
||||||
#include "llvm/IR/Module.h"
|
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
|
||||||
/// Pass to perform split of global variables.
|
/// Pass to perform split of global variables.
|
||||||
class GlobalSplitPass : public PassInfoMixin<GlobalSplitPass> {
|
class GlobalSplitPass : public PassInfoMixin<GlobalSplitPass> {
|
||||||
public:
|
public:
|
||||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_TRANSFORMS_IPO_GLOBALSPLIT_H
|
#endif // LLVM_TRANSFORMS_IPO_GLOBALSPLIT_H
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//===- PartialInlining.h - Inline parts of functions --------------------===//
|
//===- PartialInlining.h - Inline parts of functions ------------*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
|
@ -15,15 +15,18 @@
|
||||||
#ifndef LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
|
#ifndef LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
|
||||||
#define LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
|
#define LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
|
||||||
|
|
||||||
#include "llvm/IR/Module.h"
|
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
|
||||||
/// Pass to remove unused function declarations.
|
/// Pass to remove unused function declarations.
|
||||||
class PartialInlinerPass : public PassInfoMixin<PartialInlinerPass> {
|
class PartialInlinerPass : public PassInfoMixin<PartialInlinerPass> {
|
||||||
public:
|
public:
|
||||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
|
#endif // LLVM_TRANSFORMS_IPO_PARTIALINLINING_H
|
||||||
|
|
|
@ -19,16 +19,23 @@
|
||||||
|
|
||||||
#include "llvm/Transforms/IPO/ConstantMerge.h"
|
#include "llvm/Transforms/IPO/ConstantMerge.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/IR/DerivedTypes.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/IR/Module.h"
|
||||||
#include "llvm/IR/Operator.h"
|
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Transforms/IPO.h"
|
#include "llvm/Transforms/IPO.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "constmerge"
|
#define DEBUG_TYPE "constmerge"
|
||||||
|
@ -102,8 +109,7 @@ static bool mergeConstants(Module &M) {
|
||||||
// constants together may allow us to merge other constants together if the
|
// constants together may allow us to merge other constants together if the
|
||||||
// second level constants have initializers which point to the globals that
|
// second level constants have initializers which point to the globals that
|
||||||
// were just merged.
|
// were just merged.
|
||||||
while (1) {
|
while (true) {
|
||||||
|
|
||||||
// First: Find the canonical constants others will be merged with.
|
// First: Find the canonical constants others will be merged with.
|
||||||
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
|
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
|
||||||
GVI != E; ) {
|
GVI != E; ) {
|
||||||
|
@ -225,23 +231,27 @@ PreservedAnalyses ConstantMergePass::run(Module &M, ModuleAnalysisManager &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct ConstantMergeLegacyPass : public ModulePass {
|
struct ConstantMergeLegacyPass : public ModulePass {
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
|
|
||||||
ConstantMergeLegacyPass() : ModulePass(ID) {
|
ConstantMergeLegacyPass() : ModulePass(ID) {
|
||||||
initializeConstantMergeLegacyPassPass(*PassRegistry::getPassRegistry());
|
initializeConstantMergeLegacyPassPass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
|
|
||||||
// For this pass, process all of the globals in the module, eliminating
|
// For this pass, process all of the globals in the module, eliminating
|
||||||
// duplicate constants.
|
// duplicate constants.
|
||||||
bool runOnModule(Module &M) {
|
bool runOnModule(Module &M) override {
|
||||||
if (skipModule(M))
|
if (skipModule(M))
|
||||||
return false;
|
return false;
|
||||||
return mergeConstants(M);
|
return mergeConstants(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
char ConstantMergeLegacyPass::ID = 0;
|
char ConstantMergeLegacyPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS(ConstantMergeLegacyPass, "constmerge",
|
INITIALIZE_PASS(ConstantMergeLegacyPass, "constmerge",
|
||||||
"Merge Duplicate Global Constants", false, false)
|
"Merge Duplicate Global Constants", false, false)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//===-- DeadArgumentElimination.cpp - Eliminate dead arguments ------------===//
|
//===- DeadArgumentElimination.cpp - Eliminate dead arguments -------------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
|
@ -20,24 +20,36 @@
|
||||||
#include "llvm/Transforms/IPO/DeadArgumentElimination.h"
|
#include "llvm/Transforms/IPO/DeadArgumentElimination.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/IR/Argument.h"
|
||||||
|
#include "llvm/IR/Attributes.h"
|
||||||
|
#include "llvm/IR/BasicBlock.h"
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/CallingConv.h"
|
|
||||||
#include "llvm/IR/Constant.h"
|
#include "llvm/IR/Constant.h"
|
||||||
#include "llvm/IR/DIBuilder.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/DebugInfo.h"
|
|
||||||
#include "llvm/IR/DerivedTypes.h"
|
#include "llvm/IR/DerivedTypes.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/InstrTypes.h"
|
||||||
|
#include "llvm/IR/Instruction.h"
|
||||||
#include "llvm/IR/Instructions.h"
|
#include "llvm/IR/Instructions.h"
|
||||||
#include "llvm/IR/IntrinsicInst.h"
|
#include "llvm/IR/IntrinsicInst.h"
|
||||||
#include "llvm/IR/LLVMContext.h"
|
#include "llvm/IR/Intrinsics.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
|
#include "llvm/IR/PassManager.h"
|
||||||
|
#include "llvm/IR/Type.h"
|
||||||
|
#include "llvm/IR/Use.h"
|
||||||
|
#include "llvm/IR/User.h"
|
||||||
|
#include "llvm/IR/Value.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Transforms/IPO.h"
|
#include "llvm/Transforms/IPO.h"
|
||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||||
#include <set>
|
#include <cassert>
|
||||||
#include <tuple>
|
#include <cstdint>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "deadargelim"
|
#define DEBUG_TYPE "deadargelim"
|
||||||
|
@ -46,9 +58,10 @@ STATISTIC(NumArgumentsEliminated, "Number of unread args removed");
|
||||||
STATISTIC(NumRetValsEliminated , "Number of unused return values removed");
|
STATISTIC(NumRetValsEliminated , "Number of unused return values removed");
|
||||||
STATISTIC(NumArgumentsReplacedWithUndef,
|
STATISTIC(NumArgumentsReplacedWithUndef,
|
||||||
"Number of unread args replaced with undef");
|
"Number of unread args replaced with undef");
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// DAE - The dead argument elimination pass.
|
/// DAE - The dead argument elimination pass.
|
||||||
///
|
|
||||||
class DAE : public ModulePass {
|
class DAE : public ModulePass {
|
||||||
protected:
|
protected:
|
||||||
// DAH uses this to specify a different ID.
|
// DAH uses this to specify a different ID.
|
||||||
|
@ -56,6 +69,7 @@ namespace {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
|
|
||||||
DAE() : ModulePass(ID) {
|
DAE() : ModulePass(ID) {
|
||||||
initializeDAEPass(*PassRegistry::getPassRegistry());
|
initializeDAEPass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
|
@ -71,33 +85,38 @@ namespace {
|
||||||
|
|
||||||
virtual bool ShouldHackArguments() const { return false; }
|
virtual bool ShouldHackArguments() const { return false; }
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
char DAE::ID = 0;
|
char DAE::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS(DAE, "deadargelim", "Dead Argument Elimination", false, false)
|
INITIALIZE_PASS(DAE, "deadargelim", "Dead Argument Elimination", false, false)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// DAH - DeadArgumentHacking pass - Same as dead argument elimination, but
|
/// DAH - DeadArgumentHacking pass - Same as dead argument elimination, but
|
||||||
/// deletes arguments to functions which are external. This is only for use
|
/// deletes arguments to functions which are external. This is only for use
|
||||||
/// by bugpoint.
|
/// by bugpoint.
|
||||||
struct DAH : public DAE {
|
struct DAH : public DAE {
|
||||||
static char ID;
|
static char ID;
|
||||||
|
|
||||||
DAH() : DAE(ID) {}
|
DAH() : DAE(ID) {}
|
||||||
|
|
||||||
bool ShouldHackArguments() const override { return true; }
|
bool ShouldHackArguments() const override { return true; }
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
char DAH::ID = 0;
|
char DAH::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS(DAH, "deadarghaX0r",
|
INITIALIZE_PASS(DAH, "deadarghaX0r",
|
||||||
"Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)",
|
"Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)",
|
||||||
false, false)
|
false, false)
|
||||||
|
|
||||||
/// createDeadArgEliminationPass - This pass removes arguments from functions
|
/// createDeadArgEliminationPass - This pass removes arguments from functions
|
||||||
/// which are not used by the body of the function.
|
/// which are not used by the body of the function.
|
||||||
///
|
|
||||||
ModulePass *llvm::createDeadArgEliminationPass() { return new DAE(); }
|
ModulePass *llvm::createDeadArgEliminationPass() { return new DAE(); }
|
||||||
|
|
||||||
ModulePass *llvm::createDeadArgHackingPass() { return new DAH(); }
|
ModulePass *llvm::createDeadArgHackingPass() { return new DAH(); }
|
||||||
|
|
||||||
/// DeleteDeadVarargs - If this is an function that takes a ... list, and if
|
/// DeleteDeadVarargs - If this is an function that takes a ... list, and if
|
||||||
|
@ -140,7 +159,7 @@ bool DeadArgumentEliminationPass::DeleteDeadVarargs(Function &Fn) {
|
||||||
// the old function, but doesn't have isVarArg set.
|
// the old function, but doesn't have isVarArg set.
|
||||||
FunctionType *FTy = Fn.getFunctionType();
|
FunctionType *FTy = Fn.getFunctionType();
|
||||||
|
|
||||||
std::vector<Type*> Params(FTy->param_begin(), FTy->param_end());
|
std::vector<Type *> Params(FTy->param_begin(), FTy->param_end());
|
||||||
FunctionType *NFTy = FunctionType::get(FTy->getReturnType(),
|
FunctionType *NFTy = FunctionType::get(FTy->getReturnType(),
|
||||||
Params, false);
|
Params, false);
|
||||||
unsigned NumArgs = Params.size();
|
unsigned NumArgs = Params.size();
|
||||||
|
@ -155,7 +174,7 @@ bool DeadArgumentEliminationPass::DeleteDeadVarargs(Function &Fn) {
|
||||||
// Loop over all of the callers of the function, transforming the call sites
|
// Loop over all of the callers of the function, transforming the call sites
|
||||||
// to pass in a smaller number of arguments into the new function.
|
// to pass in a smaller number of arguments into the new function.
|
||||||
//
|
//
|
||||||
std::vector<Value*> Args;
|
std::vector<Value *> Args;
|
||||||
for (Value::user_iterator I = Fn.user_begin(), E = Fn.user_end(); I != E; ) {
|
for (Value::user_iterator I = Fn.user_begin(), E = Fn.user_end(); I != E; ) {
|
||||||
CallSite CS(*I++);
|
CallSite CS(*I++);
|
||||||
if (!CS)
|
if (!CS)
|
||||||
|
@ -214,7 +233,6 @@ bool DeadArgumentEliminationPass::DeleteDeadVarargs(Function &Fn) {
|
||||||
// Loop over the argument list, transferring uses of the old arguments over to
|
// Loop over the argument list, transferring uses of the old arguments over to
|
||||||
// the new arguments, also transferring over the names as well. While we're at
|
// the new arguments, also transferring over the names as well. While we're at
|
||||||
// it, remove the dead arguments from the DeadArguments list.
|
// it, remove the dead arguments from the DeadArguments list.
|
||||||
//
|
|
||||||
for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(),
|
for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(),
|
||||||
I2 = NF->arg_begin(); I != E; ++I, ++I2) {
|
I2 = NF->arg_begin(); I != E; ++I, ++I2) {
|
||||||
// Move the name and users over to the new version.
|
// Move the name and users over to the new version.
|
||||||
|
@ -343,7 +361,6 @@ DeadArgumentEliminationPass::MarkIfNotLive(RetOrArg Use,
|
||||||
return MaybeLive;
|
return MaybeLive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// SurveyUse - This looks at a single use of an argument or return value
|
/// SurveyUse - This looks at a single use of an argument or return value
|
||||||
/// and determines if it should be alive or not. Adds this use to MaybeLiveUses
|
/// and determines if it should be alive or not. Adds this use to MaybeLiveUses
|
||||||
/// if it causes the used value to become MaybeLive.
|
/// if it causes the used value to become MaybeLive.
|
||||||
|
@ -460,7 +477,6 @@ DeadArgumentEliminationPass::SurveyUses(const Value *V,
|
||||||
//
|
//
|
||||||
// We consider arguments of non-internal functions to be intrinsically alive as
|
// We consider arguments of non-internal functions to be intrinsically alive as
|
||||||
// well as arguments to functions which have their "address taken".
|
// well as arguments to functions which have their "address taken".
|
||||||
//
|
|
||||||
void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
|
void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
|
||||||
// Functions with inalloca parameters are expecting args in a particular
|
// Functions with inalloca parameters are expecting args in a particular
|
||||||
// register and memory layout.
|
// register and memory layout.
|
||||||
|
@ -478,11 +494,14 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned RetCount = NumRetVals(&F);
|
unsigned RetCount = NumRetVals(&F);
|
||||||
|
|
||||||
// Assume all return values are dead
|
// Assume all return values are dead
|
||||||
typedef SmallVector<Liveness, 5> RetVals;
|
using RetVals = SmallVector<Liveness, 5>;
|
||||||
|
|
||||||
RetVals RetValLiveness(RetCount, MaybeLive);
|
RetVals RetValLiveness(RetCount, MaybeLive);
|
||||||
|
|
||||||
typedef SmallVector<UseVector, 5> RetUses;
|
using RetUses = SmallVector<UseVector, 5>;
|
||||||
|
|
||||||
// These vectors map each return value to the uses that make it MaybeLive, so
|
// These vectors map each return value to the uses that make it MaybeLive, so
|
||||||
// we can add those to the Uses map if the return value really turns out to be
|
// we can add those to the Uses map if the return value really turns out to be
|
||||||
// MaybeLive. Initialized to a list of RetCount empty lists.
|
// MaybeLive. Initialized to a list of RetCount empty lists.
|
||||||
|
@ -601,15 +620,15 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
|
||||||
void DeadArgumentEliminationPass::MarkValue(const RetOrArg &RA, Liveness L,
|
void DeadArgumentEliminationPass::MarkValue(const RetOrArg &RA, Liveness L,
|
||||||
const UseVector &MaybeLiveUses) {
|
const UseVector &MaybeLiveUses) {
|
||||||
switch (L) {
|
switch (L) {
|
||||||
case Live: MarkLive(RA); break;
|
case Live:
|
||||||
|
MarkLive(RA);
|
||||||
|
break;
|
||||||
case MaybeLive:
|
case MaybeLive:
|
||||||
{
|
|
||||||
// Note any uses of this value, so this return value can be
|
// Note any uses of this value, so this return value can be
|
||||||
// marked live whenever one of the uses becomes live.
|
// marked live whenever one of the uses becomes live.
|
||||||
for (const auto &MaybeLiveUse : MaybeLiveUses)
|
for (const auto &MaybeLiveUse : MaybeLiveUses)
|
||||||
Uses.insert(std::make_pair(MaybeLiveUse, RA));
|
Uses.insert(std::make_pair(MaybeLiveUse, RA));
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,7 +781,7 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
|
||||||
// One return type? Just a simple value then, but only if we didn't use to
|
// One return type? Just a simple value then, but only if we didn't use to
|
||||||
// return a struct with that simple value before.
|
// return a struct with that simple value before.
|
||||||
NRetTy = RetTypes.front();
|
NRetTy = RetTypes.front();
|
||||||
else if (RetTypes.size() == 0)
|
else if (RetTypes.empty())
|
||||||
// No return types? Make it void, but only if we didn't use to return {}.
|
// No return types? Make it void, but only if we didn't use to return {}.
|
||||||
NRetTy = Type::getVoidTy(F->getContext());
|
NRetTy = Type::getVoidTy(F->getContext());
|
||||||
}
|
}
|
||||||
|
@ -808,7 +827,6 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
|
||||||
|
|
||||||
// Loop over all of the callers of the function, transforming the call sites
|
// Loop over all of the callers of the function, transforming the call sites
|
||||||
// to pass in a smaller number of arguments into the new function.
|
// to pass in a smaller number of arguments into the new function.
|
||||||
//
|
|
||||||
std::vector<Value*> Args;
|
std::vector<Value*> Args;
|
||||||
while (!F->use_empty()) {
|
while (!F->use_empty()) {
|
||||||
CallSite CS(F->user_back());
|
CallSite CS(F->user_back());
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//===-- ElimAvailExtern.cpp - DCE unreachable internal functions
|
//===- ElimAvailExtern.cpp - DCE unreachable internal functions -----------===//
|
||||||
//----------------===//
|
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
|
@ -15,11 +14,15 @@
|
||||||
|
|
||||||
#include "llvm/Transforms/IPO/ElimAvailExtern.h"
|
#include "llvm/Transforms/IPO/ElimAvailExtern.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/IR/Constants.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/IR/Module.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/Transforms/IPO.h"
|
#include "llvm/Transforms/IPO.h"
|
||||||
#include "llvm/Transforms/Utils/GlobalStatus.h"
|
#include "llvm/Transforms/Utils/GlobalStatus.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "elim-avail-extern"
|
#define DEBUG_TYPE "elim-avail-extern"
|
||||||
|
@ -69,8 +72,10 @@ EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct EliminateAvailableExternallyLegacyPass : public ModulePass {
|
struct EliminateAvailableExternallyLegacyPass : public ModulePass {
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
|
|
||||||
EliminateAvailableExternallyLegacyPass() : ModulePass(ID) {
|
EliminateAvailableExternallyLegacyPass() : ModulePass(ID) {
|
||||||
initializeEliminateAvailableExternallyLegacyPassPass(
|
initializeEliminateAvailableExternallyLegacyPassPass(
|
||||||
*PassRegistry::getPassRegistry());
|
*PassRegistry::getPassRegistry());
|
||||||
|
@ -78,16 +83,17 @@ struct EliminateAvailableExternallyLegacyPass : public ModulePass {
|
||||||
|
|
||||||
// run - Do the EliminateAvailableExternally pass on the specified module,
|
// run - Do the EliminateAvailableExternally pass on the specified module,
|
||||||
// optionally updating the specified callgraph to reflect the changes.
|
// optionally updating the specified callgraph to reflect the changes.
|
||||||
//
|
bool runOnModule(Module &M) override {
|
||||||
bool runOnModule(Module &M) {
|
|
||||||
if (skipModule(M))
|
if (skipModule(M))
|
||||||
return false;
|
return false;
|
||||||
return eliminateAvailableExternally(M);
|
return eliminateAvailableExternally(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
char EliminateAvailableExternallyLegacyPass::ID = 0;
|
char EliminateAvailableExternallyLegacyPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
|
INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
|
||||||
"Eliminate Available Externally Globals", false, false)
|
"Eliminate Available Externally Globals", false, false)
|
||||||
|
|
||||||
|
|
|
@ -12,30 +12,51 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Transforms/IPO/FunctionImport.h"
|
#include "llvm/Transforms/IPO/FunctionImport.h"
|
||||||
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/ADT/SetVector.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringSet.h"
|
#include "llvm/ADT/StringSet.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Bitcode/BitcodeReader.h"
|
#include "llvm/Bitcode/BitcodeReader.h"
|
||||||
#include "llvm/IR/AutoUpgrade.h"
|
#include "llvm/IR/AutoUpgrade.h"
|
||||||
#include "llvm/IR/DiagnosticPrinter.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/IntrinsicInst.h"
|
#include "llvm/IR/GlobalAlias.h"
|
||||||
|
#include "llvm/IR/GlobalObject.h"
|
||||||
|
#include "llvm/IR/GlobalValue.h"
|
||||||
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
|
#include "llvm/IR/Metadata.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/Verifier.h"
|
#include "llvm/IR/ModuleSummaryIndex.h"
|
||||||
#include "llvm/IRReader/IRReader.h"
|
#include "llvm/IRReader/IRReader.h"
|
||||||
#include "llvm/Linker/Linker.h"
|
#include "llvm/Linker/IRMover.h"
|
||||||
#include "llvm/Object/IRObjectFile.h"
|
#include "llvm/Object/ModuleSymbolTable.h"
|
||||||
|
#include "llvm/Object/SymbolicFile.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Support/Error.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Transforms/IPO/Internalize.h"
|
#include "llvm/Transforms/IPO/Internalize.h"
|
||||||
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
|
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
|
||||||
|
#include <cassert>
|
||||||
#define DEBUG_TYPE "function-import"
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <system_error>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "function-import"
|
||||||
|
|
||||||
STATISTIC(NumImportedFunctions, "Number of functions imported");
|
STATISTIC(NumImportedFunctions, "Number of functions imported");
|
||||||
STATISTIC(NumImportedModules, "Number of modules imported from");
|
STATISTIC(NumImportedModules, "Number of modules imported from");
|
||||||
STATISTIC(NumDeadSymbols, "Number of dead stripped symbols in index");
|
STATISTIC(NumDeadSymbols, "Number of dead stripped symbols in index");
|
||||||
|
@ -91,6 +112,12 @@ static cl::opt<bool> EnableImportMetadata(
|
||||||
),
|
),
|
||||||
cl::Hidden, cl::desc("Enable import metadata like 'thinlto_src_module'"));
|
cl::Hidden, cl::desc("Enable import metadata like 'thinlto_src_module'"));
|
||||||
|
|
||||||
|
/// Summary file to use for function importing when using -function-import from
|
||||||
|
/// the command line.
|
||||||
|
static cl::opt<std::string>
|
||||||
|
SummaryFile("summary-file",
|
||||||
|
cl::desc("The summary file to use for function importing."));
|
||||||
|
|
||||||
// Load lazily a module from \p FileName in \p Context.
|
// Load lazily a module from \p FileName in \p Context.
|
||||||
static std::unique_ptr<Module> loadFile(const std::string &FileName,
|
static std::unique_ptr<Module> loadFile(const std::string &FileName,
|
||||||
LLVMContext &Context) {
|
LLVMContext &Context) {
|
||||||
|
@ -109,8 +136,6 @@ static std::unique_ptr<Module> loadFile(const std::string &FileName,
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
/// Given a list of possible callee implementation for a call site, select one
|
/// Given a list of possible callee implementation for a call site, select one
|
||||||
/// that fits the \p Threshold.
|
/// that fits the \p Threshold.
|
||||||
///
|
///
|
||||||
|
@ -184,9 +209,13 @@ selectCallee(const ModuleSummaryIndex &Index,
|
||||||
return cast<GlobalValueSummary>(It->get());
|
return cast<GlobalValueSummary>(It->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
using EdgeInfo = std::tuple<const FunctionSummary *, unsigned /* Threshold */,
|
using EdgeInfo = std::tuple<const FunctionSummary *, unsigned /* Threshold */,
|
||||||
GlobalValue::GUID>;
|
GlobalValue::GUID>;
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
static ValueInfo
|
static ValueInfo
|
||||||
updateValueInfoForIndirectCalls(const ModuleSummaryIndex &Index, ValueInfo VI) {
|
updateValueInfoForIndirectCalls(const ModuleSummaryIndex &Index, ValueInfo VI) {
|
||||||
if (!VI.getSummaryList().empty())
|
if (!VI.getSummaryList().empty())
|
||||||
|
@ -354,8 +383,6 @@ static void ComputeImportForModule(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
/// Compute all the import and export for every module using the Index.
|
/// Compute all the import and export for every module using the Index.
|
||||||
void llvm::ComputeCrossModuleImport(
|
void llvm::ComputeCrossModuleImport(
|
||||||
const ModuleSummaryIndex &Index,
|
const ModuleSummaryIndex &Index,
|
||||||
|
@ -409,7 +436,6 @@ void llvm::ComputeCrossModuleImport(
|
||||||
void llvm::ComputeCrossModuleImportForModule(
|
void llvm::ComputeCrossModuleImportForModule(
|
||||||
StringRef ModulePath, const ModuleSummaryIndex &Index,
|
StringRef ModulePath, const ModuleSummaryIndex &Index,
|
||||||
FunctionImporter::ImportMapTy &ImportList) {
|
FunctionImporter::ImportMapTy &ImportList) {
|
||||||
|
|
||||||
// Collect the list of functions this module defines.
|
// Collect the list of functions this module defines.
|
||||||
// GUID -> Summary
|
// GUID -> Summary
|
||||||
GVSummaryMapTy FunctionSummaryMap;
|
GVSummaryMapTy FunctionSummaryMap;
|
||||||
|
@ -663,12 +689,11 @@ void llvm::thinLTOInternalizeModule(Module &TheModule,
|
||||||
|
|
||||||
// FIXME: See if we can just internalize directly here via linkage changes
|
// FIXME: See if we can just internalize directly here via linkage changes
|
||||||
// based on the index, rather than invoking internalizeModule.
|
// based on the index, rather than invoking internalizeModule.
|
||||||
llvm::internalizeModule(TheModule, MustPreserveGV);
|
internalizeModule(TheModule, MustPreserveGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Automatically import functions in Module \p DestModule based on the summaries
|
// Automatically import functions in Module \p DestModule based on the summaries
|
||||||
// index.
|
// index.
|
||||||
//
|
|
||||||
Expected<bool> FunctionImporter::importFunctions(
|
Expected<bool> FunctionImporter::importFunctions(
|
||||||
Module &DestModule, const FunctionImporter::ImportMapTy &ImportList) {
|
Module &DestModule, const FunctionImporter::ImportMapTy &ImportList) {
|
||||||
DEBUG(dbgs() << "Starting import for Module "
|
DEBUG(dbgs() << "Starting import for Module "
|
||||||
|
@ -715,10 +740,9 @@ Expected<bool> FunctionImporter::importFunctions(
|
||||||
// Add 'thinlto_src_module' metadata for statistics and debugging.
|
// Add 'thinlto_src_module' metadata for statistics and debugging.
|
||||||
F.setMetadata(
|
F.setMetadata(
|
||||||
"thinlto_src_module",
|
"thinlto_src_module",
|
||||||
llvm::MDNode::get(
|
MDNode::get(DestModule.getContext(),
|
||||||
DestModule.getContext(),
|
{MDString::get(DestModule.getContext(),
|
||||||
{llvm::MDString::get(DestModule.getContext(),
|
SrcModule->getSourceFileName())}));
|
||||||
SrcModule->getSourceFileName())}));
|
|
||||||
}
|
}
|
||||||
GlobalsToImport.insert(&F);
|
GlobalsToImport.insert(&F);
|
||||||
}
|
}
|
||||||
|
@ -779,12 +803,6 @@ Expected<bool> FunctionImporter::importFunctions(
|
||||||
return ImportedCount;
|
return ImportedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Summary file to use for function importing when using -function-import from
|
|
||||||
/// the command line.
|
|
||||||
static cl::opt<std::string>
|
|
||||||
SummaryFile("summary-file",
|
|
||||||
cl::desc("The summary file to use for function importing."));
|
|
||||||
|
|
||||||
static bool doImportingForModule(Module &M) {
|
static bool doImportingForModule(Module &M) {
|
||||||
if (SummaryFile.empty())
|
if (SummaryFile.empty())
|
||||||
report_fatal_error("error: -function-import requires -summary-file\n");
|
report_fatal_error("error: -function-import requires -summary-file\n");
|
||||||
|
@ -838,17 +856,18 @@ static bool doImportingForModule(Module &M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// Pass that performs cross-module function import provided a summary file.
|
/// Pass that performs cross-module function import provided a summary file.
|
||||||
class FunctionImportLegacyPass : public ModulePass {
|
class FunctionImportLegacyPass : public ModulePass {
|
||||||
public:
|
public:
|
||||||
/// Pass identification, replacement for typeid
|
/// Pass identification, replacement for typeid
|
||||||
static char ID;
|
static char ID;
|
||||||
|
|
||||||
|
explicit FunctionImportLegacyPass() : ModulePass(ID) {}
|
||||||
|
|
||||||
/// Specify pass name for debug output
|
/// Specify pass name for debug output
|
||||||
StringRef getPassName() const override { return "Function Importing"; }
|
StringRef getPassName() const override { return "Function Importing"; }
|
||||||
|
|
||||||
explicit FunctionImportLegacyPass() : ModulePass(ID) {}
|
|
||||||
|
|
||||||
bool runOnModule(Module &M) override {
|
bool runOnModule(Module &M) override {
|
||||||
if (skipModule(M))
|
if (skipModule(M))
|
||||||
return false;
|
return false;
|
||||||
|
@ -856,7 +875,8 @@ public:
|
||||||
return doImportingForModule(M);
|
return doImportingForModule(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // anonymous namespace
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
PreservedAnalyses FunctionImportPass::run(Module &M,
|
PreservedAnalyses FunctionImportPass::run(Module &M,
|
||||||
ModuleAnalysisManager &AM) {
|
ModuleAnalysisManager &AM) {
|
||||||
|
@ -871,7 +891,9 @@ INITIALIZE_PASS(FunctionImportLegacyPass, "function-import",
|
||||||
"Summary Based Function Import", false, false)
|
"Summary Based Function Import", false, false)
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
Pass *createFunctionImportPass() {
|
Pass *createFunctionImportPass() {
|
||||||
return new FunctionImportLegacyPass();
|
return new FunctionImportLegacyPass();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
|
@ -20,24 +20,41 @@
|
||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallSet.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
|
#include "llvm/ADT/Twine.h"
|
||||||
|
#include "llvm/ADT/iterator_range.h"
|
||||||
#include "llvm/Analysis/ConstantFolding.h"
|
#include "llvm/Analysis/ConstantFolding.h"
|
||||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||||
|
#include "llvm/BinaryFormat/Dwarf.h"
|
||||||
|
#include "llvm/IR/Attributes.h"
|
||||||
|
#include "llvm/IR/BasicBlock.h"
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/CallingConv.h"
|
#include "llvm/IR/CallingConv.h"
|
||||||
|
#include "llvm/IR/Constant.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/IR/DebugInfoMetadata.h"
|
#include "llvm/IR/DebugInfoMetadata.h"
|
||||||
#include "llvm/IR/DerivedTypes.h"
|
#include "llvm/IR/DerivedTypes.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
||||||
|
#include "llvm/IR/GlobalAlias.h"
|
||||||
|
#include "llvm/IR/GlobalValue.h"
|
||||||
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
|
#include "llvm/IR/InstrTypes.h"
|
||||||
|
#include "llvm/IR/Instruction.h"
|
||||||
#include "llvm/IR/Instructions.h"
|
#include "llvm/IR/Instructions.h"
|
||||||
#include "llvm/IR/IntrinsicInst.h"
|
#include "llvm/IR/IntrinsicInst.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/Operator.h"
|
#include "llvm/IR/Operator.h"
|
||||||
|
#include "llvm/IR/Type.h"
|
||||||
|
#include "llvm/IR/Use.h"
|
||||||
|
#include "llvm/IR/User.h"
|
||||||
|
#include "llvm/IR/Value.h"
|
||||||
#include "llvm/IR/ValueHandle.h"
|
#include "llvm/IR/ValueHandle.h"
|
||||||
#include "llvm/IR/DebugInfoMetadata.h"
|
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/AtomicOrdering.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
|
@ -47,7 +64,11 @@
|
||||||
#include "llvm/Transforms/Utils/Evaluator.h"
|
#include "llvm/Transforms/Utils/Evaluator.h"
|
||||||
#include "llvm/Transforms/Utils/GlobalStatus.h"
|
#include "llvm/Transforms/Utils/GlobalStatus.h"
|
||||||
#include "llvm/Transforms/Utils/Local.h"
|
#include "llvm/Transforms/Utils/Local.h"
|
||||||
#include <algorithm>
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "globalopt"
|
#define DEBUG_TYPE "globalopt"
|
||||||
|
@ -141,7 +162,7 @@ static bool IsSafeComputationToRemove(Value *V, const TargetLibraryInfo *TLI) {
|
||||||
}
|
}
|
||||||
|
|
||||||
V = I->getOperand(0);
|
V = I->getOperand(0);
|
||||||
} while (1);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This GV is a pointer root. Loop over all users of the global and clean up
|
/// This GV is a pointer root. Loop over all users of the global and clean up
|
||||||
|
@ -222,7 +243,7 @@ static bool CleanupPointerRootUsers(GlobalVariable *GV,
|
||||||
break;
|
break;
|
||||||
I->eraseFromParent();
|
I->eraseFromParent();
|
||||||
I = J;
|
I = J;
|
||||||
} while (1);
|
} while (true);
|
||||||
I->eraseFromParent();
|
I->eraseFromParent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,7 +371,6 @@ static bool isSafeSROAElementUse(Value *V) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// U is a direct user of the specified global value. Look at it and its uses
|
/// U is a direct user of the specified global value. Look at it and its uses
|
||||||
/// and decide whether it is safe to SROA this global.
|
/// and decide whether it is safe to SROA this global.
|
||||||
static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) {
|
static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) {
|
||||||
|
@ -436,7 +456,6 @@ static void transferSRADebugInfo(GlobalVariable *GV, GlobalVariable *NGV,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Perform scalar replacement of aggregates on the specified global variable.
|
/// Perform scalar replacement of aggregates on the specified global variable.
|
||||||
/// This opens the door for other optimizations by exposing the behavior of the
|
/// This opens the door for other optimizations by exposing the behavior of the
|
||||||
/// program in a more fine-grained way. We have determined that this
|
/// program in a more fine-grained way. We have determined that this
|
||||||
|
@ -451,7 +470,7 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const DataLayout &DL) {
|
||||||
Constant *Init = GV->getInitializer();
|
Constant *Init = GV->getInitializer();
|
||||||
Type *Ty = Init->getType();
|
Type *Ty = Init->getType();
|
||||||
|
|
||||||
std::vector<GlobalVariable*> NewGlobals;
|
std::vector<GlobalVariable *> NewGlobals;
|
||||||
Module::GlobalListType &Globals = GV->getParent()->getGlobalList();
|
Module::GlobalListType &Globals = GV->getParent()->getGlobalList();
|
||||||
|
|
||||||
// Get the alignment of the global, either explicit or target-specific.
|
// Get the alignment of the global, either explicit or target-specific.
|
||||||
|
@ -717,7 +736,6 @@ static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV) {
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// The specified global has only one non-null value stored into it. If there
|
/// The specified global has only one non-null value stored into it. If there
|
||||||
/// are uses of the loaded value that would trap if the loaded value is
|
/// are uses of the loaded value that would trap if the loaded value is
|
||||||
/// dynamically null, then we know that they cannot be reachable with a null
|
/// dynamically null, then we know that they cannot be reachable with a null
|
||||||
|
@ -1073,7 +1091,6 @@ static bool LoadUsesSimpleEnoughForHeapSRA(const Value *V,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// If all users of values loaded from GV are simple enough to perform HeapSRA,
|
/// If all users of values loaded from GV are simple enough to perform HeapSRA,
|
||||||
/// return true.
|
/// return true.
|
||||||
static bool AllGlobalLoadUsesSimpleEnoughForHeapSRA(const GlobalVariable *GV,
|
static bool AllGlobalLoadUsesSimpleEnoughForHeapSRA(const GlobalVariable *GV,
|
||||||
|
@ -1123,9 +1140,9 @@ static bool AllGlobalLoadUsesSimpleEnoughForHeapSRA(const GlobalVariable *GV,
|
||||||
}
|
}
|
||||||
|
|
||||||
static Value *GetHeapSROAValue(Value *V, unsigned FieldNo,
|
static Value *GetHeapSROAValue(Value *V, unsigned FieldNo,
|
||||||
DenseMap<Value*, std::vector<Value*> > &InsertedScalarizedValues,
|
DenseMap<Value *, std::vector<Value *>> &InsertedScalarizedValues,
|
||||||
std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite) {
|
std::vector<std::pair<PHINode *, unsigned>> &PHIsToRewrite) {
|
||||||
std::vector<Value*> &FieldVals = InsertedScalarizedValues[V];
|
std::vector<Value *> &FieldVals = InsertedScalarizedValues[V];
|
||||||
|
|
||||||
if (FieldNo >= FieldVals.size())
|
if (FieldNo >= FieldVals.size())
|
||||||
FieldVals.resize(FieldNo+1);
|
FieldVals.resize(FieldNo+1);
|
||||||
|
@ -1167,8 +1184,8 @@ static Value *GetHeapSROAValue(Value *V, unsigned FieldNo,
|
||||||
/// Given a load instruction and a value derived from the load, rewrite the
|
/// Given a load instruction and a value derived from the load, rewrite the
|
||||||
/// derived value to use the HeapSRoA'd load.
|
/// derived value to use the HeapSRoA'd load.
|
||||||
static void RewriteHeapSROALoadUser(Instruction *LoadUser,
|
static void RewriteHeapSROALoadUser(Instruction *LoadUser,
|
||||||
DenseMap<Value*, std::vector<Value*> > &InsertedScalarizedValues,
|
DenseMap<Value *, std::vector<Value *>> &InsertedScalarizedValues,
|
||||||
std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite) {
|
std::vector<std::pair<PHINode *, unsigned>> &PHIsToRewrite) {
|
||||||
// If this is a comparison against null, handle it.
|
// If this is a comparison against null, handle it.
|
||||||
if (ICmpInst *SCI = dyn_cast<ICmpInst>(LoadUser)) {
|
if (ICmpInst *SCI = dyn_cast<ICmpInst>(LoadUser)) {
|
||||||
assert(isa<ConstantPointerNull>(SCI->getOperand(1)));
|
assert(isa<ConstantPointerNull>(SCI->getOperand(1)));
|
||||||
|
@ -1215,7 +1232,7 @@ static void RewriteHeapSROALoadUser(Instruction *LoadUser,
|
||||||
// processed.
|
// processed.
|
||||||
PHINode *PN = cast<PHINode>(LoadUser);
|
PHINode *PN = cast<PHINode>(LoadUser);
|
||||||
if (!InsertedScalarizedValues.insert(std::make_pair(PN,
|
if (!InsertedScalarizedValues.insert(std::make_pair(PN,
|
||||||
std::vector<Value*>())).second)
|
std::vector<Value *>())).second)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If this is the first time we've seen this PHI, recursively process all
|
// If this is the first time we've seen this PHI, recursively process all
|
||||||
|
@ -1230,8 +1247,8 @@ static void RewriteHeapSROALoadUser(Instruction *LoadUser,
|
||||||
/// global. Eliminate all uses of Ptr, making them use FieldGlobals instead.
|
/// global. Eliminate all uses of Ptr, making them use FieldGlobals instead.
|
||||||
/// All uses of loaded values satisfy AllGlobalLoadUsesSimpleEnoughForHeapSRA.
|
/// All uses of loaded values satisfy AllGlobalLoadUsesSimpleEnoughForHeapSRA.
|
||||||
static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Load,
|
static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Load,
|
||||||
DenseMap<Value*, std::vector<Value*> > &InsertedScalarizedValues,
|
DenseMap<Value *, std::vector<Value *>> &InsertedScalarizedValues,
|
||||||
std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite) {
|
std::vector<std::pair<PHINode *, unsigned> > &PHIsToRewrite) {
|
||||||
for (auto UI = Load->user_begin(), E = Load->user_end(); UI != E;) {
|
for (auto UI = Load->user_begin(), E = Load->user_end(); UI != E;) {
|
||||||
Instruction *User = cast<Instruction>(*UI++);
|
Instruction *User = cast<Instruction>(*UI++);
|
||||||
RewriteHeapSROALoadUser(User, InsertedScalarizedValues, PHIsToRewrite);
|
RewriteHeapSROALoadUser(User, InsertedScalarizedValues, PHIsToRewrite);
|
||||||
|
@ -1260,8 +1277,8 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
|
||||||
|
|
||||||
// Okay, at this point, there are no users of the malloc. Insert N
|
// Okay, at this point, there are no users of the malloc. Insert N
|
||||||
// new mallocs at the same place as CI, and N globals.
|
// new mallocs at the same place as CI, and N globals.
|
||||||
std::vector<Value*> FieldGlobals;
|
std::vector<Value *> FieldGlobals;
|
||||||
std::vector<Value*> FieldMallocs;
|
std::vector<Value *> FieldMallocs;
|
||||||
|
|
||||||
SmallVector<OperandBundleDef, 1> OpBundles;
|
SmallVector<OperandBundleDef, 1> OpBundles;
|
||||||
CI->getOperandBundlesAsDefs(OpBundles);
|
CI->getOperandBundlesAsDefs(OpBundles);
|
||||||
|
@ -1358,10 +1375,10 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
|
||||||
|
|
||||||
/// As we process loads, if we can't immediately update all uses of the load,
|
/// As we process loads, if we can't immediately update all uses of the load,
|
||||||
/// keep track of what scalarized loads are inserted for a given load.
|
/// keep track of what scalarized loads are inserted for a given load.
|
||||||
DenseMap<Value*, std::vector<Value*> > InsertedScalarizedValues;
|
DenseMap<Value *, std::vector<Value *>> InsertedScalarizedValues;
|
||||||
InsertedScalarizedValues[GV] = FieldGlobals;
|
InsertedScalarizedValues[GV] = FieldGlobals;
|
||||||
|
|
||||||
std::vector<std::pair<PHINode*, unsigned> > PHIsToRewrite;
|
std::vector<std::pair<PHINode *, unsigned>> PHIsToRewrite;
|
||||||
|
|
||||||
// Okay, the malloc site is completely handled. All of the uses of GV are now
|
// Okay, the malloc site is completely handled. All of the uses of GV are now
|
||||||
// loads, and all uses of those loads are simple. Rewrite them to use loads
|
// loads, and all uses of those loads are simple. Rewrite them to use loads
|
||||||
|
@ -1407,7 +1424,7 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop all inter-phi links and any loads that made it this far.
|
// Drop all inter-phi links and any loads that made it this far.
|
||||||
for (DenseMap<Value*, std::vector<Value*> >::iterator
|
for (DenseMap<Value *, std::vector<Value *>>::iterator
|
||||||
I = InsertedScalarizedValues.begin(), E = InsertedScalarizedValues.end();
|
I = InsertedScalarizedValues.begin(), E = InsertedScalarizedValues.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
if (PHINode *PN = dyn_cast<PHINode>(I->first))
|
if (PHINode *PN = dyn_cast<PHINode>(I->first))
|
||||||
|
@ -1417,7 +1434,7 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all the phis and loads now that inter-references are dead.
|
// Delete all the phis and loads now that inter-references are dead.
|
||||||
for (DenseMap<Value*, std::vector<Value*> >::iterator
|
for (DenseMap<Value *, std::vector<Value *>>::iterator
|
||||||
I = InsertedScalarizedValues.begin(), E = InsertedScalarizedValues.end();
|
I = InsertedScalarizedValues.begin(), E = InsertedScalarizedValues.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
if (PHINode *PN = dyn_cast<PHINode>(I->first))
|
if (PHINode *PN = dyn_cast<PHINode>(I->first))
|
||||||
|
@ -2275,7 +2292,7 @@ static void setUsedInitializer(GlobalVariable &V,
|
||||||
// Type of pointer to the array of pointers.
|
// Type of pointer to the array of pointers.
|
||||||
PointerType *Int8PtrTy = Type::getInt8PtrTy(V.getContext(), 0);
|
PointerType *Int8PtrTy = Type::getInt8PtrTy(V.getContext(), 0);
|
||||||
|
|
||||||
SmallVector<llvm::Constant *, 8> UsedArray;
|
SmallVector<Constant *, 8> UsedArray;
|
||||||
for (GlobalValue *GV : Init) {
|
for (GlobalValue *GV : Init) {
|
||||||
Constant *Cast
|
Constant *Cast
|
||||||
= ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, Int8PtrTy);
|
= ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, Int8PtrTy);
|
||||||
|
@ -2288,14 +2305,15 @@ static void setUsedInitializer(GlobalVariable &V,
|
||||||
Module *M = V.getParent();
|
Module *M = V.getParent();
|
||||||
V.removeFromParent();
|
V.removeFromParent();
|
||||||
GlobalVariable *NV =
|
GlobalVariable *NV =
|
||||||
new GlobalVariable(*M, ATy, false, llvm::GlobalValue::AppendingLinkage,
|
new GlobalVariable(*M, ATy, false, GlobalValue::AppendingLinkage,
|
||||||
llvm::ConstantArray::get(ATy, UsedArray), "");
|
ConstantArray::get(ATy, UsedArray), "");
|
||||||
NV->takeName(&V);
|
NV->takeName(&V);
|
||||||
NV->setSection("llvm.metadata");
|
NV->setSection("llvm.metadata");
|
||||||
delete &V;
|
delete &V;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// An easy to access representation of llvm.used and llvm.compiler.used.
|
/// An easy to access representation of llvm.used and llvm.compiler.used.
|
||||||
class LLVMUsed {
|
class LLVMUsed {
|
||||||
SmallPtrSet<GlobalValue *, 8> Used;
|
SmallPtrSet<GlobalValue *, 8> Used;
|
||||||
|
@ -2308,25 +2326,34 @@ public:
|
||||||
UsedV = collectUsedGlobalVariables(M, Used, false);
|
UsedV = collectUsedGlobalVariables(M, Used, false);
|
||||||
CompilerUsedV = collectUsedGlobalVariables(M, CompilerUsed, true);
|
CompilerUsedV = collectUsedGlobalVariables(M, CompilerUsed, true);
|
||||||
}
|
}
|
||||||
typedef SmallPtrSet<GlobalValue *, 8>::iterator iterator;
|
|
||||||
typedef iterator_range<iterator> used_iterator_range;
|
using iterator = SmallPtrSet<GlobalValue *, 8>::iterator;
|
||||||
|
using used_iterator_range = iterator_range<iterator>;
|
||||||
|
|
||||||
iterator usedBegin() { return Used.begin(); }
|
iterator usedBegin() { return Used.begin(); }
|
||||||
iterator usedEnd() { return Used.end(); }
|
iterator usedEnd() { return Used.end(); }
|
||||||
|
|
||||||
used_iterator_range used() {
|
used_iterator_range used() {
|
||||||
return used_iterator_range(usedBegin(), usedEnd());
|
return used_iterator_range(usedBegin(), usedEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator compilerUsedBegin() { return CompilerUsed.begin(); }
|
iterator compilerUsedBegin() { return CompilerUsed.begin(); }
|
||||||
iterator compilerUsedEnd() { return CompilerUsed.end(); }
|
iterator compilerUsedEnd() { return CompilerUsed.end(); }
|
||||||
|
|
||||||
used_iterator_range compilerUsed() {
|
used_iterator_range compilerUsed() {
|
||||||
return used_iterator_range(compilerUsedBegin(), compilerUsedEnd());
|
return used_iterator_range(compilerUsedBegin(), compilerUsedEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usedCount(GlobalValue *GV) const { return Used.count(GV); }
|
bool usedCount(GlobalValue *GV) const { return Used.count(GV); }
|
||||||
|
|
||||||
bool compilerUsedCount(GlobalValue *GV) const {
|
bool compilerUsedCount(GlobalValue *GV) const {
|
||||||
return CompilerUsed.count(GV);
|
return CompilerUsed.count(GV);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usedErase(GlobalValue *GV) { return Used.erase(GV); }
|
bool usedErase(GlobalValue *GV) { return Used.erase(GV); }
|
||||||
bool compilerUsedErase(GlobalValue *GV) { return CompilerUsed.erase(GV); }
|
bool compilerUsedErase(GlobalValue *GV) { return CompilerUsed.erase(GV); }
|
||||||
bool usedInsert(GlobalValue *GV) { return Used.insert(GV).second; }
|
bool usedInsert(GlobalValue *GV) { return Used.insert(GV).second; }
|
||||||
|
|
||||||
bool compilerUsedInsert(GlobalValue *GV) {
|
bool compilerUsedInsert(GlobalValue *GV) {
|
||||||
return CompilerUsed.insert(GV).second;
|
return CompilerUsed.insert(GV).second;
|
||||||
}
|
}
|
||||||
|
@ -2338,7 +2365,8 @@ public:
|
||||||
setUsedInitializer(*CompilerUsedV, CompilerUsed);
|
setUsedInitializer(*CompilerUsedV, CompilerUsed);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U) {
|
static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U) {
|
||||||
if (GA.use_empty()) // No use at all.
|
if (GA.use_empty()) // No use at all.
|
||||||
|
@ -2653,8 +2681,10 @@ PreservedAnalyses GlobalOptPass::run(Module &M, ModuleAnalysisManager &AM) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct GlobalOptLegacyPass : public ModulePass {
|
struct GlobalOptLegacyPass : public ModulePass {
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
|
|
||||||
GlobalOptLegacyPass() : ModulePass(ID) {
|
GlobalOptLegacyPass() : ModulePass(ID) {
|
||||||
initializeGlobalOptLegacyPassPass(*PassRegistry::getPassRegistry());
|
initializeGlobalOptLegacyPassPass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
|
@ -2676,9 +2706,11 @@ struct GlobalOptLegacyPass : public ModulePass {
|
||||||
AU.addRequired<DominatorTreeWrapperPass>();
|
AU.addRequired<DominatorTreeWrapperPass>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
char GlobalOptLegacyPass::ID = 0;
|
char GlobalOptLegacyPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS_BEGIN(GlobalOptLegacyPass, "globalopt",
|
INITIALIZE_PASS_BEGIN(GlobalOptLegacyPass, "globalopt",
|
||||||
"Global Variable Optimizer", false, false)
|
"Global Variable Optimizer", false, false)
|
||||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||||
|
|
|
@ -15,22 +15,30 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Transforms/IPO/GlobalSplit.h"
|
#include "llvm/Transforms/IPO/GlobalSplit.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/IR/Constant.h"
|
||||||
#include "llvm/IR/Constants.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/GlobalVariable.h"
|
||||||
#include "llvm/IR/Intrinsics.h"
|
#include "llvm/IR/Intrinsics.h"
|
||||||
|
#include "llvm/IR/LLVMContext.h"
|
||||||
|
#include "llvm/IR/Metadata.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/Operator.h"
|
#include "llvm/IR/Operator.h"
|
||||||
|
#include "llvm/IR/Type.h"
|
||||||
|
#include "llvm/IR/User.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Transforms/IPO.h"
|
#include "llvm/Transforms/IPO.h"
|
||||||
|
#include <cstdint>
|
||||||
#include <set>
|
#include <vector>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
static bool splitGlobal(GlobalVariable &GV) {
|
||||||
|
|
||||||
bool splitGlobal(GlobalVariable &GV) {
|
|
||||||
// If the address of the global is taken outside of the module, we cannot
|
// If the address of the global is taken outside of the module, we cannot
|
||||||
// apply this transformation.
|
// apply this transformation.
|
||||||
if (!GV.hasLocalLinkage())
|
if (!GV.hasLocalLinkage())
|
||||||
|
@ -130,7 +138,7 @@ bool splitGlobal(GlobalVariable &GV) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool splitGlobals(Module &M) {
|
static bool splitGlobals(Module &M) {
|
||||||
// First, see if the module uses either of the llvm.type.test or
|
// First, see if the module uses either of the llvm.type.test or
|
||||||
// llvm.type.checked.load intrinsics, which indicates that splitting globals
|
// llvm.type.checked.load intrinsics, which indicates that splitting globals
|
||||||
// may be beneficial.
|
// may be beneficial.
|
||||||
|
@ -151,12 +159,16 @@ bool splitGlobals(Module &M) {
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
struct GlobalSplit : public ModulePass {
|
struct GlobalSplit : public ModulePass {
|
||||||
static char ID;
|
static char ID;
|
||||||
|
|
||||||
GlobalSplit() : ModulePass(ID) {
|
GlobalSplit() : ModulePass(ID) {
|
||||||
initializeGlobalSplitPass(*PassRegistry::getPassRegistry());
|
initializeGlobalSplitPass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
bool runOnModule(Module &M) {
|
|
||||||
|
bool runOnModule(Module &M) override {
|
||||||
if (skipModule(M))
|
if (skipModule(M))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -164,10 +176,11 @@ struct GlobalSplit : public ModulePass {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
char GlobalSplit::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS(GlobalSplit, "globalsplit", "Global splitter", false, false)
|
INITIALIZE_PASS(GlobalSplit, "globalsplit", "Global splitter", false, false)
|
||||||
char GlobalSplit::ID = 0;
|
|
||||||
|
|
||||||
ModulePass *llvm::createGlobalSplitPass() {
|
ModulePass *llvm::createGlobalSplitPass() {
|
||||||
return new GlobalSplit;
|
return new GlobalSplit;
|
||||||
|
|
|
@ -13,26 +13,54 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Transforms/IPO/PartialInlining.h"
|
#include "llvm/Transforms/IPO/PartialInlining.h"
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/DenseSet.h"
|
||||||
|
#include "llvm/ADT/None.h"
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
||||||
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
||||||
#include "llvm/Analysis/CodeMetrics.h"
|
|
||||||
#include "llvm/Analysis/InlineCost.h"
|
#include "llvm/Analysis/InlineCost.h"
|
||||||
#include "llvm/Analysis/LoopInfo.h"
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
||||||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
||||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||||
|
#include "llvm/IR/Attributes.h"
|
||||||
|
#include "llvm/IR/BasicBlock.h"
|
||||||
#include "llvm/IR/CFG.h"
|
#include "llvm/IR/CFG.h"
|
||||||
|
#include "llvm/IR/CallSite.h"
|
||||||
|
#include "llvm/IR/DebugLoc.h"
|
||||||
#include "llvm/IR/DiagnosticInfo.h"
|
#include "llvm/IR/DiagnosticInfo.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/InstrTypes.h"
|
||||||
|
#include "llvm/IR/Instruction.h"
|
||||||
#include "llvm/IR/Instructions.h"
|
#include "llvm/IR/Instructions.h"
|
||||||
#include "llvm/IR/IntrinsicInst.h"
|
#include "llvm/IR/IntrinsicInst.h"
|
||||||
|
#include "llvm/IR/Intrinsics.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
|
#include "llvm/IR/User.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/BlockFrequency.h"
|
||||||
|
#include "llvm/Support/BranchProbability.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Transforms/IPO.h"
|
#include "llvm/Transforms/IPO.h"
|
||||||
#include "llvm/Transforms/Utils/Cloning.h"
|
#include "llvm/Transforms/Utils/Cloning.h"
|
||||||
#include "llvm/Transforms/Utils/CodeExtractor.h"
|
#include "llvm/Transforms/Utils/CodeExtractor.h"
|
||||||
|
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "partial-inlining"
|
#define DEBUG_TYPE "partial-inlining"
|
||||||
|
@ -44,6 +72,7 @@ STATISTIC(NumPartialInlined,
|
||||||
static cl::opt<bool>
|
static cl::opt<bool>
|
||||||
DisablePartialInlining("disable-partial-inlining", cl::init(false),
|
DisablePartialInlining("disable-partial-inlining", cl::init(false),
|
||||||
cl::Hidden, cl::desc("Disable partial ininling"));
|
cl::Hidden, cl::desc("Disable partial ininling"));
|
||||||
|
|
||||||
// This is an option used by testing:
|
// This is an option used by testing:
|
||||||
static cl::opt<bool> SkipCostAnalysis("skip-partial-inlining-cost-analysis",
|
static cl::opt<bool> SkipCostAnalysis("skip-partial-inlining-cost-analysis",
|
||||||
cl::init(false), cl::ZeroOrMore,
|
cl::init(false), cl::ZeroOrMore,
|
||||||
|
@ -76,9 +105,8 @@ static cl::opt<unsigned> ExtraOutliningPenalty(
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct FunctionOutliningInfo {
|
struct FunctionOutliningInfo {
|
||||||
FunctionOutliningInfo()
|
FunctionOutliningInfo() = default;
|
||||||
: Entries(), ReturnBlock(nullptr), NonReturnBlock(nullptr),
|
|
||||||
ReturnBlockPreds() {}
|
|
||||||
// Returns the number of blocks to be inlined including all blocks
|
// Returns the number of blocks to be inlined including all blocks
|
||||||
// in Entries and one return block.
|
// in Entries and one return block.
|
||||||
unsigned GetNumInlinedBlocks() const { return Entries.size() + 1; }
|
unsigned GetNumInlinedBlocks() const { return Entries.size() + 1; }
|
||||||
|
@ -86,10 +114,13 @@ struct FunctionOutliningInfo {
|
||||||
// A set of blocks including the function entry that guard
|
// A set of blocks including the function entry that guard
|
||||||
// the region to be outlined.
|
// the region to be outlined.
|
||||||
SmallVector<BasicBlock *, 4> Entries;
|
SmallVector<BasicBlock *, 4> Entries;
|
||||||
|
|
||||||
// The return block that is not included in the outlined region.
|
// The return block that is not included in the outlined region.
|
||||||
BasicBlock *ReturnBlock;
|
BasicBlock *ReturnBlock = nullptr;
|
||||||
|
|
||||||
// The dominating block of the region to be outlined.
|
// The dominating block of the region to be outlined.
|
||||||
BasicBlock *NonReturnBlock;
|
BasicBlock *NonReturnBlock = nullptr;
|
||||||
|
|
||||||
// The set of blocks in Entries that that are predecessors to ReturnBlock
|
// The set of blocks in Entries that that are predecessors to ReturnBlock
|
||||||
SmallVector<BasicBlock *, 4> ReturnBlockPreds;
|
SmallVector<BasicBlock *, 4> ReturnBlockPreds;
|
||||||
};
|
};
|
||||||
|
@ -101,6 +132,7 @@ struct PartialInlinerImpl {
|
||||||
Optional<function_ref<BlockFrequencyInfo &(Function &)>> GBFI,
|
Optional<function_ref<BlockFrequencyInfo &(Function &)>> GBFI,
|
||||||
ProfileSummaryInfo *ProfSI)
|
ProfileSummaryInfo *ProfSI)
|
||||||
: GetAssumptionCache(GetAC), GetTTI(GTTI), GetBFI(GBFI), PSI(ProfSI) {}
|
: GetAssumptionCache(GetAC), GetTTI(GTTI), GetBFI(GBFI), PSI(ProfSI) {}
|
||||||
|
|
||||||
bool run(Module &M);
|
bool run(Module &M);
|
||||||
Function *unswitchFunction(Function *F);
|
Function *unswitchFunction(Function *F);
|
||||||
|
|
||||||
|
@ -197,17 +229,18 @@ private:
|
||||||
// - The second value is the estimated size of the new call sequence in
|
// - The second value is the estimated size of the new call sequence in
|
||||||
// basic block Cloner.OutliningCallBB;
|
// basic block Cloner.OutliningCallBB;
|
||||||
std::tuple<int, int> computeOutliningCosts(FunctionCloner &Cloner);
|
std::tuple<int, int> computeOutliningCosts(FunctionCloner &Cloner);
|
||||||
|
|
||||||
// Compute the 'InlineCost' of block BB. InlineCost is a proxy used to
|
// Compute the 'InlineCost' of block BB. InlineCost is a proxy used to
|
||||||
// approximate both the size and runtime cost (Note that in the current
|
// approximate both the size and runtime cost (Note that in the current
|
||||||
// inline cost analysis, there is no clear distinction there either).
|
// inline cost analysis, there is no clear distinction there either).
|
||||||
static int computeBBInlineCost(BasicBlock *BB);
|
static int computeBBInlineCost(BasicBlock *BB);
|
||||||
|
|
||||||
std::unique_ptr<FunctionOutliningInfo> computeOutliningInfo(Function *F);
|
std::unique_ptr<FunctionOutliningInfo> computeOutliningInfo(Function *F);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PartialInlinerLegacyPass : public ModulePass {
|
struct PartialInlinerLegacyPass : public ModulePass {
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
|
|
||||||
PartialInlinerLegacyPass() : ModulePass(ID) {
|
PartialInlinerLegacyPass() : ModulePass(ID) {
|
||||||
initializePartialInlinerLegacyPassPass(*PassRegistry::getPassRegistry());
|
initializePartialInlinerLegacyPassPass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
|
@ -217,6 +250,7 @@ struct PartialInlinerLegacyPass : public ModulePass {
|
||||||
AU.addRequired<ProfileSummaryInfoWrapperPass>();
|
AU.addRequired<ProfileSummaryInfoWrapperPass>();
|
||||||
AU.addRequired<TargetTransformInfoWrapperPass>();
|
AU.addRequired<TargetTransformInfoWrapperPass>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runOnModule(Module &M) override {
|
bool runOnModule(Module &M) override {
|
||||||
if (skipModule(M))
|
if (skipModule(M))
|
||||||
return false;
|
return false;
|
||||||
|
@ -240,7 +274,8 @@ struct PartialInlinerLegacyPass : public ModulePass {
|
||||||
return PartialInlinerImpl(&GetAssumptionCache, &GetTTI, None, PSI).run(M);
|
return PartialInlinerImpl(&GetAssumptionCache, &GetTTI, None, PSI).run(M);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
std::unique_ptr<FunctionOutliningInfo>
|
std::unique_ptr<FunctionOutliningInfo>
|
||||||
PartialInlinerImpl::computeOutliningInfo(Function *F) {
|
PartialInlinerImpl::computeOutliningInfo(Function *F) {
|
||||||
|
@ -320,7 +355,6 @@ PartialInlinerImpl::computeOutliningInfo(Function *F) {
|
||||||
|
|
||||||
OutliningInfo->Entries.push_back(CurrEntry);
|
OutliningInfo->Entries.push_back(CurrEntry);
|
||||||
CurrEntry = OtherSucc;
|
CurrEntry = OtherSucc;
|
||||||
|
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
if (!CandidateFound)
|
if (!CandidateFound)
|
||||||
|
@ -414,7 +448,6 @@ static bool hasProfileData(Function *F, FunctionOutliningInfo *OI) {
|
||||||
|
|
||||||
BranchProbability
|
BranchProbability
|
||||||
PartialInlinerImpl::getOutliningCallBBRelativeFreq(FunctionCloner &Cloner) {
|
PartialInlinerImpl::getOutliningCallBBRelativeFreq(FunctionCloner &Cloner) {
|
||||||
|
|
||||||
auto EntryFreq =
|
auto EntryFreq =
|
||||||
Cloner.ClonedFuncBFI->getBlockFreq(&Cloner.ClonedFunc->getEntryBlock());
|
Cloner.ClonedFuncBFI->getBlockFreq(&Cloner.ClonedFunc->getEntryBlock());
|
||||||
auto OutliningCallFreq =
|
auto OutliningCallFreq =
|
||||||
|
@ -451,8 +484,8 @@ PartialInlinerImpl::getOutliningCallBBRelativeFreq(FunctionCloner &Cloner) {
|
||||||
bool PartialInlinerImpl::shouldPartialInline(
|
bool PartialInlinerImpl::shouldPartialInline(
|
||||||
CallSite CS, FunctionCloner &Cloner, BlockFrequency WeightedOutliningRcost,
|
CallSite CS, FunctionCloner &Cloner, BlockFrequency WeightedOutliningRcost,
|
||||||
OptimizationRemarkEmitter &ORE) {
|
OptimizationRemarkEmitter &ORE) {
|
||||||
|
|
||||||
using namespace ore;
|
using namespace ore;
|
||||||
|
|
||||||
if (SkipCostAnalysis)
|
if (SkipCostAnalysis)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -567,7 +600,6 @@ int PartialInlinerImpl::computeBBInlineCost(BasicBlock *BB) {
|
||||||
|
|
||||||
std::tuple<int, int>
|
std::tuple<int, int>
|
||||||
PartialInlinerImpl::computeOutliningCosts(FunctionCloner &Cloner) {
|
PartialInlinerImpl::computeOutliningCosts(FunctionCloner &Cloner) {
|
||||||
|
|
||||||
// Now compute the cost of the call sequence to the outlined function
|
// Now compute the cost of the call sequence to the outlined function
|
||||||
// 'OutlinedFunction' in BB 'OutliningCallBB':
|
// 'OutlinedFunction' in BB 'OutliningCallBB':
|
||||||
int OutliningFuncCallCost = computeBBInlineCost(Cloner.OutliningCallBB);
|
int OutliningFuncCallCost = computeBBInlineCost(Cloner.OutliningCallBB);
|
||||||
|
@ -661,7 +693,6 @@ PartialInlinerImpl::FunctionCloner::FunctionCloner(Function *F,
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartialInlinerImpl::FunctionCloner::NormalizeReturnBlock() {
|
void PartialInlinerImpl::FunctionCloner::NormalizeReturnBlock() {
|
||||||
|
|
||||||
auto getFirstPHI = [](BasicBlock *BB) {
|
auto getFirstPHI = [](BasicBlock *BB) {
|
||||||
BasicBlock::iterator I = BB->begin();
|
BasicBlock::iterator I = BB->begin();
|
||||||
PHINode *FirstPhi = nullptr;
|
PHINode *FirstPhi = nullptr;
|
||||||
|
@ -798,7 +829,6 @@ PartialInlinerImpl::FunctionCloner::~FunctionCloner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Function *PartialInlinerImpl::unswitchFunction(Function *F) {
|
Function *PartialInlinerImpl::unswitchFunction(Function *F) {
|
||||||
|
|
||||||
if (F->hasAddressTaken())
|
if (F->hasAddressTaken())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -955,6 +985,7 @@ bool PartialInlinerImpl::run(Module &M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char PartialInlinerLegacyPass::ID = 0;
|
char PartialInlinerLegacyPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS_BEGIN(PartialInlinerLegacyPass, "partial-inliner",
|
INITIALIZE_PASS_BEGIN(PartialInlinerLegacyPass, "partial-inliner",
|
||||||
"Partial Inliner", false, false)
|
"Partial Inliner", false, false)
|
||||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||||
|
|
Loading…
Reference in New Issue