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:
Sam Elliott 2017-08-21 16:57:21 +00:00
parent 5a2530da05
commit e963c89d11
1 changed files with 75 additions and 25 deletions

View File

@ -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()));
}
}