llvm.org GIT mirror llvm / 71b21d8
Add support for generating a call graph profile from Branch Frequency Info. === Generating the CG Profile === The CGProfile module pass simply gets the block profile count for each BB and scans for call instructions. For each call instruction it adds an edge from the current function to the called function with the current BB block profile count as the weight. After scanning all the functions, it generates an appending module flag containing the data. The format looks like: ``` !llvm.module.flags = !{!0} !0 = !{i32 5, !"CG Profile", !1} !1 = !{!2, !3, !4} ; List of edges !2 = !{void ()* @a, void ()* @b, i64 32} ; Edge from a to b with a weight of 32 !3 = !{void (i1)* @freq, void ()* @a, i64 11} !4 = !{void (i1)* @freq, void ()* @b, i64 20} ``` Differential Revision: https://reviews.llvm.org/D48105 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335794 91177308-0d34-0410-b5e6-96231b3b80d8 Michael J. Spencer 1 year, 2 months ago
13 changed file(s) with 329 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
3535 protected:
3636 MCSymbolRefExpr::VariantKind PLTRelativeVariantKind =
3737 MCSymbolRefExpr::VK_None;
38 const TargetMachine *TM;
3839
3940 public:
4041 TargetLoweringObjectFileELF() = default;
4142 ~TargetLoweringObjectFileELF() override = default;
43
44 void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
4245
4346 /// Emit Obj-C garbage collection and linker options.
4447 void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
0 //===- Transforms/Instrumentation/CGProfile.h -------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file provides the interface for LLVM's Call Graph Profile pass.
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_TRANSFORMS_CGPROFILE_H
13 #define LLVM_TRANSFORMS_CGPROFILE_H
14
15 #include "llvm/ADT/MapVector.h"
16 #include "llvm/IR/PassManager.h"
17
18 namespace llvm {
19 class CGProfilePass : public PassInfoMixin {
20 public:
21 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
22
23 private:
24 void addModuleFlags(
25 Module &M,
26 MapVector, uint64_t> &Counts) const;
27 };
28 } // end namespace llvm
29
30 #endif // LLVM_TRANSFORMS_CGPROFILE_H
9090 // ELF
9191 //===----------------------------------------------------------------------===//
9292
93 void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
94 const TargetMachine &TgtM) {
95 TargetLoweringObjectFile::Initialize(Ctx, TgtM);
96 TM = &TgtM;
97 }
98
9399 void TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer,
94100 Module &M) const {
95101 auto &C = getContext();
115121 StringRef Section;
116122
117123 GetObjCImageInfo(M, Version, Flags, Section);
118 if (Section.empty())
124 if (!Section.empty()) {
125 auto *S = C.getELFSection(Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
126 Streamer.SwitchSection(S);
127 Streamer.EmitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO")));
128 Streamer.EmitIntValue(Version, 4);
129 Streamer.EmitIntValue(Flags, 4);
130 Streamer.AddBlankLine();
131 }
132
133 SmallVector ModuleFlags;
134 M.getModuleFlagsMetadata(ModuleFlags);
135
136 MDNode *CFGProfile = nullptr;
137
138 for (const auto &MFE : ModuleFlags) {
139 StringRef Key = MFE.Key->getString();
140 if (Key == "CG Profile") {
141 CFGProfile = cast(MFE.Val);
142 break;
143 }
144 }
145
146 if (!CFGProfile)
119147 return;
120148
121 auto *S = C.getELFSection(Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
122 Streamer.SwitchSection(S);
123 Streamer.EmitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO")));
124 Streamer.EmitIntValue(Version, 4);
125 Streamer.EmitIntValue(Flags, 4);
126 Streamer.AddBlankLine();
149 auto GetSym = [this](const MDOperand &MDO) {
150 auto V = cast(MDO);
151 const Function *F = cast(V->getValue());
152 return TM->getSymbol(F);
153 };
154
155 for (const auto &Edge : CFGProfile->operands()) {
156 MDNode *E = cast(Edge);
157 const MCSymbol *From = GetSym(E->getOperand(0));
158 const MCSymbol *To = GetSym(E->getOperand(1));
159 uint64_t Count = cast(E->getOperand(2))
160 ->getValue()
161 ->getUniqueInteger()
162 .getZExtValue();
163 Streamer.emitCGProfileEntry(
164 MCSymbolRefExpr::create(From, MCSymbolRefExpr::VK_None, C),
165 MCSymbolRefExpr::create(To, MCSymbolRefExpr::VK_None, C), Count);
166 }
127167 }
128168
129169 MCSymbol *TargetLoweringObjectFileELF::getCFIPersonalitySymbol(
408408 void visitModuleFlag(const MDNode *Op,
409409 DenseMap &SeenIDs,
410410 SmallVectorImpl &Requirements);
411 void visitModuleFlagCGProfileEntry(const MDOperand &MDO);
411412 void visitFunction(const Function &F);
412413 void visitBasicBlock(BasicBlock &BB);
413414 void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty);
14101411 Assert(M.getNamedMetadata("llvm.linker.options"),
14111412 "'Linker Options' named metadata no longer supported");
14121413 }
1414
1415 if (ID->getString() == "CG Profile") {
1416 for (const MDOperand &MDO : cast(Op->getOperand(2))->operands())
1417 visitModuleFlagCGProfileEntry(MDO);
1418 }
1419 }
1420
1421 void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) {
1422 auto Node = dyn_cast_or_null(MDO);
1423 Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO);
1424 auto From = dyn_cast_or_null(Node->getOperand(0));
1425 Assert(From && isa(From->getValue()), "expected a Function",
1426 Node->getOperand(0));
1427 auto To = dyn_cast_or_null(Node->getOperand(1));
1428 Assert(To && isa(To->getValue()), "expected a Function",
1429 Node->getOperand(1));
1430 auto Count = dyn_cast_or_null(Node->getOperand(2));
1431 Assert(Count && Count->getType()->isIntegerTy(),
1432 "expected an integer constant", Node->getOperand(2));
14131433 }
14141434
14151435 /// Return true if this attribute kind only applies to functions.
6060 #include "llvm/Target/TargetMachine.h"
6161 #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
6262 #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
63 #include "llvm/Transforms/Instrumentation/CGProfile.h"
6364 #include "llvm/Transforms/IPO/AlwaysInliner.h"
6465 #include "llvm/Transforms/IPO/ArgumentPromotion.h"
6566 #include "llvm/Transforms/IPO/CalledValuePropagation.h"
831832 // Add the core optimizing pipeline.
832833 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM)));
833834
835 MPM.addPass(CGProfilePass());
836
834837 // Now we need to do some global optimization transforms.
835838 // FIXME: It would seem like these should come first in the optimization
836839 // pipeline and maybe be the bottom of the canonicalization pipeline? Weird
3939 #endif
4040 MODULE_PASS("always-inline", AlwaysInlinerPass())
4141 MODULE_PASS("called-value-propagation", CalledValuePropagationPass())
42 MODULE_PASS("cg-profile", CGProfilePass())
4243 MODULE_PASS("constmerge", ConstantMergePass())
4344 MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass())
4445 MODULE_PASS("deadargelim", DeadArgumentEliminationPass())
0 //===-- CGProfile.cpp -----------------------------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Transforms/Instrumentation/CGProfile.h"
10
11 #include "llvm/ADT/MapVector.h"
12 #include "llvm/Analysis/BlockFrequencyInfo.h"
13 #include "llvm/Analysis/TargetTransformInfo.h"
14 #include "llvm/IR/CallSite.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/MDBuilder.h"
18 #include "llvm/IR/PassManager.h"
19 #include "llvm/ProfileData/InstrProf.h"
20 #include "llvm/Transforms/Instrumentation.h"
21
22 #include
23
24 using namespace llvm;
25
26 PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) {
27 MapVector, uint64_t> Counts;
28 FunctionAnalysisManager &FAM =
29 MAM.getResult(M).getManager();
30 InstrProfSymtab Symtab;
31 auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F,
32 Function *CalledF, uint64_t NewCount) {
33 if (!CalledF || !TTI.isLoweredToCall(CalledF))
34 return;
35 uint64_t &Count = Counts[std::make_pair(F, CalledF)];
36 Count = SaturatingAdd(Count, NewCount);
37 };
38 // Ignore error here. Indirect calls are ignored if this fails.
39 (bool)Symtab.create(M);
40 for (auto &F : M) {
41 if (F.isDeclaration())
42 continue;
43 auto &BFI = FAM.getResult(F);
44 if (BFI.getEntryFreq() == 0)
45 continue;
46 TargetTransformInfo &TTI = FAM.getResult(F);
47 for (auto &BB : F) {
48 Optional BBCount = BFI.getBlockProfileCount(&BB);
49 if (!BBCount)
50 continue;
51 for (auto &I : BB) {
52 CallSite CS(&I);
53 if (!CS)
54 continue;
55 if (CS.isIndirectCall()) {
56 InstrProfValueData ValueData[8];
57 uint32_t ActualNumValueData;
58 uint64_t TotalC;
59 if (!getValueProfDataFromInst(*CS.getInstruction(),
60 IPVK_IndirectCallTarget, 8, ValueData,
61 ActualNumValueData, TotalC))
62 continue;
63 for (const auto &VD :
64 ArrayRef(ValueData, ActualNumValueData)) {
65 UpdateCounts(TTI, &F, Symtab.getFunction(VD.Value), VD.Count);
66 }
67 continue;
68 }
69 UpdateCounts(TTI, &F, CS.getCalledFunction(), *BBCount);
70 }
71 }
72 }
73
74 addModuleFlags(M, Counts);
75
76 return PreservedAnalyses::all();
77 }
78
79 void CGProfilePass::addModuleFlags(
80 Module &M,
81 MapVector, uint64_t> &Counts) const {
82 if (Counts.empty())
83 return;
84
85 LLVMContext &Context = M.getContext();
86 MDBuilder MDB(Context);
87 std::vector Nodes;
88
89 for (auto E : Counts) {
90 SmallVector Vals;
91 Vals.push_back(ValueAsMetadata::get(E.first.first));
92 Vals.push_back(ValueAsMetadata::get(E.first.second));
93 Vals.push_back(MDB.createConstant(
94 ConstantInt::get(Type::getInt64Ty(Context), E.second)));
95 Nodes.push_back(MDNode::get(Context, Vals));
96 }
97
98 M.addModuleFlag(Module::Append, "CG Profile", MDNode::get(Context, Nodes));
99 }
0 add_llvm_library(LLVMInstrumentation
11 AddressSanitizer.cpp
22 BoundsChecking.cpp
3 CGProfile.cpp
34 DataFlowSanitizer.cpp
45 GCOVProfiling.cpp
56 MemorySanitizer.cpp
0 ; RUN: opt < %s -passes cg-profile -S | FileCheck %s
1
2 declare void @b()
3
4 define void @a() !prof !1 {
5 call void @b()
6 ret void
7 }
8
9 @foo = common global i32 ()* null, align 8
10 declare i32 @func1()
11 declare i32 @func2()
12 declare i32 @func3()
13 declare i32 @func4()
14
15 define void @freq(i1 %cond) !prof !1 {
16 %tmp = load i32 ()*, i32 ()** @foo, align 8
17 call i32 %tmp(), !prof !3
18 br i1 %cond, label %A, label %B, !prof !2
19 A:
20 call void @a();
21 ret void
22 B:
23 call void @b();
24 ret void
25 }
26
27 !1 = !{!"function_entry_count", i64 32}
28 !2 = !{!"branch_weights", i32 5, i32 10}
29 !3 = !{!"VP", i32 0, i64 1600, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410, i64 -6929281286627296573, i64 150, i64 -2545542355363006406, i64 10}
30
31 ; CHECK: !llvm.module.flags = !{![[cgprof:[0-9]+]]}
32 ; CHECK: ![[cgprof]] = !{i32 5, !"CG Profile", ![[prof:[0-9]+]]}
33 ; CHECK: ![[prof]] = !{![[e0:[0-9]+]], ![[e1:[0-9]+]], ![[e2:[0-9]+]], ![[e3:[0-9]+]], ![[e4:[0-9]+]], ![[e5:[0-9]+]], ![[e6:[0-9]+]]}
34 ; CHECK: ![[e0]] = !{void ()* @a, void ()* @b, i64 32}
35 ; CHECK: ![[e1]] = !{void (i1)* @freq, i32 ()* @func4, i64 1030}
36 ; CHECK: ![[e2]] = !{void (i1)* @freq, i32 ()* @func2, i64 410}
37 ; CHECK: ![[e3]] = !{void (i1)* @freq, i32 ()* @func3, i64 150}
38 ; CHECK: ![[e4]] = !{void (i1)* @freq, i32 ()* @func1, i64 10}
39 ; CHECK: ![[e5]] = !{void (i1)* @freq, void ()* @a, i64 11}
40 ; CHECK: ![[e6]] = !{void (i1)* @freq, void ()* @b, i64 20}
0 ; RUN: llc -filetype=asm %s -o - -mtriple x86_64-pc-linux-gnu | FileCheck %s
1 ; RUN: llc -filetype=obj %s -o %t -mtriple x86_64-pc-linux-gnu
2 ; RUN: llvm-readobj -elf-cg-profile %t | FileCheck %s --check-prefix=OBJ
3
4 declare void @b()
5
6 define void @a() {
7 call void @b()
8 ret void
9 }
10
11 define void @freq(i1 %cond) {
12 br i1 %cond, label %A, label %B
13 A:
14 call void @a();
15 ret void
16 B:
17 call void @b();
18 ret void
19 }
20
21 !llvm.module.flags = !{!0}
22
23 !0 = !{i32 5, !"CG Profile", !1}
24 !1 = !{!2, !3, !4}
25 !2 = !{void ()* @a, void ()* @b, i64 32}
26 !3 = !{void (i1)* @freq, void ()* @a, i64 11}
27 !4 = !{void (i1)* @freq, void ()* @b, i64 20}
28
29 ; CHECK: .cg_profile a, b, 32
30 ; CHECK: .cg_profile freq, a, 11
31 ; CHECK: .cg_profile freq, b, 20
32
33 ; OBJ: CGProfile [
34 ; OBJ: CGProfileEntry {
35 ; OBJ: From: a
36 ; OBJ: To: b
37 ; OBJ: Weight: 32
38 ; OBJ: }
39 ; OBJ: CGProfileEntry {
40 ; OBJ: From: freq
41 ; OBJ: To: a
42 ; OBJ: Weight: 11
43 ; OBJ: }
44 ; OBJ: CGProfileEntry {
45 ; OBJ: From: freq
46 ; OBJ: To: b
47 ; OBJ: Weight: 20
48 ; OBJ: }
49 ; OBJ:]
245245 ; CHECK-O-NEXT: Running pass: SimplifyCFGPass
246246 ; CHECK-O-NEXT: Running pass: SpeculateAroundPHIsPass
247247 ; CHECK-O-NEXT: Finished llvm::Function pass manager run.
248 ; CHECK-O-NEXT: Running pass: CGProfilePass
248249 ; CHECK-O-NEXT: Running pass: GlobalDCEPass
249250 ; CHECK-O-NEXT: Running pass: ConstantMergePass
250251 ; CHECK-O-NEXT: Finished llvm::Module pass manager run.
223223 ; CHECK-POSTLINK-O-NEXT: Running pass: SimplifyCFGPass
224224 ; CHECK-POSTLINK-O-NEXT: Running pass: SpeculateAroundPHIsPass
225225 ; CHECK-POSTLINK-O-NEXT: Finished llvm::Function pass manager run.
226 ; CHECK-POSTLINK-O-NEXT: Running pass: CGProfilePass
226227 ; CHECK-POSTLINK-O-NEXT: Running pass: GlobalDCEPass
227228 ; CHECK-POSTLINK-O-NEXT: Running pass: ConstantMergePass
228229 ; CHECK-POSTLINK-O-NEXT: Finished llvm::Module pass manager run.
0 ; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
1
2 declare void @b()
3 declare void @a()
4
5 !llvm.module.flags = !{!0}
6
7 !0 = !{i32 5, !"CG Profile", !1}
8 !1 = !{!2, !"", !3, !4, !5, !6, !7, !8}
9 !2 = !{void ()* @a, void ()* @b, i64 32}
10 !3 = !{void ()* @a, void ()* @b}
11 !4 = !{void ()* @a, void ()* @b, i64 32, i64 32}
12 !5 = !{!"a", void ()* @b, i64 32}
13 !6 = !{void ()* @a, !"b", i64 32}
14 !7 = !{void ()* @a, void ()* @b, !""}
15 !8 = !{void ()* @a, void ()* @b, null}
16
17 ; CHECK: expected a MDNode triple
18 ; CHECK: !""
19 ; CHECK: expected a MDNode triple
20 ; CHECK: !3 = !{void ()* @a, void ()* @b}
21 ; CHECK: expected a MDNode triple
22 ; CHECK: !4 = !{void ()* @a, void ()* @b, i64 32, i64 32}
23 ; CHECK: expected a Function
24 ; CHECK: !"a"
25 ; CHECK: expected a Function
26 ; CHECK: !"b"
27 ; CHECK: expected an integer constant
28 ; CHECK: !""
29 ; CHECK: expected an integer constant