llvm.org GIT mirror llvm / 2713e77
Revert "Output optimization remarks in YAML" This reverts commit r282499. The GCC bots are failing git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282503 91177308-0d34-0410-b5e6-96231b3b80d8 Adam Nemet 3 years ago
10 changed file(s) with 10 addition(s) and 331 deletion(s). Raw diff Collapse all Expand all
1616
1717 #include "llvm/ADT/Optional.h"
1818 #include "llvm/Analysis/BlockFrequencyInfo.h"
19 #include "llvm/IR/DiagnosticInfo.h"
2019 #include "llvm/IR/PassManager.h"
2120 #include "llvm/Pass.h"
2221
6261 return *this;
6362 }
6463
65 /// The new interface to emit remarks.
66 void emit(DiagnosticInfoOptimizationBase &OptDiag);
67
6864 /// Emit an optimization-applied message.
6965 ///
7066 /// \p PassName is the name of the pass emitting the message. If -Rpass= is
201197 /// If we generate BFI on demand, we need to free it when ORE is freed.
202198 std::unique_ptr OwnedBFI;
203199
204 /// Compute hotness from IR value (currently assumed to be a block) if PGO is
205 /// available.
206200 Optional computeHotness(const Value *V);
207
208 /// Similar but use value from \p OptDiag and update hotness there.
209 void computeHotness(DiagnosticInfoOptimizationBase &OptDiag);
210201
211202 /// \brief Only allow verbose messages if we know we're filtering by hotness
212203 /// (BFI is only set in this case).
215206 OptimizationRemarkEmitter(const OptimizationRemarkEmitter &) = delete;
216207 void operator=(const OptimizationRemarkEmitter &) = delete;
217208 };
218
219 /// \brief Add a small namespace to avoid name clashes with the classes used in
220 /// the streaming interface. We want these to be short for better
221 /// write/readability.
222 namespace ore {
223 using NV = DiagnosticInfoOptimizationBase::Argument;
224 using setIsVerbose = DiagnosticInfoOptimizationBase::setIsVerbose;
225 }
226209
227210 /// OptimizationRemarkEmitter legacy analysis pass
228211 ///
1616
1717 #include "llvm-c/Types.h"
1818 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/SmallString.h"
2019 #include "llvm/ADT/StringRef.h"
2120 #include "llvm/ADT/Twine.h"
2221 #include "llvm/IR/DebugLoc.h"
2322 #include "llvm/Support/CBindingWrapping.h"
24 #include "llvm/Support/YAMLTraits.h"
2523 #include
2624 #include
2725
376374 /// Common features for diagnostics dealing with optimization remarks.
377375 class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithDebugLocBase {
378376 public:
379 /// \brief Used to set IsVerbose via the stream interface.
380 struct setIsVerbose {};
381
382 /// \brief Used in the streaming interface as the general argument type. It
383 /// internally converts everything into a key-value pair.
384 struct Argument {
385 StringRef Key;
386 std::string Val;
387
388 explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
389 explicit Argument(StringRef Key, Value *V) : Key(Key), Val(V->getName()) {}
390 explicit Argument(StringRef Key, int N)
391 : Key(Key), Val(std::to_string(N)) {}
392 };
393
394 /// \p PassName is the name of the pass emitting this diagnostic. \p
395 /// RemarkName is a textual identifier for the remark. \p Fn is the function
396 /// where the diagnostic is being emitted. \p DLoc is the location information
397 /// to use in the diagnostic. If line table information is available, the
398 /// diagnostic will include the source code location. \p CodeRegion is IR
399 /// value (currently basic block) that the optimization operates on. This is
400 /// currently used to provide run-time hotness information with PGO.
401 DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
402 enum DiagnosticSeverity Severity,
403 const char *PassName, StringRef RemarkName,
404 const Function &Fn, const DebugLoc &DLoc,
405 Value *CodeRegion = nullptr)
406 : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc),
407 PassName(PassName), RemarkName(RemarkName), CodeRegion(CodeRegion),
408 IsVerbose(false) {}
409
410 /// Legacy interface.
411377 /// \p PassName is the name of the pass emitting this diagnostic.
412378 /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
413379 /// the location information to use in the diagnostic. If line table
421387 const DebugLoc &DLoc, const Twine &Msg,
422388 Optional Hotness = None)
423389 : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc),
424 PassName(PassName), Hotness(Hotness), IsVerbose(false) {
425 Args.push_back(Argument(Msg.str()));
426 }
427
428 DiagnosticInfoOptimizationBase &operator<<(StringRef S);
429 DiagnosticInfoOptimizationBase &operator<<(Argument A);
430 DiagnosticInfoOptimizationBase &operator<<(setIsVerbose V);
390 PassName(PassName), Msg(Msg), Hotness(Hotness) {}
431391
432392 /// \see DiagnosticInfo::print.
433393 void print(DiagnosticPrinter &DP) const override;
440400 virtual bool isEnabled() const = 0;
441401
442402 const char *getPassName() const { return PassName; }
443 std::string getMsg() const;
403 const Twine &getMsg() const { return Msg; }
444404 Optional getHotness() const { return Hotness; }
445 void setHotness(Optional H) { Hotness = H; }
446
447 Value *getCodeRegion() const { return CodeRegion; }
448
449 bool isVerbose() const { return IsVerbose; }
450405
451406 static bool classof(const DiagnosticInfo *DI) {
452407 return DI->getKind() >= DK_FirstRemark &&
459414 /// be emitted.
460415 const char *PassName;
461416
462 /// Textual identifier for the remark. Can be used by external tools reading
463 /// the YAML output file for optimization remarks to identify the remark.
464 StringRef RemarkName;
417 /// Message to report.
418 const Twine &Msg;
465419
466420 /// If profile information is available, this is the number of times the
467421 /// corresponding code was executed in a profile instrumentation run.
468422 Optional Hotness;
469
470 /// The IR value (currently basic block) that the optimization operates on.
471 /// This is currently used to provide run-time hotness information with PGO.
472 Value *CodeRegion;
473
474 /// Arguments collected via the streaming interface.
475 SmallVector Args;
476
477 /// The remark is expected to be noisy.
478 bool IsVerbose;
479
480 friend struct yaml::MappingTraits;
481423 };
482424
483425 /// Diagnostic information for applied optimization remarks.
523465 Optional Hotness = None)
524466 : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkMissed, DS_Remark,
525467 PassName, Fn, DLoc, Msg, Hotness) {}
526
527 /// \p PassName is the name of the pass emitting this diagnostic. If this name
528 /// matches the regular expression given in -Rpass-missed=, then the
529 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
530 /// remark. \p Inst is the instruction that the optimization operates on.
531 DiagnosticInfoOptimizationRemarkMissed(const char *PassName,
532 StringRef RemarkName,
533 Instruction *Inst);
534468
535469 static bool classof(const DiagnosticInfo *DI) {
536470 return DI->getKind() == DK_OptimizationRemarkMissed;
3333 class Function;
3434 class DebugLoc;
3535 class OptBisect;
36 namespace yaml {
37 class Output;
38 }
3936
4037 /// This is an important class for using LLVM in a threaded context. It
4138 /// (opaquely) owns and manages the core "global" data of LLVM's core
183180 /// diagnostics.
184181 void setDiagnosticHotnessRequested(bool Requested);
185182
186 /// \brief Return the YAML file used by the backend to save optimization
187 /// diagnostics. If null, diagnostics are not saved in a file but only
188 /// emitted via the diagnostic handler.
189 yaml::Output *getDiagnosticsOutputFile();
190 /// Set the diagnostics output file used for optimization diagnostics.
191 ///
192 /// By default or if invoked with null, diagnostics are not saved in a file
193 /// but only emitted via the diagnostic handler. Even if an output file is
194 /// set, the handler is invoked for each diagnostic message.
195 void setDiagnosticsOutputFile(yaml::Output *F);
196
197183 /// \brief Get the prefix that should be printed in front of a diagnostic of
198184 /// the given \p Severity
199185 static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity);
1515 #include "llvm/Analysis/BranchProbabilityInfo.h"
1616 #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
1717 #include "llvm/Analysis/LoopInfo.h"
18 #include "llvm/IR/DebugInfo.h"
1918 #include "llvm/IR/DiagnosticInfo.h"
2019 #include "llvm/IR/Dominators.h"
2120 #include "llvm/IR/LLVMContext.h"
4948 return None;
5049
5150 return BFI->getBlockProfileCount(cast(V));
52 }
53
54 template <> struct yaml::MappingTraits {
55 static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
56 assert(io.outputting() && "input not yet implemented");
57
58 if (io.mapTag("!Missed", OptDiag->getKind() == DK_OptimizationRemarkMissed))
59 ;
60 else
61 llvm_unreachable("todo");
62
63 // These are read-only for now.
64 DebugLoc DL = OptDiag->getDebugLoc();
65 StringRef FN = OptDiag->getFunction().getName();
66
67 StringRef PassName(OptDiag->PassName);
68 io.mapRequired("Pass", PassName);
69 io.mapRequired("Name", OptDiag->RemarkName);
70 if (!io.outputting() || DL)
71 io.mapOptional("DebugLoc", DL);
72 io.mapRequired("Function", FN);
73 io.mapOptional("Hotness", OptDiag->Hotness);
74 io.mapOptional("Args", OptDiag->Args);
75 }
76 };
77
78 template <> struct yaml::MappingTraits {
79 static void mapping(IO &io, DebugLoc &DL) {
80 assert(io.outputting() && "input not yet implemented");
81
82 auto *Scope = cast(DL.getScope());
83 StringRef File = Scope->getFilename();
84 unsigned Line = DL.getLine();
85 unsigned Col = DL.getCol();
86
87 io.mapRequired("File", File);
88 io.mapRequired("Line", Line);
89 io.mapRequired("Column", Col);
90 }
91
92 static const bool flow = true;
93 };
94
95 template <>
96 struct yaml::ScalarTraits {
97 static void output(const DiagnosticInfoOptimizationBase::Argument &Arg,
98 void *, llvm::raw_ostream &out) {
99 out << Arg.Key << ": " << Arg.Val;
100 }
101
102 static StringRef input(StringRef scalar, void *,
103 DiagnosticInfoOptimizationBase::Argument &Arg) {
104 llvm_unreachable("input not yet implemented");
105 }
106
107 static bool mustQuote(StringRef) { return false; }
108 };
109
110 LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
111
112 void OptimizationRemarkEmitter::computeHotness(
113 DiagnosticInfoOptimizationBase &OptDiag) {
114 Value *V = OptDiag.getCodeRegion();
115 if (V)
116 OptDiag.setHotness(computeHotness(V));
117 }
118
119 void OptimizationRemarkEmitter::emit(DiagnosticInfoOptimizationBase &OptDiag) {
120 computeHotness(OptDiag);
121
122 yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
123 if (Out && OptDiag.isEnabled()) {
124 auto *P = &const_cast(OptDiag);
125 *Out << P;
126 }
127 // FIXME: now that IsVerbose is part of DI, filtering for this will be moved
128 // from here to clang.
129 if (!OptDiag.isVerbose() || shouldEmitVerbose())
130 F->getContext().diagnose(OptDiag);
13151 }
13252
13353 void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
180180 PassRemarksOptLoc.Pattern->match(getPassName());
181181 }
182182
183 DiagnosticInfoOptimizationRemarkMissed::DiagnosticInfoOptimizationRemarkMissed(
184 const char *PassName, StringRef RemarkName, Instruction *Inst)
185 : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkMissed, DS_Remark,
186 PassName, RemarkName,
187 *Inst->getParent()->getParent(),
188 Inst->getDebugLoc(), Inst->getParent()) {}
189
190183 bool DiagnosticInfoOptimizationRemarkMissed::isEnabled() const {
191184 return PassRemarksMissedOptLoc.Pattern &&
192185 PassRemarksMissedOptLoc.Pattern->match(getPassName());
272265 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {
273266 DP << "Instruction selection used fallback path for " << getFunction();
274267 }
275
276 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
277 operator<<(StringRef S) {
278 Args.emplace_back(S);
279 return *this;
280 }
281
282 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
283 operator<<(Argument A) {
284 Args.push_back(std::move(A));
285 return *this;
286 }
287
288 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
289 operator<<(setIsVerbose V) {
290 IsVerbose = true;
291 return *this;
292 }
293
294 std::string DiagnosticInfoOptimizationBase::getMsg() const {
295 std::string Str;
296 raw_string_ostream OS(Str);
297 for (const DiagnosticInfoOptimizationBase::Argument &Arg : Args)
298 OS << Arg.Val;
299 return OS.str();
300 }
202202 return pImpl->DiagnosticHotnessRequested;
203203 }
204204
205 yaml::Output *LLVMContext::getDiagnosticsOutputFile() {
206 return pImpl->DiagnosticsOutputFile.get();
207 }
208
209 void LLVMContext::setDiagnosticsOutputFile(yaml::Output *F) {
210 pImpl->DiagnosticsOutputFile.reset(F);
211 }
212
213205 LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
214206 return pImpl->DiagnosticHandler;
215207 }
3232 #include "llvm/IR/Metadata.h"
3333 #include "llvm/IR/ValueHandle.h"
3434 #include "llvm/Support/Dwarf.h"
35 #include "llvm/Support/YAMLTraits.h"
3635 #include
3736
3837 namespace llvm {
10431042 void *DiagnosticContext;
10441043 bool RespectDiagnosticFilters;
10451044 bool DiagnosticHotnessRequested;
1046 std::unique_ptr DiagnosticsOutputFile;
10471045
10481046 LLVMContext::YieldCallbackTy YieldCallback;
10491047 void *YieldOpaqueHandle;
468468 // direct call, so we keep it.
469469 if (Function *Callee = CS.getCalledFunction())
470470 if (Callee->isDeclaration()) {
471 ORE.emitOptimizationRemarkAnalysis(
472 DEBUG_TYPE, &I, Twine("definition of ") + Callee->getName() +
473 " is not available",
471 ORE.emitOptimizationRemarkMissedAndAnalysis(
472 DEBUG_TYPE, &I,
473 Twine(Callee->getName()) + " will not be inlined into " +
474 CS.getCaller()->getName(),
475 Twine("definition of ") + Callee->getName() +
476 " is not available",
474477 /*Verbose=*/true);
475 using namespace ore;
476 ORE.emit(DiagnosticInfoOptimizationRemarkMissed(DEBUG_TYPE,
477 "NotInlined", &I)
478 << NV("Callee", Callee) << " will not be inlined into "
479 << NV("Caller", CS.getCaller()) << setIsVerbose());
480478 continue;
481479 }
482480
+0
-76
test/Transforms/Inline/optimization-remarks-yaml.ll less more
None ; RUN: opt < %s -inline -pass-remarks-missed=inline -pass-remarks-with-hotness \
1 ; RUN: -pass-remarks-output=%t 2>&1 | FileCheck %s
2 ; RUN: cat %t | FileCheck -check-prefix=YAML %s
3
4 ; Check the YAML file generated for inliner remarks for this program:
5 ;
6 ; 1 int foo();
7 ; 2 int bar();
8 ; 3
9 ; 4 int baz() {
10 ; 5 return foo() + bar();
11 ; 6 }
12
13 ; CHECK: remark: /tmp/s.c:5:10: foo will not be inlined into baz (hotness: 30)
14 ; CHECK-NEXT: remark: /tmp/s.c:5:18: bar will not be inlined into baz (hotness: 30)
15
16 ; YAML: --- !Missed
17 ; YAML-NEXT: Pass: inline
18 ; YAML-NEXT: Name: NotInlined
19 ; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 5, Column: 10 }
20 ; YAML-NEXT: Function: baz
21 ; YAML-NEXT: Hotness: 30
22 ; YAML-NEXT: Args:
23 ; YAML-NEXT: - Callee: foo
24 ; YAML-NEXT: - String: will not be inlined into
25 ; YAML-NEXT: - Caller: baz
26 ; YAML-NEXT: ...
27 ; YAML-NEXT: --- !Missed
28 ; YAML-NEXT: Pass: inline
29 ; YAML-NEXT: Name: NotInlined
30 ; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 5, Column: 18 }
31 ; YAML-NEXT: Function: baz
32 ; YAML-NEXT: Hotness: 30
33 ; YAML-NEXT: Args:
34 ; YAML-NEXT: - Callee: bar
35 ; YAML-NEXT: - String: will not be inlined into
36 ; YAML-NEXT: - Caller: baz
37 ; YAML-NEXT: ...
38
39 ; ModuleID = '/tmp/s.c'
40 source_filename = "/tmp/s.c"
41 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
42 target triple = "x86_64-apple-macosx10.11.0"
43
44 ; Function Attrs: nounwind ssp uwtable
45 define i32 @baz() !dbg !7 !prof !14 {
46 entry:
47 %call = call i32 (...) @foo(), !dbg !9
48 %call1 = call i32 (...) @bar(), !dbg !10
49 %add = add nsw i32 %call, %call1, !dbg !12
50 ret i32 %add, !dbg !13
51 }
52
53 declare i32 @foo(...)
54
55 declare i32 @bar(...)
56
57 !llvm.dbg.cu = !{!0}
58 !llvm.module.flags = !{!3, !4, !5}
59 !llvm.ident = !{!6}
60
61 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 281293) (llvm/trunk 281290)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
62 !1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
63 !2 = !{}
64 !3 = !{i32 2, !"Dwarf Version", i32 4}
65 !4 = !{i32 2, !"Debug Info Version", i32 3}
66 !5 = !{i32 1, !"PIC Level", i32 2}
67 !6 = !{!"clang version 4.0.0 (trunk 281293) (llvm/trunk 281290)"}
68 !7 = distinct !DISubprogram(name: "baz", scope: !1, file: !1, line: 4, type: !8, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: true, unit: !0, variables: !2)
69 !8 = !DISubroutineType(types: !2)
70 !9 = !DILocation(line: 5, column: 10, scope: !7)
71 !10 = !DILocation(line: 5, column: 18, scope: !11)
72 !11 = !DILexicalBlockFile(scope: !7, file: !1, discriminator: 1)
73 !12 = !DILocation(line: 5, column: 16, scope: !7)
74 !13 = !DILocation(line: 5, column: 3, scope: !7)
75 !14 = !{!"function_entry_count", i64 30}
4848 #include "llvm/Support/TargetRegistry.h"
4949 #include "llvm/Support/TargetSelect.h"
5050 #include "llvm/Support/ToolOutputFile.h"
51 #include "llvm/Support/YAMLTraits.h"
5251 #include "llvm/Target/TargetMachine.h"
5352 #include "llvm/Transforms/Coroutines.h"
5453 #include "llvm/Transforms/IPO/AlwaysInliner.h"
230229 "pass-remarks-with-hotness",
231230 cl::desc("With PGO, include profile count in optimization remarks"),
232231 cl::Hidden);
233
234 static cl::opt
235 RemarksFilename("pass-remarks-output",
236 cl::desc("YAML output filename for pass remarks"),
237 cl::value_desc("filename"));
238232
239233 static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
240234 // Add the pass to the pass manager...
413407 if (PassRemarksWithHotness)
414408 Context.setDiagnosticHotnessRequested(true);
415409
416 std::unique_ptr YamlFile;
417 if (RemarksFilename != "") {
418 std::error_code EC;
419 YamlFile = llvm::make_unique(RemarksFilename, EC,
420 sys::fs::F_None);
421 if (EC) {
422 errs() << EC.message() << '\n';
423 return 1;
424 }
425 Context.setDiagnosticsOutputFile(new yaml::Output(YamlFile->os()));
426 }
427
428410 // Load the input module...
429411 std::unique_ptr M = parseIRFile(InputFilename, Err, Context);
430412
733715 "the compile-twice option\n";
734716 Out->os() << BOS->str();
735717 Out->keep();
736 if (YamlFile)
737 YamlFile->keep();
738718 return 1;
739719 }
740720 Out->os() << BOS->str();
744724 if (!NoOutput || PrintBreakpoints)
745725 Out->keep();
746726
747 if (YamlFile)
748 YamlFile->keep();
749
750727 return 0;
751728 }