llvm.org GIT mirror llvm / 3da6ce5
Recommit r335794 "Add support for generating a call graph profile from Branch Frequency Info." with fix for removed functions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337140 91177308-0d34-0410-b5e6-96231b3b80d8 Michael J. Spencer 1 year, 2 months ago
13 changed file(s) with 339 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) -> MCSymbol * {
150 if (!MDO)
151 return nullptr;
152 auto V = cast(MDO);
153 const Function *F = cast(V->getValue());
154 return TM->getSymbol(F);
155 };
156
157 for (const auto &Edge : CFGProfile->operands()) {
158 MDNode *E = cast(Edge);
159 const MCSymbol *From = GetSym(E->getOperand(0));
160 const MCSymbol *To = GetSym(E->getOperand(1));
161 // Skip null functions. This can happen if functions are dead stripped after
162 // the CGProfile pass has been run.
163 if (!From || !To)
164 continue;
165 uint64_t Count = cast(E->getOperand(2))
166 ->getValue()
167 ->getUniqueInteger()
168 .getZExtValue();
169 Streamer.emitCGProfileEntry(
170 MCSymbolRefExpr::create(From, MCSymbolRefExpr::VK_None, C),
171 MCSymbolRefExpr::create(To, MCSymbolRefExpr::VK_None, C), Count);
172 }
127173 }
128174
129175 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 CheckFunction = [&](const MDOperand &FuncMDO) {
1423 if (!FuncMDO)
1424 return;
1425 auto F = dyn_cast(FuncMDO);
1426 Assert(F && isa(F->getValue()), "expected a Function or null",
1427 FuncMDO);
1428 };
1429 auto Node = dyn_cast_or_null(MDO);
1430 Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO);
1431 CheckFunction(Node->getOperand(0));
1432 CheckFunction(Node->getOperand(1));
1433 auto Count = dyn_cast_or_null(Node->getOperand(2));
1434 Assert(Count && Count->getType()->isIntegerTy(),
1435 "expected an integer constant", Node->getOperand(2));
14131436 }
14141437
14151438 /// Return true if this attribute kind only applies to functions.
6060 #include "llvm/Support/Regex.h"
6161 #include "llvm/Target/TargetMachine.h"
6262 #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.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"
842843 // Add the core optimizing pipeline.
843844 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM)));
844845
846 MPM.addPass(CGProfilePass());
847
845848 // Now we need to do some global optimization transforms.
846849 // FIXME: It would seem like these should come first in the optimization
847850 // 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 (void)(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, !5}
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 !5 = !{void (i1)* @freq, null, i64 20}
29
30 ; CHECK: .cg_profile a, b, 32
31 ; CHECK: .cg_profile freq, a, 11
32 ; CHECK: .cg_profile freq, b, 20
33
34 ; OBJ: CGProfile [
35 ; OBJ: CGProfileEntry {
36 ; OBJ: From: a
37 ; OBJ: To: b
38 ; OBJ: Weight: 32
39 ; OBJ: }
40 ; OBJ: CGProfileEntry {
41 ; OBJ: From: freq
42 ; OBJ: To: a
43 ; OBJ: Weight: 11
44 ; OBJ: }
45 ; OBJ: CGProfileEntry {
46 ; OBJ: From: freq
47 ; OBJ: To: b
48 ; OBJ: Weight: 20
49 ; OBJ: }
50 ; 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 or null
24 ; CHECK: !"a"
25 ; CHECK: expected a Function or null
26 ; CHECK: !"b"
27 ; CHECK: expected an integer constant
28 ; CHECK: !""
29 ; CHECK: expected an integer constant