Skip to content

Commit 5d37354

Browse files
authored
Merge pull request swiftlang#33597 from gottesmm/pr-d13e5a398f892c94f54a62e0c4bd6d2e871ff7d2
[opt-remark] Handle inline locations correctly.
2 parents 9ce8250 + 7aac681 commit 5d37354

File tree

4 files changed

+83
-21
lines changed

4 files changed

+83
-21
lines changed

include/swift/SIL/SILDebugScope.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,28 @@ class SILDebugScope : public SILAllocated<SILDebugScope> {
6666
/// into.
6767
SILFunction *getParentFunction() const;
6868

69+
/// If this is a debug scope associated with an inlined call site, return the
70+
/// SILLocation associated with the call site resulting from the final
71+
/// inlining.
72+
///
73+
/// This allows one to emit diagnostics based off of inlined code's final
74+
/// location in the function that was inlined into.
75+
SILLocation getOutermostInlineLocation() const {
76+
if (!InlinedCallSite)
77+
return SILLocation::invalid();
78+
79+
auto *scope = this;
80+
do {
81+
scope = scope->InlinedCallSite;
82+
} while (scope->InlinedCallSite);
83+
84+
SILLocation callSite = scope->Loc;
85+
if (callSite.isNull() || !callSite.isASTNode())
86+
return SILLocation::invalid();
87+
88+
return callSite;
89+
}
90+
6991
void print(SourceManager &SM, llvm::raw_ostream &OS = llvm::errs(),
7092
unsigned Indent = 0) const;
7193

lib/SIL/Utils/OptimizationRemark.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ static SourceLoc inferOptRemarkSearchForwards(SILInstruction &i) {
152152
for (auto &inst :
153153
llvm::make_range(std::next(i.getIterator()), i.getParent()->end())) {
154154
auto newLoc = inst.getLoc().getSourceLoc();
155+
if (auto inlinedLoc = inst.getDebugScope()->getOutermostInlineLocation())
156+
newLoc = inlinedLoc.getSourceLoc();
155157
if (newLoc.isValid())
156158
return newLoc;
157159
}
@@ -167,7 +169,9 @@ static SourceLoc inferOptRemarkSearchBackwards(SILInstruction &i) {
167169
for (auto &inst : llvm::make_range(std::next(i.getReverseIterator()),
168170
i.getParent()->rend())) {
169171
auto loc = inst.getLoc();
170-
if (!bool(loc))
172+
if (auto inlinedLoc = inst.getDebugScope()->getOutermostInlineLocation())
173+
loc = inlinedLoc;
174+
if (!loc.getSourceLoc().isValid())
171175
continue;
172176

173177
auto range = loc.getSourceRange();
@@ -180,31 +184,35 @@ static SourceLoc inferOptRemarkSearchBackwards(SILInstruction &i) {
180184

181185
SourceLoc swift::OptRemark::inferOptRemarkSourceLoc(
182186
SILInstruction &i, SourceLocInferenceBehavior inferBehavior) {
183-
auto loc = i.getLoc().getSourceLoc();
184-
185-
// Do a quick check if we already have a valid loc. In such a case, just
186-
// return. Otherwise, we try to infer using one of our heuristics below.
187-
if (loc.isValid())
188-
return loc;
187+
// Do a quick check if we already have a valid loc and it isnt an inline
188+
// loc. In such a case, just return. Otherwise, we try to infer using one of
189+
// our heuristics below.
190+
auto loc = i.getLoc();
191+
if (loc.getSourceLoc().isValid()) {
192+
// Before we do anything, if we do not have an inlined call site, just
193+
// return our loc.
194+
if (!i.getDebugScope() || !i.getDebugScope()->InlinedCallSite)
195+
return loc.getSourceLoc();
196+
}
189197

190198
// Otherwise, try to handle the individual behavior cases, returning loc at
191199
// the end of each case (its invalid, so it will get ignored). If loc is not
192200
// returned, we hit an assert at the end to make it easy to identify a case
193201
// was missed.
194202
switch (inferBehavior) {
195203
case SourceLocInferenceBehavior::None:
196-
return loc;
204+
return SourceLoc();
197205
case SourceLocInferenceBehavior::ForwardScanOnly: {
198206
SourceLoc newLoc = inferOptRemarkSearchForwards(i);
199207
if (newLoc.isValid())
200208
return newLoc;
201-
return loc;
209+
return SourceLoc();
202210
}
203211
case SourceLocInferenceBehavior::BackwardScanOnly: {
204212
SourceLoc newLoc = inferOptRemarkSearchBackwards(i);
205213
if (newLoc.isValid())
206214
return newLoc;
207-
return loc;
215+
return SourceLoc();
208216
}
209217
case SourceLocInferenceBehavior::ForwardThenBackward: {
210218
SourceLoc newLoc = inferOptRemarkSearchForwards(i);
@@ -213,7 +221,7 @@ SourceLoc swift::OptRemark::inferOptRemarkSourceLoc(
213221
newLoc = inferOptRemarkSearchBackwards(i);
214222
if (newLoc.isValid())
215223
return newLoc;
216-
return loc;
224+
return SourceLoc();
217225
}
218226
case SourceLocInferenceBehavior::BackwardThenForward: {
219227
SourceLoc newLoc = inferOptRemarkSearchBackwards(i);
@@ -222,7 +230,7 @@ SourceLoc swift::OptRemark::inferOptRemarkSourceLoc(
222230
newLoc = inferOptRemarkSearchForwards(i);
223231
if (newLoc.isValid())
224232
return newLoc;
225-
return loc;
233+
return SourceLoc();
226234
}
227235
}
228236

lib/SILOptimizer/Transforms/OptRemarkGenerator.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static llvm::cl::opt<bool> ForceVisitImplicitAutogeneratedFunctions(
4242
llvm::cl::init(false));
4343

4444
//===----------------------------------------------------------------------===//
45-
// Utility
45+
// Value To Decl Inferrer
4646
//===----------------------------------------------------------------------===//
4747

4848
namespace {
@@ -176,15 +176,21 @@ bool ValueToDeclInferrer::infer(
176176
continue;
177177

178178
if (auto *dvi = dyn_cast<DebugValueInst>(use->getUser())) {
179-
if (auto *decl = dvi->getDecl()) {
180-
std::string msg;
181-
{
182-
llvm::raw_string_ostream stream(msg);
183-
printNote(stream, decl);
179+
// Check if our debug_value has a decl and was not inlined into the
180+
// current function.
181+
if (auto *scope = dvi->getDebugScope()) {
182+
if (!scope->InlinedCallSite) {
183+
if (auto *decl = dvi->getDecl()) {
184+
std::string msg;
185+
{
186+
llvm::raw_string_ostream stream(msg);
187+
printNote(stream, decl);
188+
}
189+
resultingInferredDecls.push_back(
190+
Argument({keyKind, "InferredValue"}, std::move(msg), decl));
191+
foundDeclFromUse = true;
192+
}
184193
}
185-
resultingInferredDecls.push_back(
186-
Argument({keyKind, "InferredValue"}, std::move(msg), decl));
187-
foundDeclFromUse = true;
188194
}
189195
}
190196
}

test/SILOptimizer/opt-remark-generator.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,29 @@ func inoutKlassQuestionCastArgument2(x: inout Klass?) -> SubKlass? {
231231
return x as? SubKlass // expected-remark {{retain of type 'Klass'}}
232232
// expected-note @-2 {{of 'x.some'}}
233233
}
234+
235+
// We should have 1x rr remark here on calleeX for storing it into the array to
236+
// print. Release is from the array. We don't pattern match it due to the actual
237+
// underlying Array type name changing under the hood in between platforms.
238+
@inline(__always)
239+
func alwaysInlineCallee(_ calleeX: Klass) {
240+
print(calleeX) // expected-remark @:5 {{retain of type 'Klass'}}
241+
// expected-note @-2:27 {{of 'calleeX'}}
242+
// expected-remark @-2:18 {{release of type}}
243+
}
244+
245+
// We should have 3x rr remarks here on callerX and none on calleeX. All of the
246+
// releases are for the temporary array that we pass into print.
247+
//
248+
// TODO: Should we print out as notes the whole inlined call stack?
249+
func alwaysInlineCaller(_ callerX: Klass) {
250+
alwaysInlineCallee(callerX) // expected-remark @:5 {{retain of type 'Klass'}}
251+
// expected-note @-2:27 {{of 'callerX'}}
252+
// expected-remark @-2:31 {{release of type}}
253+
print(callerX) // expected-remark @:5 {{retain of type 'Klass'}}
254+
// expected-note @-5:27 {{of 'callerX'}}
255+
// expected-remark @-2:18 {{release of type}}
256+
alwaysInlineCallee(callerX) // expected-remark @:5 {{retain of type 'Klass'}}
257+
// expected-note @-8:27 {{of 'callerX'}}
258+
// expected-remark @-2:31 {{release of type}}
259+
}

0 commit comments

Comments
 (0)