summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp54
-rw-r--r--llvm/lib/IR/Verifier.cpp20
-rw-r--r--llvm/lib/Transforms/IPO/PassManagerBuilder.cpp2
-rw-r--r--llvm/lib/Transforms/Instrumentation/CGProfile.cpp110
-rw-r--r--llvm/lib/Transforms/Instrumentation/CMakeLists.txt1
-rw-r--r--llvm/lib/Transforms/Instrumentation/Instrumentation.cpp1
6 files changed, 181 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index df8aecd7cf4..24ff42a34ff 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,49 @@ 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) {
+ 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));
+ 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 dca9d9b64ff..11af71142ef 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,25 @@ 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 Node = dyn_cast_or_null<MDNode>(MDO);
+ Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO);
+ auto From = dyn_cast_or_null<ValueAsMetadata>(Node->getOperand(0));
+ Assert(From && isa<Function>(From->getValue()), "expected a Function",
+ Node->getOperand(0));
+ auto To = dyn_cast_or_null<ValueAsMetadata>(Node->getOperand(1));
+ Assert(To && isa<Function>(To->getValue()), "expected a Function",
+ 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/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
index a2559bc70b1..defb54e19bf 100644
--- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
+++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
@@ -694,6 +694,8 @@ void PassManagerBuilder::populateModulePassManager(
MPM.add(createConstantMergePass()); // Merge dup global constants
}
+ MPM.add(createCGProfilePass());
+
if (MergeFunctions)
MPM.add(createMergeFunctionsPass());
diff --git a/llvm/lib/Transforms/Instrumentation/CGProfile.cpp b/llvm/lib/Transforms/Instrumentation/CGProfile.cpp
new file mode 100644
index 00000000000..cb1fcb21425
--- /dev/null
+++ b/llvm/lib/Transforms/Instrumentation/CGProfile.cpp
@@ -0,0 +1,110 @@
+//===-- 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/ADT/MapVector.h"
+#include "llvm/Analysis/BlockFrequencyInfo.h"
+#include "llvm/Analysis/BranchProbabilityInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Instrumentation.h"
+
+#include <array>
+
+using namespace llvm;
+
+class CGProfilePass : public ModulePass {
+public:
+ static char ID;
+
+ CGProfilePass() : ModulePass(ID) {
+ initializeCGProfilePassPass(*PassRegistry::getPassRegistry());
+ }
+
+ StringRef getPassName() const override { return "CGProfilePass"; }
+
+private:
+ bool runOnModule(Module &M) override;
+ bool addModuleFlags(
+ Module &M,
+ MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<BlockFrequencyInfoWrapperPass>();
+ AU.addRequired<BranchProbabilityInfoWrapperPass>();
+ }
+};
+
+bool CGProfilePass::runOnModule(Module &M) {
+ if (skipModule(M))
+ return false;
+
+ MapVector<std::pair<Function *, Function *>, uint64_t> Counts;
+
+ for (auto &F : M) {
+ if (F.isDeclaration())
+ continue;
+ getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
+ auto &BFI = getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
+ for (const auto &BB : F) {
+ Optional<uint64_t> BBCount = BFI.getBlockProfileCount(&BB);
+ if (!BBCount)
+ continue;
+ for (const auto &I : BB) {
+ auto *CI = dyn_cast<CallInst>(&I);
+ if (!CI)
+ continue;
+ Function *CalledF = CI->getCalledFunction();
+ if (!CalledF || CalledF->isIntrinsic())
+ continue;
+
+ uint64_t &Count = Counts[std::make_pair(&F, CalledF)];
+ Count = SaturatingAdd(Count, *BBCount);
+ }
+ }
+ }
+
+ return addModuleFlags(M, Counts);
+}
+
+bool CGProfilePass::addModuleFlags(
+ Module &M,
+ MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const {
+ if (Counts.empty())
+ return false;
+
+ 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));
+ return true;
+}
+
+char CGProfilePass::ID = 0;
+INITIALIZE_PASS_BEGIN(CGProfilePass, "cg-profile",
+ "Generate profile information from the call graph.",
+ false, false)
+INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)
+INITIALIZE_PASS_END(CGProfilePass, "cg-profile",
+ "Generate profile information from the call graph.", false,
+ false)
+
+ModulePass *llvm::createCGProfilePass() { return new CGProfilePass(); }
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
diff --git a/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp b/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp
index 8e9eea96ced..fbd651f3f20 100644
--- a/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp
+++ b/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp
@@ -60,6 +60,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) {
initializeAddressSanitizerModulePass(Registry);
initializeBoundsCheckingLegacyPassPass(Registry);
initializeGCOVProfilerLegacyPassPass(Registry);
+ initializeCGProfilePassPass(Registry);
initializePGOInstrumentationGenLegacyPassPass(Registry);
initializePGOInstrumentationUseLegacyPassPass(Registry);
initializePGOIndirectCallPromotionLegacyPassPass(Registry);
OpenPOWER on IntegriCloud