Index: lib/Transforms/IPO/WholeProgramDevirt.cpp =================================================================== --- lib/Transforms/IPO/WholeProgramDevirt.cpp +++ lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -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,34 @@ // 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 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(); + + std::unique_ptr OwnedORE; + OptimizationRemarkEmitter *ORE; + if (OREGetter) + ORE = &OREGetter(F); + else { + OwnedORE = make_unique(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 OREGetter, + Value *New) { if (RemarksEnabled) - emitRemark(OptName, TargetName); + emitRemark(OptName, TargetName, OREGetter); CS->replaceAllUsesWith(New); if (auto II = dyn_cast(CS.getInstruction())) { BranchInst::Create(II->getNormalDest(), CS.getInstruction()); @@ -383,6 +399,7 @@ IntegerType *IntPtrTy; bool RemarksEnabled; + function_ref OREGetter; MapVector CallSlots; @@ -397,6 +414,7 @@ std::map NumUnsafeUsesForTypeTest; DevirtModule(Module &M, function_ref AARGetter, + function_ref OREGetter, ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary) : M(M), AARGetter(AARGetter), ExportSummary(ExportSummary), @@ -405,7 +423,7 @@ 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 +500,9 @@ // Lower the module using the action and summary passed as command line // arguments. For testing purposes only. - static bool runForTesting(Module &M, - function_ref AARGetter); + static bool runForTesting( + Module &M, function_ref AARGetter, + function_ref OREGetter); }; struct WholeProgramDevirt : public ModulePass { @@ -508,9 +527,14 @@ bool runOnModule(Module &M) override { if (skipModule(M)) return false; + + auto OREGetter = function_ref(); + 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 +566,17 @@ auto AARGetter = [&](Function &F) -> AAResults & { return FAM.getResult(F); }; - if (!DevirtModule(M, AARGetter, nullptr, nullptr).run()) + auto OREGetter = [&](Function *F) -> OptimizationRemarkEmitter & { + return FAM.getResult(*F); + }; + if (!DevirtModule(M, AARGetter, OREGetter, nullptr, nullptr).run()) return PreservedAnalyses::all(); return PreservedAnalyses::none(); } bool DevirtModule::runForTesting( - Module &M, function_ref AARGetter) { + Module &M, function_ref AARGetter, + function_ref OREGetter) { ModuleSummaryIndex Summary; // Handle the command-line summary arguments. This code is for testing @@ -566,7 +594,7 @@ bool Changed = DevirtModule( - M, AARGetter, + M, AARGetter, OREGetter, ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr, ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr) .run(); @@ -684,7 +712,7 @@ 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 +797,7 @@ uint64_t TheRetVal) { for (auto Call : CSInfo.CallSites) Call.replaceAndErase( - "uniform-ret-val", FnName, RemarksEnabled, + "uniform-ret-val", FnName, RemarksEnabled, OREGetter, ConstantInt::get(cast(Call.CS.getType()), TheRetVal)); CSInfo.markDevirt(); } @@ -846,7 +874,8 @@ 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 +944,12 @@ 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 +1436,20 @@ // 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()); + // DISubprogram *SP = F->getSubprogram(); + + std::unique_ptr OwnedORE; + OptimizationRemarkEmitter *ORE; + if (OREGetter) + ORE = &OREGetter(F); + else { + OwnedORE = make_unique(F); + ORE = OwnedORE.get(); + } + + using namespace ore; + ORE->emit(OptimizationRemark(DEBUG_TYPE, "Devirtualized", F) + << "devirtualized " << NV("FunctionName", F->getName())); } }