Skip to content

Commit aaab186

Browse files
authored
Merge pull request swiftlang#29650 from francisvm/sil-remark-streamer
[Remarks] Add a specialized RemarkStreamer for SIL remarks
2 parents 69b513a + e724eba commit aaab186

29 files changed

+636
-358
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,8 @@ NOTE(compiled_module_invalid_reason,none,
372372
ERROR(unknown_forced_module_loading_mode,none,
373373
"unknown value for SWIFT_FORCE_MODULE_LOADING variable: '%0'",
374374
(StringRef))
375+
ERROR(error_creating_remark_serializer,none,
376+
"error while creating remark serializer: '%0'", (StringRef))
375377

376378
REMARK(interface_file_lock_failure,none,
377379
"could not acquire lock file for module interface '%0'", (StringRef))

include/swift/AST/SILOptions.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/Basic/OptimizationMode.h"
2424
#include "llvm/ADT/Hashing.h"
2525
#include "llvm/ADT/StringRef.h"
26+
#include "llvm/Remarks/RemarkFormat.h"
2627
#include <string>
2728
#include <climits>
2829

@@ -161,10 +162,17 @@ class SILOptions {
161162
/// pipeline or after serialization.
162163
bool StripOwnershipAfterSerialization = true;
163164

164-
/// The name of the file to which the backend should save YAML optimization
165+
/// The name of the file to which the backend should save optimization
165166
/// records.
166167
std::string OptRecordFile;
167168

169+
/// The regex that filters the passes that should be saved to the optimization
170+
/// records.
171+
std::string OptRecordPasses;
172+
173+
/// The format used for serializing remarks (default: YAML)
174+
llvm::remarks::Format OptRecordFormat = llvm::remarks::Format::YAML;
175+
168176
SILOptions() {}
169177

170178
/// Return a hash code of any components from these options that should

include/swift/Basic/FileTypes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ TYPE("tbd", TBD, "tbd", "")
7272
TYPE("module-trace", ModuleTrace, "trace.json", "")
7373

7474
TYPE("index-data", IndexData, "", "")
75-
TYPE("opt-record", OptRecord, "opt.yaml", "")
75+
TYPE("yaml-opt-record", YAMLOptRecord, "opt.yaml", "")
76+
TYPE("bitstream-opt-record",BitstreamOptRecord, "opt.bitstream", "")
7677

7778
// Overlay files declare wrapper modules, called "separately-imported overlays",
7879
// that should be automatically imported when a particular module is imported.

include/swift/Driver/ToolChain.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,9 @@ class ToolChain {
317317
virtual void validateArguments(DiagnosticEngine &diags,
318318
const llvm::opt::ArgList &args,
319319
StringRef defaultTarget) const {}
320+
321+
llvm::Expected<file_types::ID>
322+
remarkFileTypeFromArgs(const llvm::opt::ArgList &Args) const;
320323
};
321324
} // end namespace driver
322325
} // end namespace swift

include/swift/Option/Options.td

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,10 +548,20 @@ def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">,
548548

549549
def save_optimization_record : Flag<["-"], "save-optimization-record">,
550550
Flags<[FrontendOption]>, HelpText<"Generate a YAML optimization record file">;
551+
def save_optimization_record_EQ : Joined<["-"], "save-optimization-record=">,
552+
Flags<[FrontendOption]>,
553+
HelpText<"Generate an optimization record file in a specific format "
554+
"(default: YAML)">, MetaVarName<"<format>">;
551555
def save_optimization_record_path :
552556
Separate<["-"], "save-optimization-record-path">,
553557
Flags<[FrontendOption, ArgumentIsPath]>,
554-
HelpText<"Specify the file name of any generated YAML optimization record">;
558+
HelpText<"Specify the file name of any generated optimization record">;
559+
def save_optimization_record_passes :
560+
Separate<["-"], "save-optimization-record-passes">,
561+
Flags<[FrontendOption]>,
562+
HelpText<"Only include passes which match a specified regular expression in"
563+
"the generated optimization record "
564+
"(by default, include all passes)">, MetaVarName<"<regex>">;
555565

556566
// Platform options.
557567
def enable_app_extension : Flag<["-"], "application-extension">,

include/swift/SIL/OptimizationRemark.h

Lines changed: 82 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define SWIFT_SIL_OPTIMIZATIONREMARKEMITTER_H
2121

2222
#include "swift/Basic/SourceLoc.h"
23+
#include "swift/Demangling/Demangler.h"
2324
#include "swift/SIL/SILBasicBlock.h"
2425
#include "swift/SIL/SILInstruction.h"
2526
#include "swift/SIL/SILModule.h"
@@ -34,24 +35,24 @@ namespace OptRemark {
3435
/// Used in the streaming interface as the general argument type. It
3536
/// internally converts everything into a key-value pair.
3637
struct Argument {
37-
std::string Key;
38-
std::string Val;
38+
std::string key;
39+
std::string val;
3940
/// If set, the debug location corresponding to the value.
40-
SourceLoc Loc;
41+
SourceLoc loc;
4142

42-
explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
43-
Argument(StringRef Key, StringRef Val) : Key(Key), Val(Val) {}
43+
explicit Argument(StringRef Str = "") : key("String"), val(Str) {}
44+
Argument(StringRef key, StringRef val) : key(key), val(val) {}
4445

45-
Argument(StringRef Key, int N);
46-
Argument(StringRef Key, long N);
47-
Argument(StringRef Key, long long N);
48-
Argument(StringRef Key, unsigned N);
49-
Argument(StringRef Key, unsigned long N);
50-
Argument(StringRef Key, unsigned long long N);
46+
Argument(StringRef key, int n);
47+
Argument(StringRef key, long n);
48+
Argument(StringRef key, long long n);
49+
Argument(StringRef key, unsigned n);
50+
Argument(StringRef key, unsigned long n);
51+
Argument(StringRef key, unsigned long long n);
5152

52-
Argument(StringRef Key, SILFunction *F);
53-
Argument(StringRef Key, SILType Ty);
54-
Argument(StringRef Key, CanType Ty);
53+
Argument(StringRef key, SILFunction *f);
54+
Argument(StringRef key, SILType ty);
55+
Argument(StringRef key, CanType ty);
5556
};
5657

5758
/// Shorthand to insert named-value pairs.
@@ -60,132 +61,142 @@ using NV = Argument;
6061
/// Inserting this into a Remark indents the text when printed as a debug
6162
/// message.
6263
struct IndentDebug {
63-
explicit IndentDebug(unsigned Width) : Width(Width) {}
64-
unsigned Width;
64+
explicit IndentDebug(unsigned width) : width(width) {}
65+
unsigned width;
6566
};
6667

6768
/// The base class for remarks. This can be created by optimization passed to
6869
/// report successful and unsuccessful optimizations. CRTP is used to preserve
6970
/// the underlying type encoding the remark kind in the insertion operator.
7071
template <typename DerivedT> class Remark {
7172
/// Arguments collected via the streaming interface.
72-
SmallVector<Argument, 4> Args;
73+
SmallVector<Argument, 4> args;
7374

7475
/// The name of the pass generating the remark.
75-
StringRef PassName;
76+
StringRef passName;
7677

7778
/// Textual identifier for the remark (single-word, camel-case). Can be used
78-
/// by external tools reading the YAML output file for optimization remarks to
79+
/// by external tools reading the output file for optimization remarks to
7980
/// identify the remark.
80-
StringRef Identifier;
81+
SmallString<32> identifier;
8182

8283
/// Source location for the diagnostics.
83-
SourceLoc Location;
84+
SourceLoc location;
8485

8586
/// The function for the diagnostics.
86-
SILFunction *Function;
87+
SILFunction *function;
88+
89+
/// The demangled name of \p Function.
90+
SmallString<64> demangledFunctionName;
8791

8892
/// Indentation used if this remarks is printed as a debug message.
89-
unsigned IndentDebugWidth = 0;
93+
unsigned indentDebugWidth = 0;
9094

9195
protected:
92-
Remark(StringRef Identifier, SILInstruction &I)
93-
: Identifier(Identifier), Location(I.getLoc().getSourceLoc()),
94-
Function(I.getParent()->getParent()) {}
96+
Remark(StringRef identifier, SILInstruction &i)
97+
: identifier((Twine("sil.") + identifier).str()),
98+
location(i.getLoc().getSourceLoc()),
99+
function(i.getParent()->getParent()),
100+
demangledFunctionName(Demangle::demangleSymbolAsString(
101+
function->getName(),
102+
Demangle::DemangleOptions::SimplifiedUIDemangleOptions())) {}
95103

96104
public:
97-
DerivedT &operator<<(StringRef S) {
98-
Args.emplace_back(S);
105+
DerivedT &operator<<(StringRef s) {
106+
args.emplace_back(s);
99107
return *static_cast<DerivedT *>(this);
100108
}
101109

102-
DerivedT &operator<<(Argument A) {
103-
Args.push_back(std::move(A));
110+
DerivedT &operator<<(Argument a) {
111+
args.push_back(std::move(a));
104112
return *static_cast<DerivedT *>(this);
105113
}
106114

107-
DerivedT &operator<<(IndentDebug ID) {
108-
IndentDebugWidth = ID.Width;
115+
DerivedT &operator<<(IndentDebug indent) {
116+
indentDebugWidth = indent.width;
109117
return *static_cast<DerivedT *>(this);
110118
}
111119

112-
StringRef getPassName() const { return PassName; }
113-
StringRef getIdentifier() const { return Identifier; }
114-
SILFunction *getFunction() const { return Function; }
115-
SourceLoc getLocation() const { return Location; }
120+
StringRef getPassName() const { return passName; }
121+
StringRef getIdentifier() const { return identifier; }
122+
SILFunction *getFunction() const { return function; }
123+
StringRef getDemangledFunctionName() const { return demangledFunctionName; }
124+
SourceLoc getLocation() const { return location; }
116125
std::string getMsg() const;
117126
std::string getDebugMsg() const;
118127
Remark<DerivedT> &getRemark() { return *this; }
119-
SmallVector<Argument, 4> &getArgs() { return Args; }
128+
SmallVector<Argument, 4> &getArgs() { return args; }
129+
ArrayRef<Argument> getArgs() const { return args; }
120130

121-
void setPassName(StringRef PN) { PassName = PN; }
131+
void setPassName(StringRef name) { passName = name; }
122132
};
123133

124134
/// Remark to report a successful optimization.
125135
struct RemarkPassed : public Remark<RemarkPassed> {
126-
RemarkPassed(StringRef Id, SILInstruction &I) : Remark(Id, I) {}
136+
RemarkPassed(StringRef id, SILInstruction &i) : Remark(id, i) {}
127137
};
128138
/// Remark to report a unsuccessful optimization.
129139
struct RemarkMissed : public Remark<RemarkMissed> {
130-
RemarkMissed(StringRef Id, SILInstruction &I) : Remark(Id, I) {}
140+
RemarkMissed(StringRef id, SILInstruction &i) : Remark(id, i) {}
131141
};
132142

133143
/// Used to emit the remarks. Passes reporting remarks should create an
134144
/// instance of this.
135145
class Emitter {
136-
SILModule &Module;
137-
std::string PassName;
138-
bool PassedEnabled;
139-
bool MissedEnabled;
146+
SILModule &module;
147+
std::string passName;
148+
bool passedEnabled;
149+
bool missedEnabled;
140150

141151
// Making these non-generic allows out-of-line definition.
142-
void emit(const RemarkPassed &R);
143-
void emit(const RemarkMissed &R);
144-
static void emitDebug(const RemarkPassed &R);
145-
static void emitDebug(const RemarkMissed &R);
152+
void emit(const RemarkPassed &remark);
153+
void emit(const RemarkMissed &remark);
154+
static void emitDebug(const RemarkPassed &remark);
155+
static void emitDebug(const RemarkMissed &remark);
146156

147157
template <typename RemarkT> bool isEnabled();
148158

149159
public:
150-
Emitter(StringRef PassName, SILModule &M);
160+
Emitter(StringRef passName, SILModule &m);
151161

152162
/// Take a lambda that returns a remark which will be emitted. The
153163
/// lambda is not evaluated unless remarks are enabled. Second argument is
154164
/// only used to restrict this to functions.
155165
template <typename T>
156-
void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
157-
using RemarkT = decltype(RemarkBuilder());
166+
void emit(T remarkBuilder, decltype(remarkBuilder()) * = nullptr) {
167+
using RemarkT = decltype(remarkBuilder());
158168
// Avoid building the remark unless remarks are enabled.
159-
if (isEnabled<RemarkT>() || Module.getOptRecordStream()) {
160-
auto rb = RemarkBuilder();
161-
rb.setPassName(PassName);
169+
if (isEnabled<RemarkT>() || module.getSILRemarkStreamer()) {
170+
auto rb = remarkBuilder();
171+
rb.setPassName(passName);
162172
emit(rb);
163173
}
164174
}
165175

166176
/// Emit an optimization remark or debug message.
167177
template <typename T>
168-
static void emitOrDebug(const char *PassName, Emitter *ORE, T RemarkBuilder,
169-
decltype(RemarkBuilder()) * = nullptr) {
170-
using RemarkT = decltype(RemarkBuilder());
178+
static void emitOrDebug(const char *passName, Emitter *emitter,
179+
T remarkBuilder,
180+
decltype(remarkBuilder()) * = nullptr) {
181+
using RemarkT = decltype(remarkBuilder());
171182
// Avoid building the remark unless remarks are enabled.
172-
bool EmitRemark =
173-
ORE && (ORE->isEnabled<RemarkT>() || ORE->Module.getOptRecordStream());
183+
bool emitRemark = emitter && (emitter->isEnabled<RemarkT>() ||
184+
emitter->module.getSILRemarkStreamer());
174185
// Same for DEBUG.
175-
bool EmitDebug = false;
186+
bool shouldEmitDebug = false;
176187
#ifndef NDEBUG
177-
EmitDebug |= llvm::DebugFlag && llvm::isCurrentDebugType(PassName);
188+
shouldEmitDebug |= llvm::DebugFlag && llvm::isCurrentDebugType(passName);
178189
#endif // NDEBUG
179190

180-
if (EmitRemark || EmitDebug) {
181-
auto R = RemarkBuilder();
182-
if (EmitDebug)
183-
emitDebug(R);
184-
if (EmitRemark) {
185-
// If we have ORE use the PassName that was set up with ORE. DEBUG_TYPE
191+
if (emitRemark || shouldEmitDebug) {
192+
auto r = remarkBuilder();
193+
if (shouldEmitDebug)
194+
emitDebug(r);
195+
if (emitRemark) {
196+
// If we have an Emitter use the PassName that was set up. DEBUG_TYPE
186197
// may be different if a pass is calling other modules.
187-
R.setPassName(ORE->PassName);
188-
ORE->emit(R);
198+
r.setPassName(emitter->passName);
199+
emitter->emit(r);
189200
}
190201
}
191202
}
@@ -195,10 +206,10 @@ class Emitter {
195206
OptRemark::Emitter::emitOrDebug(DEBUG_TYPE, __VA_ARGS__)
196207

197208
template <> inline bool Emitter::isEnabled<RemarkMissed>() {
198-
return MissedEnabled;
209+
return missedEnabled;
199210
}
200211
template <> inline bool Emitter::isEnabled<RemarkPassed>() {
201-
return PassedEnabled;
212+
return passedEnabled;
202213
}
203214
} // namespace OptRemark
204215
} // namespace swift

include/swift/SIL/SILModule.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class SILUndef;
6767
class SourceFile;
6868
class SerializedSILLoader;
6969
class SILFunctionBuilder;
70+
class SILRemarkStreamer;
7071

7172
namespace Lowering {
7273
class SILGenModule;
@@ -232,13 +233,11 @@ class SILModule {
232233
// The list of SILProperties in the module.
233234
PropertyListType properties;
234235

235-
/// This is the underlying raw stream of OptRecordStream.
236-
///
237-
/// It is also owned by SILModule in order to keep their lifetime in sync.
238-
std::unique_ptr<llvm::raw_ostream> OptRecordRawStream;
236+
/// The remark output stream used to record SIL remarks to a file.
237+
std::unique_ptr<llvm::raw_fd_ostream> silRemarkStream;
239238

240-
/// If non-null, the YAML file where remarks should be recorded.
241-
std::unique_ptr<llvm::yaml::Output> OptRecordStream;
239+
/// The remark streamer used to serialize SIL remarks to a file.
240+
std::unique_ptr<swift::SILRemarkStreamer> silRemarkStreamer;
242241

243242
/// This is a cache of intrinsic Function declarations to numeric ID mappings.
244243
llvm::DenseMap<Identifier, IntrinsicInfo> IntrinsicIDCache;
@@ -524,9 +523,12 @@ class SILModule {
524523
return coverageMaps;
525524
}
526525

527-
llvm::yaml::Output *getOptRecordStream() { return OptRecordStream.get(); }
528-
void setOptRecordStream(std::unique_ptr<llvm::yaml::Output> &&Stream,
529-
std::unique_ptr<llvm::raw_ostream> &&RawStream);
526+
swift::SILRemarkStreamer *getSILRemarkStreamer() {
527+
return silRemarkStreamer.get();
528+
}
529+
void setSILRemarkStreamer(
530+
std::unique_ptr<llvm::raw_fd_ostream> &&remarkStream,
531+
std::unique_ptr<swift::SILRemarkStreamer> &&remarkStreamer);
530532

531533
// This is currently limited to VarDecl because the visibility of global
532534
// variables and class properties is straightforward, while the visibility of

0 commit comments

Comments
 (0)