mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[Transforms] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC).
llvm-svn: 316253
This commit is contained in:
parent
231a63268d
commit
e08f7dbc57
@ -1,4 +1,4 @@
|
||||
//===- Transforms/PGOInstrumentation.h - PGO gen/use passes ---*- C++ -*-===//
|
||||
//===- Transforms/PGOInstrumentation.h - PGO gen/use passes -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -6,19 +6,27 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// This file provides the interface for IR based instrumentation passes (
|
||||
/// (profile-gen, and profile-use).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TRANSFORMS_PGOINSTRUMENTATION_H
|
||||
#define LLVM_TRANSFORMS_PGOINSTRUMENTATION_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Function;
|
||||
class Instruction;
|
||||
class Module;
|
||||
|
||||
/// The instrumentation (profile-instr-gen) pass for IR based PGO.
|
||||
class PGOInstrumentationGen : public PassInfoMixin<PGOInstrumentationGen> {
|
||||
public:
|
||||
@ -28,9 +36,10 @@ public:
|
||||
/// The profile annotation (profile-instr-use) pass for IR based PGO.
|
||||
class PGOInstrumentationUse : public PassInfoMixin<PGOInstrumentationUse> {
|
||||
public:
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
||||
PGOInstrumentationUse(std::string Filename = "");
|
||||
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
||||
|
||||
private:
|
||||
std::string ProfileFileName;
|
||||
};
|
||||
@ -40,6 +49,7 @@ class PGOIndirectCallPromotion : public PassInfoMixin<PGOIndirectCallPromotion>
|
||||
public:
|
||||
PGOIndirectCallPromotion(bool IsInLTO = false, bool SamplePGO = false)
|
||||
: InLTO(IsInLTO), SamplePGO(SamplePGO) {}
|
||||
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
||||
|
||||
private:
|
||||
@ -50,12 +60,14 @@ private:
|
||||
/// The profile size based optimization pass for memory intrinsics.
|
||||
class PGOMemOPSizeOpt : public PassInfoMixin<PGOMemOPSizeOpt> {
|
||||
public:
|
||||
PGOMemOPSizeOpt() {}
|
||||
PGOMemOPSizeOpt() = default;
|
||||
|
||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
||||
};
|
||||
|
||||
void setProfMetadata(Module *M, Instruction *TI, ArrayRef<uint64_t> EdgeCounts,
|
||||
uint64_t MaxCount);
|
||||
|
||||
} // End llvm namespace
|
||||
#endif
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TRANSFORMS_PGOINSTRUMENTATION_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- DataFlowSanitizer.cpp - dynamic data flow analysis ----------------===//
|
||||
//===- DataFlowSanitizer.cpp - dynamic data flow analysis -----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -6,6 +6,7 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// This file is a part of DataFlowSanitizer, a generalised dynamic data flow
|
||||
/// analysis.
|
||||
@ -43,32 +44,63 @@
|
||||
///
|
||||
/// For more information, please refer to the design document:
|
||||
/// http://clang.llvm.org/docs/DataFlowSanitizerDesign.html
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/DepthFirstIterator.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/Argument.h"
|
||||
#include "llvm/IR/Attributes.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/GlobalAlias.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
#include "llvm/IR/InstVisitor.h"
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/IntrinsicInst.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/MDBuilder.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/IR/User.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/SpecialCaseList.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -129,10 +161,7 @@ static cl::opt<bool> ClDebugNonzeroLabels(
|
||||
"load or return with a nonzero label"),
|
||||
cl::Hidden);
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
StringRef GetGlobalTypeString(const GlobalValue &G) {
|
||||
static StringRef GetGlobalTypeString(const GlobalValue &G) {
|
||||
// Types of GlobalVariables are always pointer types.
|
||||
Type *GType = G.getValueType();
|
||||
// For now we support blacklisting struct types only.
|
||||
@ -143,11 +172,13 @@ StringRef GetGlobalTypeString(const GlobalValue &G) {
|
||||
return "<unknown type>";
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class DFSanABIList {
|
||||
std::unique_ptr<SpecialCaseList> SCL;
|
||||
|
||||
public:
|
||||
DFSanABIList() {}
|
||||
DFSanABIList() = default;
|
||||
|
||||
void set(std::unique_ptr<SpecialCaseList> List) { SCL = std::move(List); }
|
||||
|
||||
@ -256,7 +287,7 @@ class DataFlowSanitizer : public ModulePass {
|
||||
DFSanABIList ABIList;
|
||||
DenseMap<Value *, Function *> UnwrappedFnMap;
|
||||
AttrBuilder ReadOnlyNoneAttrs;
|
||||
bool DFSanRuntimeShadowMask;
|
||||
bool DFSanRuntimeShadowMask = false;
|
||||
|
||||
Value *getShadowAddress(Value *Addr, Instruction *Pos);
|
||||
bool isInstrumented(const Function *F);
|
||||
@ -272,11 +303,13 @@ class DataFlowSanitizer : public ModulePass {
|
||||
FunctionType *NewFT);
|
||||
Constant *getOrBuildTrampolineFunction(FunctionType *FT, StringRef FName);
|
||||
|
||||
public:
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
DataFlowSanitizer(
|
||||
const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
|
||||
void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr);
|
||||
static char ID;
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
bool runOnModule(Module &M) override;
|
||||
};
|
||||
@ -287,12 +320,12 @@ struct DFSanFunction {
|
||||
DominatorTree DT;
|
||||
DataFlowSanitizer::InstrumentedABI IA;
|
||||
bool IsNativeABI;
|
||||
Value *ArgTLSPtr;
|
||||
Value *RetvalTLSPtr;
|
||||
AllocaInst *LabelReturnAlloca;
|
||||
Value *ArgTLSPtr = nullptr;
|
||||
Value *RetvalTLSPtr = nullptr;
|
||||
AllocaInst *LabelReturnAlloca = nullptr;
|
||||
DenseMap<Value *, Value *> ValShadowMap;
|
||||
DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap;
|
||||
std::vector<std::pair<PHINode *, PHINode *> > PHIFixups;
|
||||
std::vector<std::pair<PHINode *, PHINode *>> PHIFixups;
|
||||
DenseSet<Instruction *> SkipInsts;
|
||||
std::vector<Value *> NonZeroChecks;
|
||||
bool AvoidNewBlocks;
|
||||
@ -306,14 +339,13 @@ struct DFSanFunction {
|
||||
DenseMap<Value *, std::set<Value *>> ShadowElements;
|
||||
|
||||
DFSanFunction(DataFlowSanitizer &DFS, Function *F, bool IsNativeABI)
|
||||
: DFS(DFS), F(F), IA(DFS.getInstrumentedABI()),
|
||||
IsNativeABI(IsNativeABI), ArgTLSPtr(nullptr), RetvalTLSPtr(nullptr),
|
||||
LabelReturnAlloca(nullptr) {
|
||||
: DFS(DFS), F(F), IA(DFS.getInstrumentedABI()), IsNativeABI(IsNativeABI) {
|
||||
DT.recalculate(*F);
|
||||
// FIXME: Need to track down the register allocator issue which causes poor
|
||||
// performance in pathological cases with large numbers of basic blocks.
|
||||
AvoidNewBlocks = F->size() > 1000;
|
||||
}
|
||||
|
||||
Value *getArgTLSPtr();
|
||||
Value *getArgTLS(unsigned Index, Instruction *Pos);
|
||||
Value *getRetvalTLS();
|
||||
@ -328,8 +360,9 @@ struct DFSanFunction {
|
||||
};
|
||||
|
||||
class DFSanVisitor : public InstVisitor<DFSanVisitor> {
|
||||
public:
|
||||
public:
|
||||
DFSanFunction &DFSF;
|
||||
|
||||
DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
|
||||
|
||||
const DataLayout &getDataLayout() const {
|
||||
@ -337,7 +370,6 @@ class DFSanVisitor : public InstVisitor<DFSanVisitor> {
|
||||
}
|
||||
|
||||
void visitOperandShadowInst(Instruction &I);
|
||||
|
||||
void visitBinaryOperator(BinaryOperator &BO);
|
||||
void visitCastInst(CastInst &CI);
|
||||
void visitCmpInst(CmpInst &CI);
|
||||
@ -358,9 +390,10 @@ class DFSanVisitor : public InstVisitor<DFSanVisitor> {
|
||||
void visitMemTransferInst(MemTransferInst &I);
|
||||
};
|
||||
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
char DataFlowSanitizer::ID;
|
||||
|
||||
INITIALIZE_PASS(DataFlowSanitizer, "dfsan",
|
||||
"DataFlowSanitizer: dynamic data flow analysis.", false, false)
|
||||
|
||||
@ -374,8 +407,7 @@ llvm::createDataFlowSanitizerPass(const std::vector<std::string> &ABIListFiles,
|
||||
DataFlowSanitizer::DataFlowSanitizer(
|
||||
const std::vector<std::string> &ABIListFiles, void *(*getArgTLS)(),
|
||||
void *(*getRetValTLS)())
|
||||
: ModulePass(ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS),
|
||||
DFSanRuntimeShadowMask(false) {
|
||||
: ModulePass(ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS) {
|
||||
std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
|
||||
AllABIListFiles.insert(AllABIListFiles.end(), ClABIListFiles.begin(),
|
||||
ClABIListFiles.end());
|
||||
@ -383,7 +415,7 @@ DataFlowSanitizer::DataFlowSanitizer(
|
||||
}
|
||||
|
||||
FunctionType *DataFlowSanitizer::getArgsFunctionType(FunctionType *T) {
|
||||
llvm::SmallVector<Type *, 4> ArgTypes(T->param_begin(), T->param_end());
|
||||
SmallVector<Type *, 4> ArgTypes(T->param_begin(), T->param_end());
|
||||
ArgTypes.append(T->getNumParams(), ShadowTy);
|
||||
if (T->isVarArg())
|
||||
ArgTypes.push_back(ShadowPtrTy);
|
||||
@ -395,7 +427,7 @@ FunctionType *DataFlowSanitizer::getArgsFunctionType(FunctionType *T) {
|
||||
|
||||
FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) {
|
||||
assert(!T->isVarArg());
|
||||
llvm::SmallVector<Type *, 4> ArgTypes;
|
||||
SmallVector<Type *, 4> ArgTypes;
|
||||
ArgTypes.push_back(T->getPointerTo());
|
||||
ArgTypes.append(T->param_begin(), T->param_end());
|
||||
ArgTypes.append(T->getNumParams(), ShadowTy);
|
||||
@ -406,7 +438,7 @@ FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) {
|
||||
}
|
||||
|
||||
FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
|
||||
llvm::SmallVector<Type *, 4> ArgTypes;
|
||||
SmallVector<Type *, 4> ArgTypes;
|
||||
for (FunctionType::param_iterator i = T->param_begin(), e = T->param_end();
|
||||
i != e; ++i) {
|
||||
FunctionType *FT;
|
||||
@ -429,12 +461,12 @@ FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
|
||||
}
|
||||
|
||||
bool DataFlowSanitizer::doInitialization(Module &M) {
|
||||
llvm::Triple TargetTriple(M.getTargetTriple());
|
||||
bool IsX86_64 = TargetTriple.getArch() == llvm::Triple::x86_64;
|
||||
bool IsMIPS64 = TargetTriple.getArch() == llvm::Triple::mips64 ||
|
||||
TargetTriple.getArch() == llvm::Triple::mips64el;
|
||||
bool IsAArch64 = TargetTriple.getArch() == llvm::Triple::aarch64 ||
|
||||
TargetTriple.getArch() == llvm::Triple::aarch64_be;
|
||||
Triple TargetTriple(M.getTargetTriple());
|
||||
bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64;
|
||||
bool IsMIPS64 = TargetTriple.getArch() == Triple::mips64 ||
|
||||
TargetTriple.getArch() == Triple::mips64el;
|
||||
bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64 ||
|
||||
TargetTriple.getArch() == Triple::aarch64_be;
|
||||
|
||||
const DataLayout &DL = M.getDataLayout();
|
||||
|
||||
@ -655,7 +687,7 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
|
||||
DFSanVarargWrapperFnTy);
|
||||
|
||||
std::vector<Function *> FnsToInstrument;
|
||||
llvm::SmallPtrSet<Function *, 2> FnsWithNativeABI;
|
||||
SmallPtrSet<Function *, 2> FnsWithNativeABI;
|
||||
for (Function &i : M) {
|
||||
if (!i.isIntrinsic() &&
|
||||
&i != DFSanUnionFn &&
|
||||
@ -798,11 +830,11 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
|
||||
|
||||
// DFSanVisitor may create new basic blocks, which confuses df_iterator.
|
||||
// Build a copy of the list before iterating over it.
|
||||
llvm::SmallVector<BasicBlock *, 4> BBList(depth_first(&i->getEntryBlock()));
|
||||
SmallVector<BasicBlock *, 4> BBList(depth_first(&i->getEntryBlock()));
|
||||
|
||||
for (BasicBlock *i : BBList) {
|
||||
Instruction *Inst = &i->front();
|
||||
while (1) {
|
||||
while (true) {
|
||||
// DFSanVisitor may split the current basic block, changing the current
|
||||
// instruction's next pointer and moving the next instruction to the
|
||||
// tail block from which we should continue.
|
||||
@ -822,7 +854,7 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
|
||||
// until we have visited every block. Therefore, the code that handles phi
|
||||
// nodes adds them to the PHIFixups list so that they can be properly
|
||||
// handled here.
|
||||
for (std::vector<std::pair<PHINode *, PHINode *> >::iterator
|
||||
for (std::vector<std::pair<PHINode *, PHINode *>>::iterator
|
||||
i = DFSF.PHIFixups.begin(),
|
||||
e = DFSF.PHIFixups.end();
|
||||
i != e; ++i) {
|
||||
@ -1046,8 +1078,7 @@ void DFSanVisitor::visitOperandShadowInst(Instruction &I) {
|
||||
Value *DFSanFunction::loadShadow(Value *Addr, uint64_t Size, uint64_t Align,
|
||||
Instruction *Pos) {
|
||||
if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
|
||||
llvm::DenseMap<AllocaInst *, AllocaInst *>::iterator i =
|
||||
AllocaShadowMap.find(AI);
|
||||
const auto i = AllocaShadowMap.find(AI);
|
||||
if (i != AllocaShadowMap.end()) {
|
||||
IRBuilder<> IRB(Pos);
|
||||
return IRB.CreateLoad(i->second);
|
||||
@ -1188,8 +1219,7 @@ void DFSanVisitor::visitLoadInst(LoadInst &LI) {
|
||||
void DFSanFunction::storeShadow(Value *Addr, uint64_t Size, uint64_t Align,
|
||||
Value *Shadow, Instruction *Pos) {
|
||||
if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
|
||||
llvm::DenseMap<AllocaInst *, AllocaInst *>::iterator i =
|
||||
AllocaShadowMap.find(AI);
|
||||
const auto i = AllocaShadowMap.find(AI);
|
||||
if (i != AllocaShadowMap.end()) {
|
||||
IRBuilder<> IRB(Pos);
|
||||
IRB.CreateStore(Shadow, i->second);
|
||||
@ -1410,24 +1440,21 @@ void DFSanVisitor::visitCallSite(CallSite CS) {
|
||||
if (i != DFSF.DFS.UnwrappedFnMap.end()) {
|
||||
Function *F = i->second;
|
||||
switch (DFSF.DFS.getWrapperKind(F)) {
|
||||
case DataFlowSanitizer::WK_Warning: {
|
||||
case DataFlowSanitizer::WK_Warning:
|
||||
CS.setCalledFunction(F);
|
||||
IRB.CreateCall(DFSF.DFS.DFSanUnimplementedFn,
|
||||
IRB.CreateGlobalStringPtr(F->getName()));
|
||||
DFSF.setShadow(CS.getInstruction(), DFSF.DFS.ZeroShadow);
|
||||
return;
|
||||
}
|
||||
case DataFlowSanitizer::WK_Discard: {
|
||||
case DataFlowSanitizer::WK_Discard:
|
||||
CS.setCalledFunction(F);
|
||||
DFSF.setShadow(CS.getInstruction(), DFSF.DFS.ZeroShadow);
|
||||
return;
|
||||
}
|
||||
case DataFlowSanitizer::WK_Functional: {
|
||||
case DataFlowSanitizer::WK_Functional:
|
||||
CS.setCalledFunction(F);
|
||||
visitOperandShadowInst(*CS.getInstruction());
|
||||
return;
|
||||
}
|
||||
case DataFlowSanitizer::WK_Custom: {
|
||||
case DataFlowSanitizer::WK_Custom:
|
||||
// Don't try to handle invokes of custom functions, it's too complicated.
|
||||
// Instead, invoke the dfsw$ wrapper, which will in turn call the __dfsw_
|
||||
// wrapper.
|
||||
@ -1527,7 +1554,6 @@ void DFSanVisitor::visitCallSite(CallSite CS) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FunctionType *FT = cast<FunctionType>(
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- IndirectCallPromotion.cpp - Optimizations based on value profiling ===//
|
||||
//===- IndirectCallPromotion.cpp - Optimizations based on value profiling -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -14,15 +14,15 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
|
||||
#include "llvm/Analysis/IndirectCallSiteVisitor.h"
|
||||
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
||||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||
#include "llvm/IR/Attributes.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
@ -36,20 +36,22 @@
|
||||
#include "llvm/IR/MDBuilder.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/PassRegistry.h"
|
||||
#include "llvm/PassSupport.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include "llvm/Transforms/PGOInstrumentation.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
@ -112,6 +114,7 @@ static cl::opt<bool>
|
||||
cl::desc("Dump IR after transformation happens"));
|
||||
|
||||
namespace {
|
||||
|
||||
class PGOIndirectCallPromotionLegacyPass : public ModulePass {
|
||||
public:
|
||||
static char ID;
|
||||
@ -139,9 +142,11 @@ private:
|
||||
// the promoted direct call.
|
||||
bool SamplePGO;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
char PGOIndirectCallPromotionLegacyPass::ID = 0;
|
||||
|
||||
INITIALIZE_PASS_BEGIN(PGOIndirectCallPromotionLegacyPass, "pgo-icall-prom",
|
||||
"Use PGO instrumentation profile to promote indirect "
|
||||
"calls to direct calls.",
|
||||
@ -158,6 +163,7 @@ ModulePass *llvm::createPGOIndirectCallPromotionLegacyPass(bool InLTO,
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// The class for main data structure to promote indirect calls to conditional
|
||||
// direct calls.
|
||||
class ICallPromotionFunc {
|
||||
@ -177,6 +183,7 @@ private:
|
||||
struct PromotionCandidate {
|
||||
Function *TargetFunction;
|
||||
uint64_t Count;
|
||||
|
||||
PromotionCandidate(Function *F, uint64_t C) : TargetFunction(F), Count(C) {}
|
||||
};
|
||||
|
||||
@ -195,17 +202,16 @@ private:
|
||||
const std::vector<PromotionCandidate> &Candidates,
|
||||
uint64_t &TotalCount);
|
||||
|
||||
// Noncopyable
|
||||
ICallPromotionFunc(const ICallPromotionFunc &other) = delete;
|
||||
ICallPromotionFunc &operator=(const ICallPromotionFunc &other) = delete;
|
||||
|
||||
public:
|
||||
ICallPromotionFunc(Function &Func, Module *Modu, InstrProfSymtab *Symtab,
|
||||
bool SamplePGO, OptimizationRemarkEmitter &ORE)
|
||||
: F(Func), M(Modu), Symtab(Symtab), SamplePGO(SamplePGO), ORE(ORE) {}
|
||||
ICallPromotionFunc(const ICallPromotionFunc &) = delete;
|
||||
ICallPromotionFunc &operator=(const ICallPromotionFunc &) = delete;
|
||||
|
||||
bool processFunction(ProfileSummaryInfo *PSI);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
bool llvm::isLegalToPromote(Instruction *Inst, Function *F,
|
||||
@ -313,6 +319,7 @@ ICallPromotionFunc::getPromotionCandidatesForCallSite(
|
||||
const char *Reason = nullptr;
|
||||
if (!isLegalToPromote(Inst, TargetFunction, &Reason)) {
|
||||
using namespace ore;
|
||||
|
||||
ORE.emit([&]() {
|
||||
return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToPromote", Inst)
|
||||
<< "Cannot promote indirect call to "
|
||||
@ -613,6 +620,7 @@ Instruction *llvm::promoteIndirectCall(Instruction *Inst,
|
||||
DEBUG(dbgs() << *BB << *DirectCallBB << *IndirectCallBB << *MergeBB << "\n");
|
||||
|
||||
using namespace ore;
|
||||
|
||||
if (ORE)
|
||||
ORE->emit([&]() {
|
||||
return OptimizationRemark(DEBUG_TYPE, "Promoted", Inst)
|
||||
@ -700,7 +708,7 @@ static bool promoteIndirectCalls(Module &M, ProfileSummaryInfo *PSI,
|
||||
AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
||||
ORE = &FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
|
||||
} else {
|
||||
OwnedORE = make_unique<OptimizationRemarkEmitter>(&F);
|
||||
OwnedORE = llvm::make_unique<OptimizationRemarkEmitter>(&F);
|
||||
ORE = OwnedORE.get();
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- PGOInstrumentation.cpp - MST-based PGO Instrumentation ------------===//
|
||||
//===- PGOInstrumentation.cpp - MST-based PGO Instrumentation -------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -50,37 +50,69 @@
|
||||
|
||||
#include "llvm/Transforms/PGOInstrumentation.h"
|
||||
#include "CFGMST.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
||||
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/IndirectCallSiteVisitor.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
||||
#include "llvm/IR/Attributes.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/Comdat.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DiagnosticInfo.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/GlobalAlias.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/InstVisitor.h"
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/IntrinsicInst.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/MDBuilder.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/IR/ProfileSummary.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/ProfileData/InstrProfReader.h"
|
||||
#include "llvm/ProfileData/ProfileCommon.h"
|
||||
#include "llvm/Support/BranchProbability.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/DOTGraphTraits.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
#include "llvm/Support/JamCRC.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
@ -202,11 +234,9 @@ extern cl::opt<PGOViewCountsType> PGOViewCounts;
|
||||
// Defined in Analysis/BlockFrequencyInfo.cpp: -view-bfi-func-name=
|
||||
extern cl::opt<std::string> ViewBlockFreqFuncName;
|
||||
|
||||
namespace {
|
||||
|
||||
// Return a string describing the branch condition that can be
|
||||
// used in static branch probability heuristics:
|
||||
std::string getBranchCondString(Instruction *TI) {
|
||||
static std::string getBranchCondString(Instruction *TI) {
|
||||
BranchInst *BI = dyn_cast<BranchInst>(TI);
|
||||
if (!BI || !BI->isConditional())
|
||||
return std::string();
|
||||
@ -237,6 +267,8 @@ std::string getBranchCondString(Instruction *TI) {
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// The select instruction visitor plays three roles specified
|
||||
/// by the mode. In \c VM_counting mode, it simply counts the number of
|
||||
/// select instructions. In \c VM_instrument mode, it inserts code to count
|
||||
@ -263,6 +295,7 @@ struct SelectInstVisitor : public InstVisitor<SelectInstVisitor> {
|
||||
Mode = VM_counting;
|
||||
visit(Func);
|
||||
}
|
||||
|
||||
// Visit the IR stream and instrument all select instructions. \p
|
||||
// Ind is a pointer to the counter index variable; \p TotalNC
|
||||
// is the total number of counters; \p FNV is the pointer to the
|
||||
@ -287,8 +320,10 @@ struct SelectInstVisitor : public InstVisitor<SelectInstVisitor> {
|
||||
|
||||
void instrumentOneSelectInst(SelectInst &SI);
|
||||
void annotateOneSelectInst(SelectInst &SI);
|
||||
|
||||
// Visit \p SI instruction and perform tasks according to visit mode.
|
||||
void visitSelectInst(SelectInst &SI);
|
||||
|
||||
// Return the number of select instructions. This needs be called after
|
||||
// countSelects().
|
||||
unsigned getNumOfSelectInsts() const { return NSIs; }
|
||||
@ -332,8 +367,10 @@ struct MemIntrinsicVisitor : public InstVisitor<MemIntrinsicVisitor> {
|
||||
|
||||
// Visit the IR stream and annotate all mem intrinsic call instructions.
|
||||
void instrumentOneMemIntrinsic(MemIntrinsic &MI);
|
||||
|
||||
// Visit \p MI instruction and perform tasks according to visit mode.
|
||||
void visitMemIntrinsic(MemIntrinsic &SI);
|
||||
|
||||
unsigned getNumOfMemIntrinsics() const { return NMemIs; }
|
||||
};
|
||||
|
||||
@ -375,6 +412,7 @@ private:
|
||||
std::string ProfileFileName;
|
||||
|
||||
bool runOnModule(Module &M) override;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<BlockFrequencyInfoWrapperPass>();
|
||||
}
|
||||
@ -383,6 +421,7 @@ private:
|
||||
} // end anonymous namespace
|
||||
|
||||
char PGOInstrumentationGenLegacyPass::ID = 0;
|
||||
|
||||
INITIALIZE_PASS_BEGIN(PGOInstrumentationGenLegacyPass, "pgo-instr-gen",
|
||||
"PGO instrumentation.", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
|
||||
@ -395,6 +434,7 @@ ModulePass *llvm::createPGOInstrumentationGenLegacyPass() {
|
||||
}
|
||||
|
||||
char PGOInstrumentationUseLegacyPass::ID = 0;
|
||||
|
||||
INITIALIZE_PASS_BEGIN(PGOInstrumentationUseLegacyPass, "pgo-instr-use",
|
||||
"Read PGO instrumentation profile.", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
|
||||
@ -407,6 +447,7 @@ ModulePass *llvm::createPGOInstrumentationUseLegacyPass(StringRef Filename) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief An MST based instrumentation for PGO
|
||||
///
|
||||
/// Implements a Minimum Spanning Tree (MST) based instrumentation for PGO
|
||||
@ -417,12 +458,13 @@ struct PGOEdge {
|
||||
const BasicBlock *SrcBB;
|
||||
const BasicBlock *DestBB;
|
||||
uint64_t Weight;
|
||||
bool InMST;
|
||||
bool Removed;
|
||||
bool IsCritical;
|
||||
bool InMST = false;
|
||||
bool Removed = false;
|
||||
bool IsCritical = false;
|
||||
|
||||
PGOEdge(const BasicBlock *Src, const BasicBlock *Dest, unsigned W = 1)
|
||||
: SrcBB(Src), DestBB(Dest), Weight(W), InMST(false), Removed(false),
|
||||
IsCritical(false) {}
|
||||
: SrcBB(Src), DestBB(Dest), Weight(W) {}
|
||||
|
||||
// Return the information string of an edge.
|
||||
const std::string infoString() const {
|
||||
return (Twine(Removed ? "-" : " ") + (InMST ? " " : "*") +
|
||||
@ -434,9 +476,9 @@ struct PGOEdge {
|
||||
struct BBInfo {
|
||||
BBInfo *Group;
|
||||
uint32_t Index;
|
||||
uint32_t Rank;
|
||||
uint32_t Rank = 0;
|
||||
|
||||
BBInfo(unsigned IX) : Group(this), Index(IX), Rank(0) {}
|
||||
BBInfo(unsigned IX) : Group(this), Index(IX) {}
|
||||
|
||||
// Return the information string of this object.
|
||||
const std::string infoString() const {
|
||||
@ -448,19 +490,22 @@ struct BBInfo {
|
||||
template <class Edge, class BBInfo> class FuncPGOInstrumentation {
|
||||
private:
|
||||
Function &F;
|
||||
void computeCFGHash();
|
||||
void renameComdatFunction();
|
||||
|
||||
// A map that stores the Comdat group in function F.
|
||||
std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers;
|
||||
|
||||
void computeCFGHash();
|
||||
void renameComdatFunction();
|
||||
|
||||
public:
|
||||
std::vector<std::vector<Instruction *>> ValueSites;
|
||||
SelectInstVisitor SIVisitor;
|
||||
MemIntrinsicVisitor MIVisitor;
|
||||
std::string FuncName;
|
||||
GlobalVariable *FuncNameVar;
|
||||
|
||||
// CFG hash value for this function.
|
||||
uint64_t FunctionHash;
|
||||
uint64_t FunctionHash = 0;
|
||||
|
||||
// The Minimum Spanning Tree of function CFG.
|
||||
CFGMST<Edge, BBInfo> MST;
|
||||
@ -487,8 +532,7 @@ public:
|
||||
bool CreateGlobalVar = false, BranchProbabilityInfo *BPI = nullptr,
|
||||
BlockFrequencyInfo *BFI = nullptr)
|
||||
: F(Func), ComdatMembers(ComdatMembers), ValueSites(IPVK_Last + 1),
|
||||
SIVisitor(Func), MIVisitor(Func), FunctionHash(0), MST(F, BPI, BFI) {
|
||||
|
||||
SIVisitor(Func), MIVisitor(Func), MST(F, BPI, BFI) {
|
||||
// This should be done before CFG hash computation.
|
||||
SIVisitor.countSelects(Func);
|
||||
MIVisitor.countMemIntrinsics(Func);
|
||||
@ -499,7 +543,7 @@ public:
|
||||
|
||||
FuncName = getPGOFuncName(F);
|
||||
computeCFGHash();
|
||||
if (ComdatMembers.size())
|
||||
if (!ComdatMembers.empty())
|
||||
renameComdatFunction();
|
||||
DEBUG(dumpInfo("after CFGMST"));
|
||||
|
||||
@ -527,6 +571,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
// Compute Hash value for the CFG: the lower 32 bits are CRC32 of the index
|
||||
// value of each BB in the CFG. The higher 32 bits record the number of edges.
|
||||
template <class Edge, class BBInfo>
|
||||
@ -686,7 +732,7 @@ static void instrumentOneFunc(
|
||||
"Cannot get the Instrumentation point");
|
||||
Builder.CreateCall(
|
||||
Intrinsic::getDeclaration(M, Intrinsic::instrprof_increment),
|
||||
{llvm::ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy),
|
||||
{ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy),
|
||||
Builder.getInt64(FuncInfo.FunctionHash), Builder.getInt32(NumCounters),
|
||||
Builder.getInt32(I++)});
|
||||
}
|
||||
@ -710,7 +756,7 @@ static void instrumentOneFunc(
|
||||
"Cannot get the Instrumentation point");
|
||||
Builder.CreateCall(
|
||||
Intrinsic::getDeclaration(M, Intrinsic::instrprof_value_profile),
|
||||
{llvm::ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy),
|
||||
{ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy),
|
||||
Builder.getInt64(FuncInfo.FunctionHash),
|
||||
Builder.CreatePtrToInt(Callee, Builder.getInt64Ty()),
|
||||
Builder.getInt32(IPVK_IndirectCallTarget),
|
||||
@ -723,12 +769,15 @@ static void instrumentOneFunc(
|
||||
F, NumCounters, FuncInfo.FuncNameVar, FuncInfo.FunctionHash);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// This class represents a CFG edge in profile use compilation.
|
||||
struct PGOUseEdge : public PGOEdge {
|
||||
bool CountValid;
|
||||
uint64_t CountValue;
|
||||
bool CountValid = false;
|
||||
uint64_t CountValue = 0;
|
||||
|
||||
PGOUseEdge(const BasicBlock *Src, const BasicBlock *Dest, unsigned W = 1)
|
||||
: PGOEdge(Src, Dest, W), CountValid(false), CountValue(0) {}
|
||||
: PGOEdge(Src, Dest, W) {}
|
||||
|
||||
// Set edge count value
|
||||
void setEdgeCount(uint64_t Value) {
|
||||
@ -745,22 +794,21 @@ struct PGOUseEdge : public PGOEdge {
|
||||
}
|
||||
};
|
||||
|
||||
typedef SmallVector<PGOUseEdge *, 2> DirectEdges;
|
||||
using DirectEdges = SmallVector<PGOUseEdge *, 2>;
|
||||
|
||||
// This class stores the auxiliary information for each BB.
|
||||
struct UseBBInfo : public BBInfo {
|
||||
uint64_t CountValue;
|
||||
uint64_t CountValue = 0;
|
||||
bool CountValid;
|
||||
int32_t UnknownCountInEdge;
|
||||
int32_t UnknownCountOutEdge;
|
||||
int32_t UnknownCountInEdge = 0;
|
||||
int32_t UnknownCountOutEdge = 0;
|
||||
DirectEdges InEdges;
|
||||
DirectEdges OutEdges;
|
||||
UseBBInfo(unsigned IX)
|
||||
: BBInfo(IX), CountValue(0), CountValid(false), UnknownCountInEdge(0),
|
||||
UnknownCountOutEdge(0) {}
|
||||
|
||||
UseBBInfo(unsigned IX) : BBInfo(IX), CountValid(false) {}
|
||||
|
||||
UseBBInfo(unsigned IX, uint64_t C)
|
||||
: BBInfo(IX), CountValue(C), CountValid(true), UnknownCountInEdge(0),
|
||||
UnknownCountOutEdge(0) {}
|
||||
: BBInfo(IX), CountValue(C), CountValid(true) {}
|
||||
|
||||
// Set the profile count value for this BB.
|
||||
void setBBInfoCount(uint64_t Value) {
|
||||
@ -776,6 +824,8 @@ struct UseBBInfo : public BBInfo {
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
// Sum up the count values for all the edges.
|
||||
static uint64_t sumEdgeCount(const ArrayRef<PGOUseEdge *> Edges) {
|
||||
uint64_t Total = 0;
|
||||
@ -787,6 +837,8 @@ static uint64_t sumEdgeCount(const ArrayRef<PGOUseEdge *> Edges) {
|
||||
return Total;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class PGOUseFunc {
|
||||
public:
|
||||
PGOUseFunc(Function &Func, Module *Modu,
|
||||
@ -794,7 +846,7 @@ public:
|
||||
BranchProbabilityInfo *BPI = nullptr,
|
||||
BlockFrequencyInfo *BFI = nullptr)
|
||||
: F(Func), M(Modu), FuncInfo(Func, ComdatMembers, false, BPI, BFI),
|
||||
CountPosition(0), ProfileCountSize(0), FreqAttr(FFA_Normal) {}
|
||||
FreqAttr(FFA_Normal) {}
|
||||
|
||||
// Read counts for the instrumented BB from profile.
|
||||
bool readCounters(IndexedInstrProfReader *PGOReader);
|
||||
@ -819,6 +871,7 @@ public:
|
||||
|
||||
// Return the function hash.
|
||||
uint64_t getFuncHash() const { return FuncInfo.FunctionHash; }
|
||||
|
||||
// Return the profile record for this function;
|
||||
InstrProfRecord &getProfileRecord() { return ProfileRecord; }
|
||||
|
||||
@ -841,6 +894,7 @@ public:
|
||||
private:
|
||||
Function &F;
|
||||
Module *M;
|
||||
|
||||
// This member stores the shared information with class PGOGenFunc.
|
||||
FuncPGOInstrumentation<PGOUseEdge, UseBBInfo> FuncInfo;
|
||||
|
||||
@ -849,10 +903,10 @@ private:
|
||||
uint64_t ProgramMaxCount;
|
||||
|
||||
// Position of counter that remains to be read.
|
||||
uint32_t CountPosition;
|
||||
uint32_t CountPosition = 0;
|
||||
|
||||
// Total size of the profile count for this function.
|
||||
uint32_t ProfileCountSize;
|
||||
uint32_t ProfileCountSize = 0;
|
||||
|
||||
// ProfileRecord for this function.
|
||||
InstrProfRecord ProfileRecord;
|
||||
@ -887,11 +941,12 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
// Visit all the edges and assign the count value for the instrumented
|
||||
// edges and the BB.
|
||||
void PGOUseFunc::setInstrumentedCounts(
|
||||
const std::vector<uint64_t> &CountFromProfile) {
|
||||
|
||||
assert(FuncInfo.getNumCounters() == CountFromProfile.size());
|
||||
// Use a worklist as we will update the vector during the iteration.
|
||||
std::vector<PGOUseEdge *> WorkList;
|
||||
@ -1136,7 +1191,7 @@ void SelectInstVisitor::instrumentOneSelectInst(SelectInst &SI) {
|
||||
auto *Step = Builder.CreateZExt(SI.getCondition(), Int64Ty);
|
||||
Builder.CreateCall(
|
||||
Intrinsic::getDeclaration(M, Intrinsic::instrprof_increment_step),
|
||||
{llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
|
||||
{ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
|
||||
Builder.getInt64(FuncHash), Builder.getInt32(TotalNumCtrs),
|
||||
Builder.getInt32(*CurCtrIdx), Step});
|
||||
++(*CurCtrIdx);
|
||||
@ -1191,7 +1246,7 @@ void MemIntrinsicVisitor::instrumentOneMemIntrinsic(MemIntrinsic &MI) {
|
||||
assert(!dyn_cast<ConstantInt>(Length));
|
||||
Builder.CreateCall(
|
||||
Intrinsic::getDeclaration(M, Intrinsic::instrprof_value_profile),
|
||||
{llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
|
||||
{ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
|
||||
Builder.getInt64(FuncHash), Builder.CreateZExtOrTrunc(Length, Int64Ty),
|
||||
Builder.getInt32(IPVK_MemOPSize), Builder.getInt32(CurCtrId)});
|
||||
++CurCtrId;
|
||||
@ -1257,7 +1312,6 @@ void PGOUseFunc::annotateValueSites(uint32_t Kind) {
|
||||
ValueSiteIndex++;
|
||||
}
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
// Create a COMDAT variable INSTR_PROF_RAW_VERSION_VAR to make the runtime
|
||||
// aware this is an ir_level profile so it can set the version flag.
|
||||
@ -1327,7 +1381,6 @@ bool PGOInstrumentationGenLegacyPass::runOnModule(Module &M) {
|
||||
|
||||
PreservedAnalyses PGOInstrumentationGen::run(Module &M,
|
||||
ModuleAnalysisManager &AM) {
|
||||
|
||||
auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
||||
auto LookupBPI = [&FAM](Function &F) {
|
||||
return &FAM.getResult<BranchProbabilityAnalysis>(F);
|
||||
@ -1428,12 +1481,12 @@ static bool annotateAllFunctions(
|
||||
// can affect the BranchProbabilityInfo of any callers, resulting in an
|
||||
// inconsistent MST between prof-gen and prof-use.
|
||||
for (auto &F : HotFunctions) {
|
||||
F->addFnAttr(llvm::Attribute::InlineHint);
|
||||
F->addFnAttr(Attribute::InlineHint);
|
||||
DEBUG(dbgs() << "Set inline attribute to function: " << F->getName()
|
||||
<< "\n");
|
||||
}
|
||||
for (auto &F : ColdFunctions) {
|
||||
F->addFnAttr(llvm::Attribute::Cold);
|
||||
F->addFnAttr(Attribute::Cold);
|
||||
DEBUG(dbgs() << "Set cold attribute to function: " << F->getName() << "\n");
|
||||
}
|
||||
return true;
|
||||
@ -1477,9 +1530,19 @@ bool PGOInstrumentationUseLegacyPass::runOnModule(Module &M) {
|
||||
return annotateAllFunctions(M, ProfileFileName, LookupBPI, LookupBFI);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
void setProfMetadata(Module *M, Instruction *TI, ArrayRef<uint64_t> EdgeCounts,
|
||||
uint64_t MaxCount) {
|
||||
static std::string getSimpleNodeName(const BasicBlock *Node) {
|
||||
if (!Node->getName().empty())
|
||||
return Node->getName();
|
||||
|
||||
std::string SimpleNodeName;
|
||||
raw_string_ostream OS(SimpleNodeName);
|
||||
Node->printAsOperand(OS, false);
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
void llvm::setProfMetadata(Module *M, Instruction *TI,
|
||||
ArrayRef<uint64_t> EdgeCounts,
|
||||
uint64_t MaxCount) {
|
||||
MDBuilder MDB(M->getContext());
|
||||
assert(MaxCount > 0 && "Bad max count");
|
||||
uint64_t Scale = calculateCountScale(MaxCount);
|
||||
@ -1490,7 +1553,7 @@ void setProfMetadata(Module *M, Instruction *TI, ArrayRef<uint64_t> EdgeCounts,
|
||||
DEBUG(dbgs() << "Weight is: ";
|
||||
for (const auto &W : Weights) { dbgs() << W << " "; }
|
||||
dbgs() << "\n";);
|
||||
TI->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights(Weights));
|
||||
TI->setMetadata(LLVMContext::MD_prof, MDB.createBranchWeights(Weights));
|
||||
if (EmitBranchProbability) {
|
||||
std::string BrCondStr = getBranchCondString(TI);
|
||||
if (BrCondStr.empty())
|
||||
@ -1517,36 +1580,32 @@ void setProfMetadata(Module *M, Instruction *TI, ArrayRef<uint64_t> EdgeCounts,
|
||||
}
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <> struct GraphTraits<PGOUseFunc *> {
|
||||
typedef const BasicBlock *NodeRef;
|
||||
typedef succ_const_iterator ChildIteratorType;
|
||||
typedef pointer_iterator<Function::const_iterator> nodes_iterator;
|
||||
using NodeRef = const BasicBlock *;
|
||||
using ChildIteratorType = succ_const_iterator;
|
||||
using nodes_iterator = pointer_iterator<Function::const_iterator>;
|
||||
|
||||
static NodeRef getEntryNode(const PGOUseFunc *G) {
|
||||
return &G->getFunc().front();
|
||||
}
|
||||
|
||||
static ChildIteratorType child_begin(const NodeRef N) {
|
||||
return succ_begin(N);
|
||||
}
|
||||
|
||||
static ChildIteratorType child_end(const NodeRef N) { return succ_end(N); }
|
||||
|
||||
static nodes_iterator nodes_begin(const PGOUseFunc *G) {
|
||||
return nodes_iterator(G->getFunc().begin());
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(const PGOUseFunc *G) {
|
||||
return nodes_iterator(G->getFunc().end());
|
||||
}
|
||||
};
|
||||
|
||||
static std::string getSimpleNodeName(const BasicBlock *Node) {
|
||||
if (!Node->getName().empty())
|
||||
return Node->getName();
|
||||
|
||||
std::string SimpleNodeName;
|
||||
raw_string_ostream OS(SimpleNodeName);
|
||||
Node->printAsOperand(OS, false);
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
template <> struct DOTGraphTraits<PGOUseFunc *> : DefaultDOTGraphTraits {
|
||||
explicit DOTGraphTraits(bool isSimple = false)
|
||||
: DefaultDOTGraphTraits(isSimple) {}
|
||||
@ -1586,4 +1645,5 @@ template <> struct DOTGraphTraits<PGOUseFunc *> : DefaultDOTGraphTraits {
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -13,46 +13,65 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "lower-switch"
|
||||
|
||||
namespace {
|
||||
|
||||
struct IntRange {
|
||||
int64_t Low, High;
|
||||
};
|
||||
// Return true iff R is covered by Ranges.
|
||||
static bool IsInRanges(const IntRange &R,
|
||||
const std::vector<IntRange> &Ranges) {
|
||||
// Note: Ranges must be sorted, non-overlapping and non-adjacent.
|
||||
|
||||
// Find the first range whose High field is >= R.High,
|
||||
// then check if the Low field is <= R.Low. If so, we
|
||||
// have a Range that covers R.
|
||||
auto I = std::lower_bound(
|
||||
Ranges.begin(), Ranges.end(), R,
|
||||
[](const IntRange &A, const IntRange &B) { return A.High < B.High; });
|
||||
return I != Ranges.end() && I->Low <= R.Low;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
// Return true iff R is covered by Ranges.
|
||||
static bool IsInRanges(const IntRange &R,
|
||||
const std::vector<IntRange> &Ranges) {
|
||||
// Note: Ranges must be sorted, non-overlapping and non-adjacent.
|
||||
|
||||
// Find the first range whose High field is >= R.High,
|
||||
// then check if the Low field is <= R.Low. If so, we
|
||||
// have a Range that covers R.
|
||||
auto I = std::lower_bound(
|
||||
Ranges.begin(), Ranges.end(), R,
|
||||
[](const IntRange &A, const IntRange &B) { return A.High < B.High; });
|
||||
return I != Ranges.end() && I->Low <= R.Low;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// Replace all SwitchInst instructions with chained branch instructions.
|
||||
class LowerSwitch : public FunctionPass {
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
// Pass identification, replacement for typeid
|
||||
static char ID;
|
||||
|
||||
LowerSwitch() : FunctionPass(ID) {
|
||||
initializeLowerSwitchPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
@ -68,8 +87,9 @@ namespace {
|
||||
: Low(low), High(high), BB(bb) {}
|
||||
};
|
||||
|
||||
typedef std::vector<CaseRange> CaseVector;
|
||||
typedef std::vector<CaseRange>::iterator CaseItr;
|
||||
using CaseVector = std::vector<CaseRange>;
|
||||
using CaseItr = std::vector<CaseRange>::iterator;
|
||||
|
||||
private:
|
||||
void processSwitchInst(SwitchInst *SI, SmallPtrSetImpl<BasicBlock*> &DeleteList);
|
||||
|
||||
@ -86,22 +106,24 @@ namespace {
|
||||
/// The comparison function for sorting the switch case values in the vector.
|
||||
/// WARNING: Case ranges should be disjoint!
|
||||
struct CaseCmp {
|
||||
bool operator () (const LowerSwitch::CaseRange& C1,
|
||||
const LowerSwitch::CaseRange& C2) {
|
||||
|
||||
bool operator()(const LowerSwitch::CaseRange& C1,
|
||||
const LowerSwitch::CaseRange& C2) {
|
||||
const ConstantInt* CI1 = cast<const ConstantInt>(C1.Low);
|
||||
const ConstantInt* CI2 = cast<const ConstantInt>(C2.High);
|
||||
return CI1->getValue().slt(CI2->getValue());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
char LowerSwitch::ID = 0;
|
||||
INITIALIZE_PASS(LowerSwitch, "lowerswitch",
|
||||
"Lower SwitchInst's to branches", false, false)
|
||||
|
||||
// Publicly exposed interface to pass...
|
||||
char &llvm::LowerSwitchID = LowerSwitch::ID;
|
||||
|
||||
INITIALIZE_PASS(LowerSwitch, "lowerswitch",
|
||||
"Lower SwitchInst's to branches", false, false)
|
||||
|
||||
// createLowerSwitchPass - Interface to this file...
|
||||
FunctionPass *llvm::createLowerSwitchPass() {
|
||||
return new LowerSwitch();
|
||||
@ -136,6 +158,7 @@ bool LowerSwitch::runOnFunction(Function &F) {
|
||||
static raw_ostream& operator<<(raw_ostream &O,
|
||||
const LowerSwitch::CaseVector &C)
|
||||
LLVM_ATTRIBUTE_USED;
|
||||
|
||||
static raw_ostream& operator<<(raw_ostream &O,
|
||||
const LowerSwitch::CaseVector &C) {
|
||||
O << "[";
|
||||
@ -186,7 +209,7 @@ static void fixPhis(BasicBlock *SuccBB, BasicBlock *OrigBB, BasicBlock *NewBB,
|
||||
}
|
||||
// Remove incoming values in the reverse order to prevent invalidating
|
||||
// *successive* index.
|
||||
for (unsigned III : reverse(Indices))
|
||||
for (unsigned III : llvm::reverse(Indices))
|
||||
PN->removeIncomingValue(III);
|
||||
}
|
||||
}
|
||||
@ -294,8 +317,7 @@ LowerSwitch::switchConvert(CaseItr Begin, CaseItr End, ConstantInt *LowerBound,
|
||||
/// value, so the jump to the "default" branch is warranted.
|
||||
BasicBlock* LowerSwitch::newLeafBlock(CaseRange& Leaf, Value* Val,
|
||||
BasicBlock* OrigBlock,
|
||||
BasicBlock* Default)
|
||||
{
|
||||
BasicBlock* Default) {
|
||||
Function* F = OrigBlock->getParent();
|
||||
BasicBlock* NewLeaf = BasicBlock::Create(Val->getContext(), "LeafBlock");
|
||||
F->getBasicBlockList().insert(++OrigBlock->getIterator(), NewLeaf);
|
||||
@ -442,7 +464,8 @@ void LowerSwitch::processSwitchInst(SwitchInst *SI,
|
||||
unsigned MaxPop = 0;
|
||||
BasicBlock *PopSucc = nullptr;
|
||||
|
||||
IntRange R = { INT64_MIN, INT64_MAX };
|
||||
IntRange R = {std::numeric_limits<int64_t>::min(),
|
||||
std::numeric_limits<int64_t>::max()};
|
||||
UnreachableRanges.push_back(R);
|
||||
for (const auto &I : Cases) {
|
||||
int64_t Low = I.Low->getSExtValue();
|
||||
@ -457,8 +480,8 @@ void LowerSwitch::processSwitchInst(SwitchInst *SI,
|
||||
assert(Low > LastRange.Low);
|
||||
LastRange.High = Low - 1;
|
||||
}
|
||||
if (High != INT64_MAX) {
|
||||
IntRange R = { High + 1, INT64_MAX };
|
||||
if (High != std::numeric_limits<int64_t>::max()) {
|
||||
IntRange R = { High + 1, std::numeric_limits<int64_t>::max() };
|
||||
UnreachableRanges.push_back(R);
|
||||
}
|
||||
|
||||
@ -487,8 +510,8 @@ void LowerSwitch::processSwitchInst(SwitchInst *SI,
|
||||
assert(MaxPop > 0 && PopSucc);
|
||||
Default = PopSucc;
|
||||
Cases.erase(
|
||||
remove_if(Cases,
|
||||
[PopSucc](const CaseRange &R) { return R.BB == PopSucc; }),
|
||||
llvm::remove_if(
|
||||
Cases, [PopSucc](const CaseRange &R) { return R.BB == PopSucc; }),
|
||||
Cases.end());
|
||||
|
||||
// If there are no cases left, just branch.
|
||||
|
@ -21,25 +21,38 @@
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasSetTracker.h"
|
||||
#include "llvm/ADT/TinyPtrVector.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/IteratedDominanceFrontier.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DIBuilder.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/DerivedTypes.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/IntrinsicInst.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/IR/User.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "mem2reg"
|
||||
@ -103,7 +116,7 @@ struct AllocaInfo {
|
||||
bool OnlyUsedInOneBlock;
|
||||
|
||||
Value *AllocaPointerVal;
|
||||
TinyPtrVector<DbgInfoIntrinsic*> DbgDeclares;
|
||||
TinyPtrVector<DbgInfoIntrinsic *> DbgDeclares;
|
||||
|
||||
void clear() {
|
||||
DefiningBlocks.clear();
|
||||
@ -154,10 +167,11 @@ struct AllocaInfo {
|
||||
// Data package used by RenamePass()
|
||||
class RenamePassData {
|
||||
public:
|
||||
typedef std::vector<Value *> ValVector;
|
||||
using ValVector = std::vector<Value *>;
|
||||
|
||||
RenamePassData(BasicBlock *B, BasicBlock *P, ValVector V)
|
||||
: BB(B), Pred(P), Values(std::move(V)) {}
|
||||
|
||||
BasicBlock *BB;
|
||||
BasicBlock *Pred;
|
||||
ValVector Values;
|
||||
@ -216,12 +230,15 @@ public:
|
||||
struct PromoteMem2Reg {
|
||||
/// The alloca instructions being promoted.
|
||||
std::vector<AllocaInst *> Allocas;
|
||||
|
||||
DominatorTree &DT;
|
||||
DIBuilder DIB;
|
||||
|
||||
/// A cache of @llvm.assume intrinsics used by SimplifyInstruction.
|
||||
AssumptionCache *AC;
|
||||
|
||||
const SimplifyQuery SQ;
|
||||
|
||||
/// Reverse mapping of Allocas.
|
||||
DenseMap<AllocaInst *, unsigned> AllocaLookup;
|
||||
|
||||
@ -248,7 +265,6 @@ struct PromoteMem2Reg {
|
||||
SmallVector<TinyPtrVector<DbgInfoIntrinsic *>, 8> AllocaDbgDeclares;
|
||||
|
||||
/// The set of basic blocks the renamer has already visited.
|
||||
///
|
||||
SmallPtrSet<BasicBlock *, 16> Visited;
|
||||
|
||||
/// Contains a stable numbering of basic blocks to avoid non-determinstic
|
||||
@ -291,7 +307,7 @@ private:
|
||||
bool QueuePhiNode(BasicBlock *BB, unsigned AllocaIdx, unsigned &Version);
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
} // end anonymous namespace
|
||||
|
||||
/// Given a LoadInst LI this adds assume(LI != null) after it.
|
||||
static void addAssumeNonNull(AssumptionCache *AC, LoadInst *LI) {
|
||||
@ -373,7 +389,6 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
|
||||
Info.UsingBlocks.push_back(StoreBB);
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if (LI->getParent() != StoreBB &&
|
||||
!DT.dominates(StoreBB, LI->getParent())) {
|
||||
// If the load and store are in different blocks, use BB dominance to
|
||||
@ -395,7 +410,7 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
|
||||
// that information when we erase this Load. So we preserve
|
||||
// it with an assume.
|
||||
if (AC && LI->getMetadata(LLVMContext::MD_nonnull) &&
|
||||
!llvm::isKnownNonZero(ReplVal, DL, 0, AC, LI, &DT))
|
||||
!isKnownNonZero(ReplVal, DL, 0, AC, LI, &DT))
|
||||
addAssumeNonNull(AC, LI);
|
||||
|
||||
LI->replaceAllUsesWith(ReplVal);
|
||||
@ -451,7 +466,7 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
|
||||
// make it efficient to get the index of various operations in the block.
|
||||
|
||||
// Walk the use-def list of the alloca, getting the locations of all stores.
|
||||
typedef SmallVector<std::pair<unsigned, StoreInst *>, 64> StoresByIndexTy;
|
||||
using StoresByIndexTy = SmallVector<std::pair<unsigned, StoreInst *>, 64>;
|
||||
StoresByIndexTy StoresByIndex;
|
||||
|
||||
for (User *U : AI->users())
|
||||
@ -491,7 +506,7 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
|
||||
// information when we erase it. So we preserve it with an assume.
|
||||
Value *ReplVal = std::prev(I)->second->getOperand(0);
|
||||
if (AC && LI->getMetadata(LLVMContext::MD_nonnull) &&
|
||||
!llvm::isKnownNonZero(ReplVal, DL, 0, AC, LI, &DT))
|
||||
!isKnownNonZero(ReplVal, DL, 0, AC, LI, &DT))
|
||||
addAssumeNonNull(AC, LI);
|
||||
|
||||
LI->replaceAllUsesWith(ReplVal);
|
||||
@ -598,7 +613,6 @@ void PromoteMem2Reg::run() {
|
||||
// nodes and see if we can optimize out some work by avoiding insertion of
|
||||
// dead phi nodes.
|
||||
|
||||
|
||||
// Unique the set of defining blocks for efficient lookup.
|
||||
SmallPtrSet<BasicBlock *, 32> DefBlocks;
|
||||
DefBlocks.insert(Info.DefiningBlocks.begin(), Info.DefiningBlocks.end());
|
||||
@ -635,14 +649,12 @@ void PromoteMem2Reg::run() {
|
||||
// Set the incoming values for the basic block to be null values for all of
|
||||
// the alloca's. We do this in case there is a load of a value that has not
|
||||
// been stored yet. In this case, it will get this null value.
|
||||
//
|
||||
RenamePassData::ValVector Values(Allocas.size());
|
||||
for (unsigned i = 0, e = Allocas.size(); i != e; ++i)
|
||||
Values[i] = UndefValue::get(Allocas[i]->getAllocatedType());
|
||||
|
||||
// Walks all basic blocks in the function performing the SSA rename algorithm
|
||||
// and inserting the phi nodes we marked as necessary
|
||||
//
|
||||
std::vector<RenamePassData> RenamePassWorkList;
|
||||
RenamePassWorkList.emplace_back(&F.front(), nullptr, std::move(Values));
|
||||
do {
|
||||
@ -705,7 +717,6 @@ void PromoteMem2Reg::run() {
|
||||
// hasn't traversed. If this is the case, the PHI nodes may not
|
||||
// have incoming values for all predecessors. Loop over all PHI nodes we have
|
||||
// created, inserting undef values if they are missing any incoming values.
|
||||
//
|
||||
for (DenseMap<std::pair<unsigned, unsigned>, PHINode *>::iterator
|
||||
I = NewPhiNodes.begin(),
|
||||
E = NewPhiNodes.end();
|
||||
@ -770,7 +781,6 @@ void PromoteMem2Reg::ComputeLiveInBlocks(
|
||||
AllocaInst *AI, AllocaInfo &Info,
|
||||
const SmallPtrSetImpl<BasicBlock *> &DefBlocks,
|
||||
SmallPtrSetImpl<BasicBlock *> &LiveInBlocks) {
|
||||
|
||||
// To determine liveness, we must iterate through the predecessors of blocks
|
||||
// where the def is live. Blocks are added to the worklist if we need to
|
||||
// check their predecessors. Start with all the using blocks.
|
||||
@ -932,7 +942,7 @@ NextIteration:
|
||||
// that information when we erase this Load. So we preserve
|
||||
// it with an assume.
|
||||
if (AC && LI->getMetadata(LLVMContext::MD_nonnull) &&
|
||||
!llvm::isKnownNonZero(V, SQ.DL, 0, AC, LI, &DT))
|
||||
!isKnownNonZero(V, SQ.DL, 0, AC, LI, &DT))
|
||||
addAssumeNonNull(AC, LI);
|
||||
|
||||
// Anything using the load now uses the current value.
|
||||
|
Loading…
Reference in New Issue
Block a user