diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 60 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/Passes/PassBuilder.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Passes/PassRegistry.def | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/CGProfile.cpp | 100 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/CMakeLists.txt | 1 |
6 files changed, 181 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index dc29397a343..b726b21f6b9 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -91,6 +91,12 @@ static void GetObjCImageInfo(Module &M, unsigned &Version, unsigned &Flags, // ELF //===----------------------------------------------------------------------===// +void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, + const TargetMachine &TgtM) { + TargetLoweringObjectFile::Initialize(Ctx, TgtM); + TM = &TgtM; +} + void TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer, Module &M) const { auto &C = getContext(); @@ -116,15 +122,55 @@ void TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer, StringRef Section; GetObjCImageInfo(M, Version, Flags, Section); - if (Section.empty()) + if (!Section.empty()) { + auto *S = C.getELFSection(Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC); + Streamer.SwitchSection(S); + Streamer.EmitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO"))); + Streamer.EmitIntValue(Version, 4); + Streamer.EmitIntValue(Flags, 4); + Streamer.AddBlankLine(); + } + + SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags; + M.getModuleFlagsMetadata(ModuleFlags); + + MDNode *CFGProfile = nullptr; + + for (const auto &MFE : ModuleFlags) { + StringRef Key = MFE.Key->getString(); + if (Key == "CG Profile") { + CFGProfile = cast<MDNode>(MFE.Val); + break; + } + } + + if (!CFGProfile) return; - auto *S = C.getELFSection(Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC); - Streamer.SwitchSection(S); - Streamer.EmitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO"))); - Streamer.EmitIntValue(Version, 4); - Streamer.EmitIntValue(Flags, 4); - Streamer.AddBlankLine(); + auto GetSym = [this](const MDOperand &MDO) -> MCSymbol * { + if (!MDO) + return nullptr; + auto V = cast<ValueAsMetadata>(MDO); + const Function *F = cast<Function>(V->getValue()); + return TM->getSymbol(F); + }; + + for (const auto &Edge : CFGProfile->operands()) { + MDNode *E = cast<MDNode>(Edge); + const MCSymbol *From = GetSym(E->getOperand(0)); + const MCSymbol *To = GetSym(E->getOperand(1)); + // Skip null functions. This can happen if functions are dead stripped after + // the CGProfile pass has been run. + if (!From || !To) + continue; + uint64_t Count = cast<ConstantAsMetadata>(E->getOperand(2)) + ->getValue() + ->getUniqueInteger() + .getZExtValue(); + Streamer.emitCGProfileEntry( + MCSymbolRefExpr::create(From, MCSymbolRefExpr::VK_None, C), + MCSymbolRefExpr::create(To, MCSymbolRefExpr::VK_None, C), Count); + } } MCSymbol *TargetLoweringObjectFileELF::getCFIPersonalitySymbol( diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 07ba329b864..e5231bb78a3 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -409,6 +409,7 @@ private: void visitModuleFlag(const MDNode *Op, DenseMap<const MDString *, const MDNode *> &SeenIDs, SmallVectorImpl<const MDNode *> &Requirements); + void visitModuleFlagCGProfileEntry(const MDOperand &MDO); void visitFunction(const Function &F); void visitBasicBlock(BasicBlock &BB); void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty); @@ -1411,6 +1412,28 @@ Verifier::visitModuleFlag(const MDNode *Op, Assert(M.getNamedMetadata("llvm.linker.options"), "'Linker Options' named metadata no longer supported"); } + + if (ID->getString() == "CG Profile") { + for (const MDOperand &MDO : cast<MDNode>(Op->getOperand(2))->operands()) + visitModuleFlagCGProfileEntry(MDO); + } +} + +void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) { + auto CheckFunction = [&](const MDOperand &FuncMDO) { + if (!FuncMDO) + return; + auto F = dyn_cast<ValueAsMetadata>(FuncMDO); + Assert(F && isa<Function>(F->getValue()), "expected a Function or null", + FuncMDO); + }; + auto Node = dyn_cast_or_null<MDNode>(MDO); + Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO); + CheckFunction(Node->getOperand(0)); + CheckFunction(Node->getOperand(1)); + auto Count = dyn_cast_or_null<ConstantAsMetadata>(Node->getOperand(2)); + Assert(Count && Count->getType()->isIntegerTy(), + "expected an integer constant", Node->getOperand(2)); } /// Return true if this attribute kind only applies to functions. diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 30d203426a6..d4d66e06a02 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -61,6 +61,7 @@ #include "llvm/Support/Regex.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" +#include "llvm/Transforms/Instrumentation/CGProfile.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/ArgumentPromotion.h" #include "llvm/Transforms/IPO/CalledValuePropagation.h" @@ -843,6 +844,8 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, // Add the core optimizing pipeline. MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM))); + MPM.addPass(CGProfilePass()); + // Now we need to do some global optimization transforms. // FIXME: It would seem like these should come first in the optimization // pipeline and maybe be the bottom of the canonicalization pipeline? Weird diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 0dcdbd70053..367f8ee3fb0 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -40,6 +40,7 @@ MODULE_ALIAS_ANALYSIS("globals-aa", GlobalsAA()) #endif MODULE_PASS("always-inline", AlwaysInlinerPass()) MODULE_PASS("called-value-propagation", CalledValuePropagationPass()) +MODULE_PASS("cg-profile", CGProfilePass()) MODULE_PASS("constmerge", ConstantMergePass()) MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass()) MODULE_PASS("deadargelim", DeadArgumentEliminationPass()) diff --git a/llvm/lib/Transforms/Instrumentation/CGProfile.cpp b/llvm/lib/Transforms/Instrumentation/CGProfile.cpp new file mode 100644 index 00000000000..9606b3da247 --- /dev/null +++ b/llvm/lib/Transforms/Instrumentation/CGProfile.cpp @@ -0,0 +1,100 @@ +//===-- CGProfile.cpp -----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Instrumentation/CGProfile.h" + +#include "llvm/ADT/MapVector.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/PassManager.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Transforms/Instrumentation.h" + +#include <array> + +using namespace llvm; + +PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) { + MapVector<std::pair<Function *, Function *>, uint64_t> Counts; + FunctionAnalysisManager &FAM = + MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + InstrProfSymtab Symtab; + auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F, + Function *CalledF, uint64_t NewCount) { + if (!CalledF || !TTI.isLoweredToCall(CalledF)) + return; + uint64_t &Count = Counts[std::make_pair(F, CalledF)]; + Count = SaturatingAdd(Count, NewCount); + }; + // Ignore error here. Indirect calls are ignored if this fails. + (void)(bool)Symtab.create(M); + for (auto &F : M) { + if (F.isDeclaration()) + continue; + auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F); + if (BFI.getEntryFreq() == 0) + continue; + TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F); + for (auto &BB : F) { + Optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB); + if (!BBCount) + continue; + for (auto &I : BB) { + CallSite CS(&I); + if (!CS) + continue; + if (CS.isIndirectCall()) { + InstrProfValueData ValueData[8]; + uint32_t ActualNumValueData; + uint64_t TotalC; + if (!getValueProfDataFromInst(*CS.getInstruction(), + IPVK_IndirectCallTarget, 8, ValueData, + ActualNumValueData, TotalC)) + continue; + for (const auto &VD : + ArrayRef<InstrProfValueData>(ValueData, ActualNumValueData)) { + UpdateCounts(TTI, &F, Symtab.getFunction(VD.Value), VD.Count); + } + continue; + } + UpdateCounts(TTI, &F, CS.getCalledFunction(), *BBCount); + } + } + } + + addModuleFlags(M, Counts); + + return PreservedAnalyses::all(); +} + +void CGProfilePass::addModuleFlags( + Module &M, + MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const { + if (Counts.empty()) + return; + + LLVMContext &Context = M.getContext(); + MDBuilder MDB(Context); + std::vector<Metadata *> Nodes; + + for (auto E : Counts) { + SmallVector<Metadata *, 3> Vals; + Vals.push_back(ValueAsMetadata::get(E.first.first)); + Vals.push_back(ValueAsMetadata::get(E.first.second)); + Vals.push_back(MDB.createConstant( + ConstantInt::get(Type::getInt64Ty(Context), E.second))); + Nodes.push_back(MDNode::get(Context, Vals)); + } + + M.addModuleFlag(Module::Append, "CG Profile", MDNode::get(Context, Nodes)); +} diff --git a/llvm/lib/Transforms/Instrumentation/CMakeLists.txt b/llvm/lib/Transforms/Instrumentation/CMakeLists.txt index 66fdcb3ccc4..5d008482319 100644 --- a/llvm/lib/Transforms/Instrumentation/CMakeLists.txt +++ b/llvm/lib/Transforms/Instrumentation/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_library(LLVMInstrumentation AddressSanitizer.cpp BoundsChecking.cpp + CGProfile.cpp DataFlowSanitizer.cpp GCOVProfiling.cpp MemorySanitizer.cpp |