forked from OSchip/llvm-project
Migrate WholeProgramDevirt to new Optimization Remark API
Summary: This is an attempt to move WholeProgramDevirt to the new remark API. https://bugs.llvm.org/show_bug.cgi?id=33793 Reviewers: anemet Reviewed By: anemet Subscribers: fhahn, llvm-commits Differential Revision: https://reviews.llvm.org/D36943 llvm-svn: 311352
This commit is contained in:
parent
5a2530da05
commit
e963c89d11
|
@ -51,6 +51,7 @@
|
|||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
|
||||
#include "llvm/Analysis/TypeMetadataUtils.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
|
@ -58,7 +59,6 @@
|
|||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/IR/DebugLoc.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/DiagnosticInfo.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/GlobalAlias.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
|
@ -275,18 +275,39 @@ struct VirtualCallSite {
|
|||
// of that field for details.
|
||||
unsigned *NumUnsafeUses;
|
||||
|
||||
void emitRemark(const Twine &OptName, const Twine &TargetName) {
|
||||
void
|
||||
emitRemark(const StringRef OptName, const StringRef TargetName,
|
||||
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter) {
|
||||
Function *F = CS.getCaller();
|
||||
emitOptimizationRemark(
|
||||
F->getContext(), DEBUG_TYPE, *F,
|
||||
CS.getInstruction()->getDebugLoc(),
|
||||
OptName + ": devirtualized a call to " + TargetName);
|
||||
DebugLoc DLoc = CS->getDebugLoc();
|
||||
BasicBlock *Block = CS.getParent();
|
||||
|
||||
// In the new pass manager, we can request the optimization
|
||||
// remark emitter pass on a per-function-basis, which the
|
||||
// OREGetter will do for us.
|
||||
// In the old pass manager, this is harder, so we just build
|
||||
// a optimization remark emitter on the fly, when we need it.
|
||||
std::unique_ptr<OptimizationRemarkEmitter> OwnedORE;
|
||||
OptimizationRemarkEmitter *ORE;
|
||||
if (OREGetter)
|
||||
ORE = &OREGetter(F);
|
||||
else {
|
||||
OwnedORE = make_unique<OptimizationRemarkEmitter>(F);
|
||||
ORE = OwnedORE.get();
|
||||
}
|
||||
|
||||
using namespace ore;
|
||||
ORE->emit(OptimizationRemark(DEBUG_TYPE, OptName, DLoc, Block)
|
||||
<< NV("Optimization", OptName) << ": devirtualized a call to "
|
||||
<< NV("FunctionName", TargetName));
|
||||
}
|
||||
|
||||
void replaceAndErase(const Twine &OptName, const Twine &TargetName,
|
||||
bool RemarksEnabled, Value *New) {
|
||||
void replaceAndErase(
|
||||
const StringRef OptName, const StringRef TargetName, bool RemarksEnabled,
|
||||
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter,
|
||||
Value *New) {
|
||||
if (RemarksEnabled)
|
||||
emitRemark(OptName, TargetName);
|
||||
emitRemark(OptName, TargetName, OREGetter);
|
||||
CS->replaceAllUsesWith(New);
|
||||
if (auto II = dyn_cast<InvokeInst>(CS.getInstruction())) {
|
||||
BranchInst::Create(II->getNormalDest(), CS.getInstruction());
|
||||
|
@ -383,6 +404,7 @@ struct DevirtModule {
|
|||
IntegerType *IntPtrTy;
|
||||
|
||||
bool RemarksEnabled;
|
||||
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter;
|
||||
|
||||
MapVector<VTableSlot, VTableSlotInfo> CallSlots;
|
||||
|
||||
|
@ -397,6 +419,7 @@ struct DevirtModule {
|
|||
std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
|
||||
|
||||
DevirtModule(Module &M, function_ref<AAResults &(Function &)> AARGetter,
|
||||
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter,
|
||||
ModuleSummaryIndex *ExportSummary,
|
||||
const ModuleSummaryIndex *ImportSummary)
|
||||
: M(M), AARGetter(AARGetter), ExportSummary(ExportSummary),
|
||||
|
@ -405,7 +428,7 @@ struct DevirtModule {
|
|||
Int32Ty(Type::getInt32Ty(M.getContext())),
|
||||
Int64Ty(Type::getInt64Ty(M.getContext())),
|
||||
IntPtrTy(M.getDataLayout().getIntPtrType(M.getContext(), 0)),
|
||||
RemarksEnabled(areRemarksEnabled()) {
|
||||
RemarksEnabled(areRemarksEnabled()), OREGetter(OREGetter) {
|
||||
assert(!(ExportSummary && ImportSummary));
|
||||
}
|
||||
|
||||
|
@ -482,8 +505,9 @@ struct DevirtModule {
|
|||
|
||||
// Lower the module using the action and summary passed as command line
|
||||
// arguments. For testing purposes only.
|
||||
static bool runForTesting(Module &M,
|
||||
function_ref<AAResults &(Function &)> AARGetter);
|
||||
static bool runForTesting(
|
||||
Module &M, function_ref<AAResults &(Function &)> AARGetter,
|
||||
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter);
|
||||
};
|
||||
|
||||
struct WholeProgramDevirt : public ModulePass {
|
||||
|
@ -508,9 +532,14 @@ struct WholeProgramDevirt : public ModulePass {
|
|||
bool runOnModule(Module &M) override {
|
||||
if (skipModule(M))
|
||||
return false;
|
||||
|
||||
auto OREGetter = function_ref<OptimizationRemarkEmitter &(Function *)>();
|
||||
|
||||
if (UseCommandLine)
|
||||
return DevirtModule::runForTesting(M, LegacyAARGetter(*this));
|
||||
return DevirtModule(M, LegacyAARGetter(*this), ExportSummary, ImportSummary)
|
||||
return DevirtModule::runForTesting(M, LegacyAARGetter(*this), OREGetter);
|
||||
|
||||
return DevirtModule(M, LegacyAARGetter(*this), OREGetter, ExportSummary,
|
||||
ImportSummary)
|
||||
.run();
|
||||
}
|
||||
|
||||
|
@ -542,13 +571,17 @@ PreservedAnalyses WholeProgramDevirtPass::run(Module &M,
|
|||
auto AARGetter = [&](Function &F) -> AAResults & {
|
||||
return FAM.getResult<AAManager>(F);
|
||||
};
|
||||
if (!DevirtModule(M, AARGetter, nullptr, nullptr).run())
|
||||
auto OREGetter = [&](Function *F) -> OptimizationRemarkEmitter & {
|
||||
return FAM.getResult<OptimizationRemarkEmitterAnalysis>(*F);
|
||||
};
|
||||
if (!DevirtModule(M, AARGetter, OREGetter, nullptr, nullptr).run())
|
||||
return PreservedAnalyses::all();
|
||||
return PreservedAnalyses::none();
|
||||
}
|
||||
|
||||
bool DevirtModule::runForTesting(
|
||||
Module &M, function_ref<AAResults &(Function &)> AARGetter) {
|
||||
Module &M, function_ref<AAResults &(Function &)> AARGetter,
|
||||
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter) {
|
||||
ModuleSummaryIndex Summary;
|
||||
|
||||
// Handle the command-line summary arguments. This code is for testing
|
||||
|
@ -566,7 +599,7 @@ bool DevirtModule::runForTesting(
|
|||
|
||||
bool Changed =
|
||||
DevirtModule(
|
||||
M, AARGetter,
|
||||
M, AARGetter, OREGetter,
|
||||
ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr,
|
||||
ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr)
|
||||
.run();
|
||||
|
@ -684,7 +717,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
|
|||
auto Apply = [&](CallSiteInfo &CSInfo) {
|
||||
for (auto &&VCallSite : CSInfo.CallSites) {
|
||||
if (RemarksEnabled)
|
||||
VCallSite.emitRemark("single-impl", TheFn->getName());
|
||||
VCallSite.emitRemark("single-impl", TheFn->getName(), OREGetter);
|
||||
VCallSite.CS.setCalledFunction(ConstantExpr::getBitCast(
|
||||
TheFn, VCallSite.CS.getCalledValue()->getType()));
|
||||
// This use is no longer unsafe.
|
||||
|
@ -769,7 +802,7 @@ void DevirtModule::applyUniformRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
|
|||
uint64_t TheRetVal) {
|
||||
for (auto Call : CSInfo.CallSites)
|
||||
Call.replaceAndErase(
|
||||
"uniform-ret-val", FnName, RemarksEnabled,
|
||||
"uniform-ret-val", FnName, RemarksEnabled, OREGetter,
|
||||
ConstantInt::get(cast<IntegerType>(Call.CS.getType()), TheRetVal));
|
||||
CSInfo.markDevirt();
|
||||
}
|
||||
|
@ -846,7 +879,8 @@ void DevirtModule::applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
|
|||
Value *Cmp = B.CreateICmp(IsOne ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE,
|
||||
Call.VTable, UniqueMemberAddr);
|
||||
Cmp = B.CreateZExt(Cmp, Call.CS->getType());
|
||||
Call.replaceAndErase("unique-ret-val", FnName, RemarksEnabled, Cmp);
|
||||
Call.replaceAndErase("unique-ret-val", FnName, RemarksEnabled, OREGetter,
|
||||
Cmp);
|
||||
}
|
||||
CSInfo.markDevirt();
|
||||
}
|
||||
|
@ -915,11 +949,12 @@ void DevirtModule::applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName,
|
|||
Value *BitsAndBit = B.CreateAnd(Bits, Bit);
|
||||
auto IsBitSet = B.CreateICmpNE(BitsAndBit, ConstantInt::get(Int8Ty, 0));
|
||||
Call.replaceAndErase("virtual-const-prop-1-bit", FnName, RemarksEnabled,
|
||||
IsBitSet);
|
||||
OREGetter, IsBitSet);
|
||||
} else {
|
||||
Value *ValAddr = B.CreateBitCast(Addr, RetType->getPointerTo());
|
||||
Value *Val = B.CreateLoad(RetType, ValAddr);
|
||||
Call.replaceAndErase("virtual-const-prop", FnName, RemarksEnabled, Val);
|
||||
Call.replaceAndErase("virtual-const-prop", FnName, RemarksEnabled,
|
||||
OREGetter, Val);
|
||||
}
|
||||
}
|
||||
CSInfo.markDevirt();
|
||||
|
@ -1406,9 +1441,24 @@ bool DevirtModule::run() {
|
|||
// Generate remarks for each devirtualized function.
|
||||
for (const auto &DT : DevirtTargets) {
|
||||
Function *F = DT.second;
|
||||
DISubprogram *SP = F->getSubprogram();
|
||||
emitOptimizationRemark(F->getContext(), DEBUG_TYPE, *F, SP,
|
||||
Twine("devirtualized ") + F->getName());
|
||||
|
||||
// In the new pass manager, we can request the optimization
|
||||
// remark emitter pass on a per-function-basis, which the
|
||||
// OREGetter will do for us.
|
||||
// In the old pass manager, this is harder, so we just build
|
||||
// a optimization remark emitter on the fly, when we need it.
|
||||
std::unique_ptr<OptimizationRemarkEmitter> OwnedORE;
|
||||
OptimizationRemarkEmitter *ORE;
|
||||
if (OREGetter)
|
||||
ORE = &OREGetter(F);
|
||||
else {
|
||||
OwnedORE = make_unique<OptimizationRemarkEmitter>(F);
|
||||
ORE = OwnedORE.get();
|
||||
}
|
||||
|
||||
using namespace ore;
|
||||
ORE->emit(OptimizationRemark(DEBUG_TYPE, "Devirtualized", F)
|
||||
<< "devirtualized " << NV("FunctionName", F->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue