Skip to content

Commit 8750b40

Browse files
committed
[opt-remark] Extract out DebugValue inference from a Value's uses into a helper struct to enable code reuse.
I am doing this so I can use the same code with alloc_stack.
1 parent f6e71d4 commit 8750b40

File tree

1 file changed

+84
-61
lines changed

1 file changed

+84
-61
lines changed

lib/SILOptimizer/Transforms/OptRemarkGenerator.cpp

Lines changed: 84 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,87 @@ static bool hasNonInlinedDebugScope(SILInstruction *i) {
217217
return false;
218218
}
219219

220+
namespace {
221+
222+
/// A helper struct that attempts to infer the decl associated with a value from
223+
/// one of its uses. It does this by searching the def-use graph locally for
224+
/// debug_value and debug_value_addr instructions.
225+
struct ValueUseToDeclInferrer {
226+
using Argument = ValueToDeclInferrer::Argument;
227+
using ArgumentKeyKind = ValueToDeclInferrer::ArgumentKeyKind;
228+
229+
SmallPtrSet<swift::SILInstruction *, 8> visitedDebugValueInsts;
230+
ValueToDeclInferrer &object;
231+
ArgumentKeyKind keyKind;
232+
SmallVectorImpl<Argument> &resultingInferredDecls;
233+
234+
bool findDecls(Operand *use, SILValue value);
235+
};
236+
237+
} // anonymous namespace
238+
239+
bool ValueUseToDeclInferrer::findDecls(Operand *use, SILValue value) {
240+
// Skip type dependent operands.
241+
if (use->isTypeDependent())
242+
return false;
243+
244+
// Then see if we have a debug_value that is associated with a non-inlined
245+
// debug scope. Such an instruction is an instruction that is from the
246+
// current function.
247+
auto *dvi = dyn_cast<DebugValueInst>(use->getUser());
248+
if (!dvi)
249+
return false;
250+
251+
if (!hasNonInlinedDebugScope(dvi))
252+
return false;
253+
254+
// See if we have already inferred this debug_value as a potential source
255+
// for this instruction. In such a case, just return.
256+
if (!visitedDebugValueInsts.insert(dvi).second)
257+
return false;
258+
259+
if (auto *decl = dvi->getDecl()) {
260+
std::string msg;
261+
{
262+
llvm::raw_string_ostream stream(msg);
263+
// If we are not a top level use, we must be a rc-identical transitive
264+
// use. In such a case, we just print out the rc identical value
265+
// without a projection path. This is because we now have a better
266+
// name and the name is rc-identical to whatever was at the end of the
267+
// projection path but is not at the end of that projection path.
268+
object.printNote(stream, decl,
269+
use->get() == value /*print projection path*/);
270+
}
271+
resultingInferredDecls.emplace_back(
272+
OptRemark::ArgumentKey{keyKind, "InferredValue"}, std::move(msg), decl);
273+
return true;
274+
}
275+
276+
// If we did not have a decl, see if we were asked for testing
277+
// purposes to use SILDebugInfo to create a placeholder inferred
278+
// value.
279+
if (!DecllessDebugValueUseSILDebugInfo)
280+
return false;
281+
282+
auto varInfo = dvi->getVarInfo();
283+
if (!varInfo)
284+
return false;
285+
286+
auto name = varInfo->Name;
287+
if (name.empty())
288+
return false;
289+
290+
std::string msg;
291+
{
292+
llvm::raw_string_ostream stream(msg);
293+
object.printNote(stream, name,
294+
use->get() == value /*print projection path*/);
295+
}
296+
resultingInferredDecls.push_back(
297+
Argument({keyKind, "InferredValue"}, std::move(msg), dvi->getLoc()));
298+
return true;
299+
}
300+
220301
bool ValueToDeclInferrer::infer(
221302
ArgumentKeyKind keyKind, SILValue value,
222303
SmallVectorImpl<Argument> &resultingInferredDecls,
@@ -225,7 +306,8 @@ bool ValueToDeclInferrer::infer(
225306
SWIFT_DEFER {
226307
accessPath.clear();
227308
};
228-
SmallPtrSet<SILInstruction *, 8> visitedDebugValueInsts;
309+
ValueUseToDeclInferrer valueUseInferrer{
310+
{}, *this, keyKind, resultingInferredDecls};
229311
bool foundSingleRefElementAddr = false;
230312

231313
// This is a linear IR traversal using a 'falling while loop'. That means
@@ -308,66 +390,7 @@ bool ValueToDeclInferrer::infer(
308390
// instance, if we FSOed.
309391
bool foundDeclFromUse = false;
310392
rcfi.visitRCUses(value, [&](Operand *use) {
311-
// Skip type dependent uses.
312-
if (use->isTypeDependent())
313-
return;
314-
315-
// Then see if we have a debug_value that is associated with a non-inlined
316-
// debug scope. Such an instruction is an instruction that is from the
317-
// current function.
318-
auto *dvi = dyn_cast<DebugValueInst>(use->getUser());
319-
if (!dvi)
320-
return;
321-
322-
if (!hasNonInlinedDebugScope(dvi))
323-
return;
324-
325-
// See if we have already inferred this debug_value as a potential source
326-
// for this instruction. In such a case, just return.
327-
if (!visitedDebugValueInsts.insert(dvi).second)
328-
return;
329-
330-
if (auto *decl = dvi->getDecl()) {
331-
std::string msg;
332-
{
333-
llvm::raw_string_ostream stream(msg);
334-
// If we are not a top level use, we must be a rc-identical transitive
335-
// use. In such a case, we just print out the rc identical value
336-
// without a projection path. This is because we now have a better
337-
// name and the name is rc-identical to whatever was at the end of the
338-
// projection path but is not at the end of that projection path.
339-
printNote(stream, decl,
340-
use->get() == value /*print projection path*/);
341-
}
342-
resultingInferredDecls.emplace_back(
343-
OptRemark::ArgumentKey{keyKind, "InferredValue"}, std::move(msg),
344-
decl);
345-
foundDeclFromUse = true;
346-
return;
347-
}
348-
349-
// If we did not have a decl, see if we were asked for testing
350-
// purposes to use SILDebugInfo to create a placeholder inferred
351-
// value.
352-
if (!DecllessDebugValueUseSILDebugInfo)
353-
return;
354-
355-
auto varInfo = dvi->getVarInfo();
356-
if (!varInfo)
357-
return;
358-
359-
auto name = varInfo->Name;
360-
if (name.empty())
361-
return;
362-
363-
std::string msg;
364-
{
365-
llvm::raw_string_ostream stream(msg);
366-
printNote(stream, name, use->get() == value /*print projection path*/);
367-
}
368-
resultingInferredDecls.push_back(
369-
Argument({keyKind, "InferredValue"}, std::move(msg), dvi->getLoc()));
370-
foundDeclFromUse = true;
393+
foundDeclFromUse |= valueUseInferrer.findDecls(use, value);
371394
});
372395

373396
// At this point, we could not infer any argument. See if we can look up the

0 commit comments

Comments
 (0)