Skip to content

[opt-remark-gen] Teach OptRemarkGen how to emit diagnostics about exclusivity. #36622

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion include/swift/Basic/SourceLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ class SourceLoc {

bool isValid() const { return Value.isValid(); }
bool isInvalid() const { return !isValid(); }


/// An explicit bool operator so one can check if a SourceLoc is valid in an
/// if statement:
///
/// if (auto x = getSourceLoc()) { ... }
explicit operator bool() const { return isValid(); }

bool operator==(const SourceLoc &RHS) const { return RHS.Value == Value; }
bool operator!=(const SourceLoc &RHS) const { return !operator==(RHS); }

Expand Down Expand Up @@ -107,6 +113,12 @@ class SourceRange {
bool isValid() const { return Start.isValid(); }
bool isInvalid() const { return !isValid(); }

/// An explicit bool operator so one can check if a SourceRange is valid in an
/// if statement:
///
/// if (auto x = getSourceRange()) { ... }
explicit operator bool() const { return isValid(); }

/// Extend this SourceRange to the smallest continuous SourceRange that
/// includes both this range and the other one.
void widen(SourceRange Other);
Expand Down
35 changes: 28 additions & 7 deletions include/swift/SIL/OptimizationRemark.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ struct IndentDebug {
unsigned width;
};

enum class SourceLocPresentationKind {
StartRange,
EndRange,
};

enum class SourceLocInferenceBehavior : unsigned {
None = 0,
ForwardScan = 0x1,
Expand Down Expand Up @@ -165,7 +170,9 @@ inline SourceLocInferenceBehavior operator&(SourceLocInferenceBehavior lhs,
/// surrounding code. If we can not find any surrounding code, we return an
/// invalid SourceLoc.
SourceLoc inferOptRemarkSourceLoc(SILInstruction &i,
SourceLocInferenceBehavior inferBehavior);
SourceLocInferenceBehavior inferBehavior,
SourceLocPresentationKind presentationKind =
SourceLocPresentationKind::StartRange);

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

protected:
Remark(StringRef identifier, SILInstruction &i,
SourceLocInferenceBehavior inferenceBehavior)
SourceLocInferenceBehavior inferenceBehavior,
SourceLocPresentationKind locPresentationKind)
: identifier((Twine("sil.") + identifier).str()),
location(inferOptRemarkSourceLoc(i, inferenceBehavior)),
location(
inferOptRemarkSourceLoc(i, inferenceBehavior, locPresentationKind)),
function(i.getParent()->getParent()),
demangledFunctionName(Demangle::demangleSymbolAsString(
function->getName(),
Expand Down Expand Up @@ -238,18 +247,30 @@ class Remark {
/// Remark to report a successful optimization.
struct RemarkPassed : public Remark<RemarkPassed> {
RemarkPassed(StringRef id, SILInstruction &i)
: Remark(id, i, SourceLocInferenceBehavior::None) {}
: Remark(id, i, SourceLocInferenceBehavior::None,
SourceLocPresentationKind::StartRange) {}
RemarkPassed(StringRef id, SILInstruction &i,
SourceLocInferenceBehavior inferenceBehavior)
: Remark(id, i, inferenceBehavior) {}
: Remark(id, i, inferenceBehavior,
SourceLocPresentationKind::StartRange) {}
RemarkPassed(StringRef id, SILInstruction &i,
SourceLocInferenceBehavior inferenceBehavior,
SourceLocPresentationKind locPresentationKind)
: Remark(id, i, inferenceBehavior, locPresentationKind) {}
};
/// Remark to report a unsuccessful optimization.
struct RemarkMissed : public Remark<RemarkMissed> {
RemarkMissed(StringRef id, SILInstruction &i)
: Remark(id, i, SourceLocInferenceBehavior::None) {}
: Remark(id, i, SourceLocInferenceBehavior::None,
SourceLocPresentationKind::StartRange) {}
RemarkMissed(StringRef id, SILInstruction &i,
SourceLocInferenceBehavior inferenceBehavior)
: Remark(id, i, inferenceBehavior) {}
: Remark(id, i, inferenceBehavior,
SourceLocPresentationKind::StartRange) {}
RemarkMissed(StringRef id, SILInstruction &i,
SourceLocInferenceBehavior inferenceBehavior,
SourceLocPresentationKind locPresentationKind)
: Remark(id, i, inferenceBehavior, locPresentationKind) {}
};

/// Used to emit the remarks. Passes reporting remarks should create an
Expand Down
81 changes: 59 additions & 22 deletions lib/SIL/Utils/OptimizationRemark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-opt-remarks"

#include "swift/SIL/OptimizationRemark.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsSIL.h"
Expand All @@ -30,6 +32,7 @@
#include "swift/SIL/SILRemarkStreamer.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

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

static SourceLoc getLocForPresentation(SILLocation loc,
SourceLocPresentationKind kind) {
if (!loc)
return SourceLoc();
switch (kind) {
case SourceLocPresentationKind::StartRange:
return loc.getSourceLoc();
case SourceLocPresentationKind::EndRange:
return loc.getEndSourceLoc();
}
}

/// The user has passed us an instruction that for some reason has a source loc
/// that can not be used. Search down the current block for an instruction with
/// a valid source loc and use that instead.
static SourceLoc inferOptRemarkSearchForwards(SILInstruction &i) {
static SourceLoc
inferOptRemarkSearchForwards(SILInstruction &i,
SourceLocPresentationKind presentationKind) {
for (auto &inst :
llvm::make_range(std::next(i.getIterator()), i.getParent()->end())) {
auto newLoc = inst.getLoc().getSourceLoc();
auto newLoc = getLocForPresentation(inst.getLoc(), presentationKind);
if (auto inlinedLoc = inst.getDebugScope()->getOutermostInlineLocation())
newLoc = inlinedLoc.getSourceLoc();
newLoc = getLocForPresentation(inlinedLoc, presentationKind);
if (newLoc.isValid())
return newLoc;
}
Expand All @@ -165,18 +182,16 @@ static SourceLoc inferOptRemarkSearchForwards(SILInstruction &i) {
/// that can not be used. Search up the current block for an instruction with
/// a valid SILLocation and use the end SourceLoc of the SourceRange for the
/// instruction.
static SourceLoc inferOptRemarkSearchBackwards(SILInstruction &i) {
static SourceLoc
inferOptRemarkSearchBackwards(SILInstruction &i,
SourceLocPresentationKind presentationKind) {
for (auto &inst : llvm::make_range(std::next(i.getReverseIterator()),
i.getParent()->rend())) {
auto loc = inst.getLoc();
if (auto inlinedLoc = inst.getDebugScope()->getOutermostInlineLocation())
loc = inlinedLoc;
if (!loc.getSourceLoc().isValid())
continue;

auto range = loc.getSourceRange();
if (range.isValid())
return range.End;
if (auto result = getLocForPresentation(loc, presentationKind))
return result;
}

return SourceLoc();
Expand All @@ -195,34 +210,56 @@ static llvm::cl::opt<bool> IgnoreAlwaysInferForTesting(
// (retain, release) and other situations where we are ok with original source
// locs if we are not inlined (alloc_ref, alloc_stack).
SourceLoc swift::OptRemark::inferOptRemarkSourceLoc(
SILInstruction &i, SourceLocInferenceBehavior inferBehavior) {
SILInstruction &i, SourceLocInferenceBehavior inferBehavior,
SourceLocPresentationKind presentationKind) {
LLVM_DEBUG(llvm::dbgs() << "Begin infer source loc for: " << i);
// If we are only supposed to infer in inline contexts, see if we have a valid
// loc and if that loc is an inlined call site.
auto loc = i.getLoc();
if (loc.getSourceLoc().isValid() &&
!(bool(inferBehavior & SourceLocInferenceBehavior::AlwaysInfer) &&
!IgnoreAlwaysInferForTesting) &&
!(i.getDebugScope() && i.getDebugScope()->InlinedCallSite))
return loc.getSourceLoc();
if (!(bool(inferBehavior & SourceLocInferenceBehavior::AlwaysInfer) &&
!IgnoreAlwaysInferForTesting)) {
LLVM_DEBUG(llvm::dbgs() << "Testing insts own source loc?!\n");
if (loc.getSourceLoc().isValid()) {
LLVM_DEBUG(llvm::dbgs() << "Found initial valid loc!\n");
if (!(i.getDebugScope() && i.getDebugScope()->InlinedCallSite)) {
LLVM_DEBUG(llvm::dbgs() << "Found debug scope!\n");
return getLocForPresentation(loc, presentationKind);
} else {
LLVM_DEBUG(llvm::dbgs() << "Did not find debug scope!\n");
}
} else {
LLVM_DEBUG(llvm::dbgs() << "Failed to find initial valid loc!\n");
}
}

if (bool(inferBehavior & SourceLocInferenceBehavior::ForwardScan)) {
SourceLoc newLoc = inferOptRemarkSearchForwards(i);
if (newLoc.isValid())
LLVM_DEBUG(llvm::dbgs() << "Inferring Source Loc Forward!\n");
SourceLoc newLoc = inferOptRemarkSearchForwards(i, presentationKind);
if (newLoc.isValid()) {
LLVM_DEBUG(llvm::dbgs() << "Found loc!\n");
return newLoc;
}
}

if (bool(inferBehavior & SourceLocInferenceBehavior::BackwardScan)) {
SourceLoc newLoc = inferOptRemarkSearchBackwards(i);
if (newLoc.isValid())
LLVM_DEBUG(llvm::dbgs() << "Inferring Source Loc Backwards!\n");
SourceLoc newLoc = inferOptRemarkSearchBackwards(i, presentationKind);
if (newLoc.isValid()) {
LLVM_DEBUG(llvm::dbgs() << "Found loc!\n");
return newLoc;
}
}

if (bool(inferBehavior & SourceLocInferenceBehavior::ForwardScan2nd)) {
SourceLoc newLoc = inferOptRemarkSearchForwards(i);
if (newLoc.isValid())
LLVM_DEBUG(llvm::dbgs() << "Inferring Source Loc Forward Scan 2nd!\n");
SourceLoc newLoc = inferOptRemarkSearchForwards(i, presentationKind);
if (newLoc.isValid()) {
LLVM_DEBUG(llvm::dbgs() << "Found loc!\n");
return newLoc;
}
}

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

Expand Down
Loading