Skip to content

Commit 1227693

Browse files
committed
[opt-remark-gen] Teach OptRemarkGen how to emit diagnostics about exclusivity.
For example, now we get the following diagnostic on globals: public func getGlobal() -> Klass { return global // expected-remark @:5 {{retain of type 'Klass'}} // expected-note @-5:12 {{of 'global'}} + // expected-remark @-2:12 {{begin exclusive access to value of type 'Klass'}} + // expected-note @-7:12 {{of 'global'}} + // expected-remark @-4 {{end exclusive access to value of type 'Klass'}} + // expected-note @-9:12 {{of 'global'}} + } and for classes when we can't eliminate the access: +func simpleInOut() -> Klass { + let x = Klass() // expected-remark @:13 {{heap allocated ref of type 'Klass'}} + // expected-note @-1:9 {{of 'x'}} + simpleInOutUser(&x.next) // expected-remark @:5 {{begin exclusive access to value of type 'Optional<Klass>'}} + // expected-note @-3:9 {{of 'x.next'}} + // expected-remark @-2:28 {{end exclusive access to value of type 'Optional<Klass>'}} + // expected-note @-5:9 {{of 'x.next'}} + return x +}
1 parent 209878f commit 1227693

File tree

6 files changed

+220
-42
lines changed

6 files changed

+220
-42
lines changed

include/swift/Basic/SourceLoc.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ class SourceLoc {
4444

4545
bool isValid() const { return Value.isValid(); }
4646
bool isInvalid() const { return !isValid(); }
47-
47+
48+
/// An explicit bool operator so one can check if a SourceLoc is valid in an
49+
/// if statement:
50+
///
51+
/// if (auto x = getSourceLoc()) { ... }
52+
explicit operator bool() const { return isValid(); }
53+
4854
bool operator==(const SourceLoc &RHS) const { return RHS.Value == Value; }
4955
bool operator!=(const SourceLoc &RHS) const { return !operator==(RHS); }
5056

@@ -107,6 +113,12 @@ class SourceRange {
107113
bool isValid() const { return Start.isValid(); }
108114
bool isInvalid() const { return !isValid(); }
109115

116+
/// An explicit bool operator so one can check if a SourceRange is valid in an
117+
/// if statement:
118+
///
119+
/// if (auto x = getSourceRange()) { ... }
120+
explicit operator bool() const { return isValid(); }
121+
110122
/// Extend this SourceRange to the smallest continuous SourceRange that
111123
/// includes both this range and the other one.
112124
void widen(SourceRange Other);

include/swift/SIL/OptimizationRemark.h

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ struct IndentDebug {
137137
unsigned width;
138138
};
139139

140+
enum class SourceLocPresentationKind {
141+
StartRange,
142+
EndRange,
143+
};
144+
140145
enum class SourceLocInferenceBehavior : unsigned {
141146
None = 0,
142147
ForwardScan = 0x1,
@@ -165,7 +170,9 @@ inline SourceLocInferenceBehavior operator&(SourceLocInferenceBehavior lhs,
165170
/// surrounding code. If we can not find any surrounding code, we return an
166171
/// invalid SourceLoc.
167172
SourceLoc inferOptRemarkSourceLoc(SILInstruction &i,
168-
SourceLocInferenceBehavior inferBehavior);
173+
SourceLocInferenceBehavior inferBehavior,
174+
SourceLocPresentationKind presentationKind =
175+
SourceLocPresentationKind::StartRange);
169176

170177
/// The base class for remarks. This can be created by optimization passed to
171178
/// report successful and unsuccessful optimizations. CRTP is used to preserve
@@ -197,9 +204,11 @@ class Remark {
197204

198205
protected:
199206
Remark(StringRef identifier, SILInstruction &i,
200-
SourceLocInferenceBehavior inferenceBehavior)
207+
SourceLocInferenceBehavior inferenceBehavior,
208+
SourceLocPresentationKind locPresentationKind)
201209
: identifier((Twine("sil.") + identifier).str()),
202-
location(inferOptRemarkSourceLoc(i, inferenceBehavior)),
210+
location(
211+
inferOptRemarkSourceLoc(i, inferenceBehavior, locPresentationKind)),
203212
function(i.getParent()->getParent()),
204213
demangledFunctionName(Demangle::demangleSymbolAsString(
205214
function->getName(),
@@ -238,18 +247,30 @@ class Remark {
238247
/// Remark to report a successful optimization.
239248
struct RemarkPassed : public Remark<RemarkPassed> {
240249
RemarkPassed(StringRef id, SILInstruction &i)
241-
: Remark(id, i, SourceLocInferenceBehavior::None) {}
250+
: Remark(id, i, SourceLocInferenceBehavior::None,
251+
SourceLocPresentationKind::StartRange) {}
242252
RemarkPassed(StringRef id, SILInstruction &i,
243253
SourceLocInferenceBehavior inferenceBehavior)
244-
: Remark(id, i, inferenceBehavior) {}
254+
: Remark(id, i, inferenceBehavior,
255+
SourceLocPresentationKind::StartRange) {}
256+
RemarkPassed(StringRef id, SILInstruction &i,
257+
SourceLocInferenceBehavior inferenceBehavior,
258+
SourceLocPresentationKind locPresentationKind)
259+
: Remark(id, i, inferenceBehavior, locPresentationKind) {}
245260
};
246261
/// Remark to report a unsuccessful optimization.
247262
struct RemarkMissed : public Remark<RemarkMissed> {
248263
RemarkMissed(StringRef id, SILInstruction &i)
249-
: Remark(id, i, SourceLocInferenceBehavior::None) {}
264+
: Remark(id, i, SourceLocInferenceBehavior::None,
265+
SourceLocPresentationKind::StartRange) {}
250266
RemarkMissed(StringRef id, SILInstruction &i,
251267
SourceLocInferenceBehavior inferenceBehavior)
252-
: Remark(id, i, inferenceBehavior) {}
268+
: Remark(id, i, inferenceBehavior,
269+
SourceLocPresentationKind::StartRange) {}
270+
RemarkMissed(StringRef id, SILInstruction &i,
271+
SourceLocInferenceBehavior inferenceBehavior,
272+
SourceLocPresentationKind locPresentationKind)
273+
: Remark(id, i, inferenceBehavior, locPresentationKind) {}
253274
};
254275

255276
/// Used to emit the remarks. Passes reporting remarks should create an

lib/SIL/Utils/OptimizationRemark.cpp

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
//
1717
//===----------------------------------------------------------------------===//
1818

19+
#define DEBUG_TYPE "sil-opt-remarks"
20+
1921
#include "swift/SIL/OptimizationRemark.h"
2022
#include "swift/AST/DiagnosticEngine.h"
2123
#include "swift/AST/DiagnosticsSIL.h"
@@ -30,6 +32,7 @@
3032
#include "swift/SIL/SILRemarkStreamer.h"
3133
#include "llvm/ADT/StringExtras.h"
3234
#include "llvm/Support/CommandLine.h"
35+
#include "llvm/Support/Debug.h"
3336
#include "llvm/Support/raw_ostream.h"
3437

3538
using namespace swift;
@@ -145,15 +148,29 @@ Emitter::Emitter(StringRef passName, SILFunction &fn)
145148
fn.getASTContext().LangOpts.OptimizationRemarkMissedPattern->match(
146149
passName))) {}
147150

151+
static SourceLoc getLocForPresentation(SILLocation loc,
152+
SourceLocPresentationKind kind) {
153+
if (!loc)
154+
return SourceLoc();
155+
switch (kind) {
156+
case SourceLocPresentationKind::StartRange:
157+
return loc.getSourceLoc();
158+
case SourceLocPresentationKind::EndRange:
159+
return loc.getEndSourceLoc();
160+
}
161+
}
162+
148163
/// The user has passed us an instruction that for some reason has a source loc
149164
/// that can not be used. Search down the current block for an instruction with
150165
/// a valid source loc and use that instead.
151-
static SourceLoc inferOptRemarkSearchForwards(SILInstruction &i) {
166+
static SourceLoc
167+
inferOptRemarkSearchForwards(SILInstruction &i,
168+
SourceLocPresentationKind presentationKind) {
152169
for (auto &inst :
153170
llvm::make_range(std::next(i.getIterator()), i.getParent()->end())) {
154-
auto newLoc = inst.getLoc().getSourceLoc();
171+
auto newLoc = getLocForPresentation(inst.getLoc(), presentationKind);
155172
if (auto inlinedLoc = inst.getDebugScope()->getOutermostInlineLocation())
156-
newLoc = inlinedLoc.getSourceLoc();
173+
newLoc = getLocForPresentation(inlinedLoc, presentationKind);
157174
if (newLoc.isValid())
158175
return newLoc;
159176
}
@@ -165,18 +182,16 @@ static SourceLoc inferOptRemarkSearchForwards(SILInstruction &i) {
165182
/// that can not be used. Search up the current block for an instruction with
166183
/// a valid SILLocation and use the end SourceLoc of the SourceRange for the
167184
/// instruction.
168-
static SourceLoc inferOptRemarkSearchBackwards(SILInstruction &i) {
185+
static SourceLoc
186+
inferOptRemarkSearchBackwards(SILInstruction &i,
187+
SourceLocPresentationKind presentationKind) {
169188
for (auto &inst : llvm::make_range(std::next(i.getReverseIterator()),
170189
i.getParent()->rend())) {
171190
auto loc = inst.getLoc();
172191
if (auto inlinedLoc = inst.getDebugScope()->getOutermostInlineLocation())
173192
loc = inlinedLoc;
174-
if (!loc.getSourceLoc().isValid())
175-
continue;
176-
177-
auto range = loc.getSourceRange();
178-
if (range.isValid())
179-
return range.End;
193+
if (auto result = getLocForPresentation(loc, presentationKind))
194+
return result;
180195
}
181196

182197
return SourceLoc();
@@ -195,34 +210,56 @@ static llvm::cl::opt<bool> IgnoreAlwaysInferForTesting(
195210
// (retain, release) and other situations where we are ok with original source
196211
// locs if we are not inlined (alloc_ref, alloc_stack).
197212
SourceLoc swift::OptRemark::inferOptRemarkSourceLoc(
198-
SILInstruction &i, SourceLocInferenceBehavior inferBehavior) {
213+
SILInstruction &i, SourceLocInferenceBehavior inferBehavior,
214+
SourceLocPresentationKind presentationKind) {
215+
LLVM_DEBUG(llvm::dbgs() << "Begin infer source loc for: " << i);
199216
// If we are only supposed to infer in inline contexts, see if we have a valid
200217
// loc and if that loc is an inlined call site.
201218
auto loc = i.getLoc();
202-
if (loc.getSourceLoc().isValid() &&
203-
!(bool(inferBehavior & SourceLocInferenceBehavior::AlwaysInfer) &&
204-
!IgnoreAlwaysInferForTesting) &&
205-
!(i.getDebugScope() && i.getDebugScope()->InlinedCallSite))
206-
return loc.getSourceLoc();
219+
if (!(bool(inferBehavior & SourceLocInferenceBehavior::AlwaysInfer) &&
220+
!IgnoreAlwaysInferForTesting)) {
221+
LLVM_DEBUG(llvm::dbgs() << "Testing insts own source loc?!\n");
222+
if (loc.getSourceLoc().isValid()) {
223+
LLVM_DEBUG(llvm::dbgs() << "Found initial valid loc!\n");
224+
if (!(i.getDebugScope() && i.getDebugScope()->InlinedCallSite)) {
225+
LLVM_DEBUG(llvm::dbgs() << "Found debug scope!\n");
226+
return getLocForPresentation(loc, presentationKind);
227+
} else {
228+
LLVM_DEBUG(llvm::dbgs() << "Did not find debug scope!\n");
229+
}
230+
} else {
231+
LLVM_DEBUG(llvm::dbgs() << "Failed to find initial valid loc!\n");
232+
}
233+
}
207234

208235
if (bool(inferBehavior & SourceLocInferenceBehavior::ForwardScan)) {
209-
SourceLoc newLoc = inferOptRemarkSearchForwards(i);
210-
if (newLoc.isValid())
236+
LLVM_DEBUG(llvm::dbgs() << "Inferring Source Loc Forward!\n");
237+
SourceLoc newLoc = inferOptRemarkSearchForwards(i, presentationKind);
238+
if (newLoc.isValid()) {
239+
LLVM_DEBUG(llvm::dbgs() << "Found loc!\n");
211240
return newLoc;
241+
}
212242
}
213243

214244
if (bool(inferBehavior & SourceLocInferenceBehavior::BackwardScan)) {
215-
SourceLoc newLoc = inferOptRemarkSearchBackwards(i);
216-
if (newLoc.isValid())
245+
LLVM_DEBUG(llvm::dbgs() << "Inferring Source Loc Backwards!\n");
246+
SourceLoc newLoc = inferOptRemarkSearchBackwards(i, presentationKind);
247+
if (newLoc.isValid()) {
248+
LLVM_DEBUG(llvm::dbgs() << "Found loc!\n");
217249
return newLoc;
250+
}
218251
}
219252

220253
if (bool(inferBehavior & SourceLocInferenceBehavior::ForwardScan2nd)) {
221-
SourceLoc newLoc = inferOptRemarkSearchForwards(i);
222-
if (newLoc.isValid())
254+
LLVM_DEBUG(llvm::dbgs() << "Inferring Source Loc Forward Scan 2nd!\n");
255+
SourceLoc newLoc = inferOptRemarkSearchForwards(i, presentationKind);
256+
if (newLoc.isValid()) {
257+
LLVM_DEBUG(llvm::dbgs() << "Found loc!\n");
223258
return newLoc;
259+
}
224260
}
225261

262+
LLVM_DEBUG(llvm::dbgs() << "Failed to find good loc!\n");
226263
return SourceLoc();
227264
}
228265

0 commit comments

Comments
 (0)