Skip to content

Commit deb404c

Browse files
authored
[Outlining] Improve logging (#7464)
Improve the quality of debug logs during outlining by: - reorder logs to occur before corresponding asserts - rename the debug logging macro used in Outlining.cpp so its not defined twice - add a parameter to function outline to thread the data needed for logging - add a parameters to struct OutliningSequence to connect the sequence back to its location in the stringified binary
1 parent 2172402 commit deb404c

File tree

2 files changed

+118
-49
lines changed

2 files changed

+118
-49
lines changed

src/passes/Outlining.cpp

Lines changed: 118 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
#define OUTLINING_DEBUG 0
2525

2626
#if OUTLINING_DEBUG
27-
#define DBG(statement) statement
27+
#define ODBG(statement) statement
2828
#else
29-
#define DBG(statement)
29+
#define ODBG(statement)
3030
#endif
3131

3232
// Check a Result or MaybeResult for error and call Fatal() if the error exists.
@@ -37,6 +37,34 @@
3737

3838
namespace wasm {
3939

40+
struct OutliningSequence {
41+
unsigned startIdx;
42+
unsigned endIdx;
43+
Name func;
44+
bool endsTypeUnreachable;
45+
#if OUTLINING_DEBUG
46+
unsigned programIdx;
47+
#endif
48+
49+
OutliningSequence(unsigned startIdx,
50+
unsigned endIdx,
51+
Name func,
52+
bool endsTypeUnreachable
53+
#if OUTLINING_DEBUG
54+
,
55+
unsigned programIdx
56+
#endif
57+
)
58+
: startIdx(startIdx), endIdx(endIdx), func(func),
59+
endsTypeUnreachable(endsTypeUnreachable)
60+
#if OUTLINING_DEBUG
61+
,
62+
programIdx(programIdx)
63+
#endif
64+
{
65+
}
66+
};
67+
4068
// Instances of this walker are intended to walk a function at a time, at the
4169
// behest of the owner of the instance.
4270
struct ReconstructStringifyWalker
@@ -45,8 +73,8 @@ struct ReconstructStringifyWalker
4573
ReconstructStringifyWalker(Module* wasm, Function* func)
4674
: existingBuilder(*wasm), outlinedBuilder(*wasm), func(func) {
4775
this->setModule(wasm);
48-
DBG(std::cerr << "\nexistingBuilder: " << &existingBuilder
49-
<< " outlinedBuilder: " << &outlinedBuilder << "\n");
76+
ODBG(std::cerr << "\nexistingBuilder: " << &existingBuilder
77+
<< " outlinedBuilder: " << &outlinedBuilder << "\n");
5078
}
5179

5280
// As we reconstruct the IR during outlining, we need to know what
@@ -91,25 +119,26 @@ struct ReconstructStringifyWalker
91119
// starting a new function, as that resets the counters back to 0.
92120
instrCounter++;
93121

94-
DBG(std::string desc);
122+
ODBG(std::string desc);
95123
if (auto curr = reason.getBlockStart()) {
124+
ODBG(desc = "Block Start at ");
96125
ASSERT_OK(existingBuilder.visitBlockStart(curr->block));
97-
DBG(desc = "Block Start at ");
98126
} else if (auto curr = reason.getIfStart()) {
99127
// IR builder needs the condition of the If pushed onto the builder before
100128
// visitIfStart(), which will expect to be able to pop the condition.
101129
// This is always okay to do because the correct condition was installed
102130
// onto the If when the outer scope was visited.
103131
existingBuilder.push(curr->iff->condition);
132+
ODBG(desc = "If Start at ");
104133
ASSERT_OK(existingBuilder.visitIfStart(curr->iff));
105-
DBG(desc = "If Start at ");
106134
} else if (reason.getElseStart()) {
135+
ODBG(desc = "Else Start at ");
107136
ASSERT_OK(existingBuilder.visitElse());
108-
DBG(desc = "Else Start at ");
109137
} else if (auto curr = reason.getLoopStart()) {
138+
ODBG(desc = "Loop Start at ");
110139
ASSERT_OK(existingBuilder.visitLoopStart(curr->loop));
111-
DBG(desc = "Loop Start at ");
112140
} else if (reason.getEnd()) {
141+
ODBG(desc = "End at ");
113142
ASSERT_OK(existingBuilder.visitEnd());
114143
// Reset the function in case we just ended the function scope.
115144
existingBuilder.setFunction(func);
@@ -122,12 +151,11 @@ struct ReconstructStringifyWalker
122151
// its expressions off the stack, so we must call build() after visitEnd()
123152
// to clear the internal stack IRBuilder manages.
124153
ASSERT_OK(existingBuilder.build());
125-
DBG(desc = "End at ");
126154
} else {
127-
DBG(desc = "addUniqueSymbol for unimplemented control flow ");
155+
ODBG(desc = "addUniqueSymbol for unimplemented control flow ");
128156
WASM_UNREACHABLE("unimplemented control flow");
129157
}
130-
DBG(printAddUniqueSymbol(desc));
158+
ODBG(printAddUniqueSymbol(desc));
131159
}
132160

133161
void visitExpression(Expression* curr) {
@@ -151,7 +179,7 @@ struct ReconstructStringifyWalker
151179
ASSERT_OK(builder->visit(curr));
152180
}
153181
}
154-
DBG(printVisitExpression(curr));
182+
ODBG(printVisitExpression(curr));
155183

156184
if (state == InSeq || state == InSkipSeq) {
157185
maybeEndSeq();
@@ -165,9 +193,9 @@ struct ReconstructStringifyWalker
165193
instrCounter = 0;
166194
seqCounter = 0;
167195
state = NotInSeq;
168-
DBG(std::cerr << "\n"
169-
<< "Func Start to $" << func->name << " at "
170-
<< &existingBuilder << "\n");
196+
ODBG(std::cerr << "\n"
197+
<< "Func Start to $" << func->name << " at "
198+
<< &existingBuilder << "\n");
171199
}
172200

173201
ReconstructState getCurrState() {
@@ -209,29 +237,41 @@ struct ReconstructStringifyWalker
209237
getModule()->getFunction(sequences[seqCounter].func);
210238
ASSERT_OK(outlinedBuilder.visitFunctionStart(outlinedFunc));
211239

212-
// Add a local.get instruction for every parameter of the outlined function.
213-
Signature sig = outlinedFunc->type.getSignature();
214-
for (Index i = 0; i < sig.params.size(); i++) {
215-
ASSERT_OK(outlinedBuilder.makeLocalGet(i));
216-
}
217-
218240
// Make a call from the existing function to the outlined function. This
219241
// call will replace the instructions moved to the outlined function.
242+
ODBG(std::cerr << "\nadding call " << outlinedFunc->name << " to "
243+
<< &existingBuilder << "\n");
220244
ASSERT_OK(existingBuilder.makeCall(outlinedFunc->name, false));
221-
DBG(std::cerr << "\ncreated outlined fn: " << outlinedFunc->name << "\n");
222245

223246
// If the last instruction of the outlined sequence is unreachable, insert
224247
// an unreachable instruction immediately after the call to the outlined
225248
// function. This maintains the unreachable type in the original scope
226249
// of the outlined sequence.
227250
if (sequences[seqCounter].endsTypeUnreachable) {
251+
ODBG(std::cerr << "\nadding endsUnreachable to " << &existingBuilder
252+
<< "\n");
228253
ASSERT_OK(existingBuilder.makeUnreachable());
229254
}
255+
256+
// Add a local.get instruction for every parameter of the outlined function.
257+
Signature sig = outlinedFunc->type.getSignature();
258+
ODBG(std::cerr << outlinedFunc->name << " takes " << sig.params.size()
259+
<< " parameters\n");
260+
for (Index i = 0; i < sig.params.size(); i++) {
261+
ODBG(std::cerr << "adding local.get $" << i << " to " << &outlinedBuilder
262+
<< "\n");
263+
ASSERT_OK(outlinedBuilder.makeLocalGet(i));
264+
}
230265
}
231266

232267
void transitionToInSkipSeq() {
233268
Function* outlinedFunc =
234269
getModule()->getFunction(sequences[seqCounter].func);
270+
ODBG(std::cerr << "\nstarting to skip instructions "
271+
<< sequences[seqCounter].startIdx << " - "
272+
<< sequences[seqCounter].endIdx - 1 << " to "
273+
<< sequences[seqCounter].func
274+
<< " and adding call() instead\n");
235275
ASSERT_OK(existingBuilder.makeCall(outlinedFunc->name, false));
236276
// If the last instruction of the outlined sequence is unreachable, insert
237277
// an unreachable instruction immediately after the call to the outlined
@@ -240,11 +280,6 @@ struct ReconstructStringifyWalker
240280
if (sequences[seqCounter].endsTypeUnreachable) {
241281
ASSERT_OK(existingBuilder.makeUnreachable());
242282
}
243-
DBG(std::cerr << "\nstarting to skip instructions "
244-
<< sequences[seqCounter].startIdx << " - "
245-
<< sequences[seqCounter].endIdx - 1 << " to "
246-
<< sequences[seqCounter].func
247-
<< " and adding call() instead\n");
248283
}
249284

250285
void maybeEndSeq() {
@@ -255,12 +290,12 @@ struct ReconstructStringifyWalker
255290
}
256291

257292
void transitionToNotInSeq() {
258-
DBG(std::cerr << "End of sequence ");
293+
ODBG(std::cerr << "End of sequence ");
259294
if (state == InSeq) {
295+
ODBG(std::cerr << "to " << &outlinedBuilder);
260296
ASSERT_OK(outlinedBuilder.visitEnd());
261-
DBG(std::cerr << "to " << &outlinedBuilder);
262297
}
263-
DBG(std::cerr << "\n\n");
298+
ODBG(std::cerr << "\n\n");
264299
// Completed a sequence so increase the seqCounter and reset the state.
265300
seqCounter++;
266301
}
@@ -288,11 +323,11 @@ struct Outlining : public Pass {
288323
HashStringifyWalker stringify;
289324
// Walk the module and create a "string representation" of the program.
290325
stringify.walkModule(module);
326+
ODBG(printHashString(stringify.hashString, stringify.exprs));
291327
// Collect all of the substrings of the string representation that appear
292328
// more than once in the program.
293329
auto substrings =
294330
StringifyProcessor::repeatSubstrings(stringify.hashString);
295-
DBG(printHashString(stringify.hashString, stringify.exprs));
296331
// Remove substrings that are substrings of longer repeat substrings.
297332
substrings = StringifyProcessor::dedupe(substrings);
298333
// Remove substrings with overlapping indices.
@@ -317,7 +352,13 @@ struct Outlining : public Pass {
317352
// are relative to the enclosing function while substrings have indices
318353
// relative to the entire program.
319354
auto sequences = makeSequences(module, substrings, stringify);
320-
outline(module, sequences);
355+
outline(module,
356+
sequences
357+
#if OUTLINING_DEBUG
358+
,
359+
stringify
360+
#endif
361+
);
321362
// Position the outlined functions first in the functions vector to make
322363
// the outlining lit tests far more readable.
323364
moveOutlinedFunctions(module, substrings.size());
@@ -371,14 +412,25 @@ struct Outlining : public Pass {
371412
relativeIdx + substring.Length,
372413
func,
373414
stringify.exprs[seqIdx + substring.Length - 1]->type ==
374-
Type::unreachable);
415+
Type::unreachable
416+
#if OUTLINING_DEBUG
417+
,
418+
seqIdx
419+
#endif
420+
);
375421
seqByFunc[existingFunc].push_back(seq);
376422
}
377423
}
378424
return seqByFunc;
379425
}
380426

381-
void outline(Module* module, Sequences seqByFunc) {
427+
void outline(Module* module,
428+
Sequences seqByFunc
429+
#if OUTLINING_DEBUG
430+
,
431+
const HashStringifyWalker& stringify
432+
#endif
433+
) {
382434
// TODO: Make this a function-parallel sub-pass.
383435
std::vector<Name> keys(seqByFunc.size());
384436
std::transform(seqByFunc.begin(),
@@ -398,6 +450,11 @@ struct Outlining : public Pass {
398450
});
399451
ReconstructStringifyWalker reconstruct(module, module->getFunction(func));
400452
reconstruct.sequences = std::move(seqByFunc[func]);
453+
ODBG(printReconstruct(module,
454+
stringify.hashString,
455+
stringify.exprs,
456+
func,
457+
reconstruct.sequences));
401458
reconstruct.doWalkFunction(module->getFunction(func));
402459
}
403460
}
@@ -433,6 +490,32 @@ struct Outlining : public Pass {
433490
}
434491
}
435492
}
493+
void printReconstruct(Module* module,
494+
const std::vector<uint32_t>& hashString,
495+
const std::vector<Expression*>& exprs,
496+
Name existingFunc,
497+
const std::vector<OutliningSequence>& seqs) {
498+
std::cerr << "\n\nReconstructing existing fn: " << existingFunc << "\n";
499+
std::cerr << "moving sequences: "
500+
<< "\n";
501+
for (auto& seq : seqs) {
502+
for (Index idx = seq.programIdx;
503+
idx < seq.programIdx + (seq.endIdx - seq.startIdx);
504+
idx++) {
505+
Expression* expr = exprs[idx];
506+
if (expr == nullptr) {
507+
std::cerr << "unique symbol\n";
508+
} else {
509+
std::cerr << idx << " - " << hashString[idx] << " - " << seq.startIdx
510+
<< " : " << ShallowExpression{expr} << "\n";
511+
}
512+
}
513+
std::cerr << "to outlined function: " << seq.func << "\n";
514+
auto outlinedFunction = module->getFunction(seq.func);
515+
std::cerr << "with signature: " << outlinedFunction->type.toString()
516+
<< "\n";
517+
}
518+
}
436519
#endif
437520
};
438521

src/passes/stringify-walker.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -254,20 +254,6 @@ struct HashStringifyWalker : public StringifyWalker<HashStringifyWalker> {
254254
std::map<uint32_t, Name> idxToFuncName;
255255
};
256256

257-
struct OutliningSequence {
258-
unsigned startIdx;
259-
unsigned endIdx;
260-
Name func;
261-
bool endsTypeUnreachable;
262-
263-
OutliningSequence(unsigned startIdx,
264-
unsigned endIdx,
265-
Name func,
266-
bool endsTypeUnreachable)
267-
: startIdx(startIdx), endIdx(endIdx), func(func),
268-
endsTypeUnreachable(endsTypeUnreachable) {}
269-
};
270-
271257
using Substrings = std::vector<SuffixTree::RepeatedSubstring>;
272258

273259
// Functions that filter vectors of SuffixTree::RepeatedSubstring

0 commit comments

Comments
 (0)