Skip to content

[sil] Eliminate the src parameter from end_borrow. #19124

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
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
19 changes: 12 additions & 7 deletions include/swift/SIL/OwnershipUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ struct ErrorBehaviorKind {
/// use with SILPasses. It uses the actual checker as an internal PImpl detail
/// so types/etc do not leak.
struct OwnershipChecker {
/// The module that we are in.
SILModule &Mod;

/// A cache of dead-end basic blocks that we use to determine if we can
/// ignore "leaks".
DeadEndBlocks &DEBlocks;

/// The list of regular users from the last run of the checker.
SmallVector<SILInstruction *, 16> RegularUsers;

Expand All @@ -80,6 +73,18 @@ struct OwnershipChecker {
/// determine if a block is in the "live" region of our SILInstruction.
SmallPtrSet<SILBasicBlock *, 32> LiveBlocks;

/// The list of implicit regular users from the last run of the checker.
///
/// This is used to encode end of scope like instructions.
SmallVector<SILInstruction *, 4> ImplicitRegularUsers;

/// The module that we are in.
SILModule &Mod;

/// A cache of dead-end basic blocks that we use to determine if we can
/// ignore "leaks".
DeadEndBlocks &DEBlocks;

bool checkValue(SILValue Value);
};

Expand Down
9 changes: 7 additions & 2 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -716,10 +716,15 @@ class SILBuilder {
return lowering.emitStore(*this, Loc, Src, DestAddr, Qualifier);
}

EndBorrowInst *createEndBorrow(SILLocation loc, SILValue borrowedValue) {
return insert(new (getModule())
EndBorrowInst(getSILDebugLocation(loc), borrowedValue));
}

EndBorrowInst *createEndBorrow(SILLocation Loc, SILValue BorrowedValue,
SILValue OriginalValue) {
return insert(new (getModule()) EndBorrowInst(
getSILDebugLocation(Loc), BorrowedValue, OriginalValue));
return insert(new (getModule())
EndBorrowInst(getSILDebugLocation(Loc), BorrowedValue));
}

EndBorrowArgumentInst *createEndBorrowArgument(SILLocation Loc,
Expand Down
7 changes: 3 additions & 4 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -773,10 +773,9 @@ void SILCloner<ImplClass>::visitStoreBorrowInst(StoreBorrowInst *Inst) {
template <typename ImplClass>
void SILCloner<ImplClass>::visitEndBorrowInst(EndBorrowInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(
Inst, getBuilder().createEndBorrow(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getBorrowedValue()),
getOpValue(Inst->getOriginalValue())));
doPostProcess(Inst, getBuilder().createEndBorrow(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()), SILValue()));
}

template <typename ImplClass>
Expand Down
103 changes: 79 additions & 24 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3094,6 +3094,8 @@ class LoadBorrowInst :
LValue->getType().getObjectType()) {}
};

class EndBorrowInst;

/// Represents the begin scope of a borrowed value. Must be paired with an
/// end_borrow instruction in its use-def list.
class BeginBorrowInst
Expand All @@ -3104,8 +3106,32 @@ class BeginBorrowInst
BeginBorrowInst(SILDebugLocation DebugLoc, SILValue LValue)
: UnaryInstructionBase(DebugLoc, LValue,
LValue->getType().getObjectType()) {}

private:
/// Predicate used to filer EndBorrowRange.
struct UseToEndBorrow;

public:
using EndBorrowRange =
OptionalTransformRange<use_range, UseToEndBorrow, use_iterator>;

/// Find all associated end_borrow instructions for this begin_borrow.
EndBorrowRange getEndBorrows() const;
};

struct BeginBorrowInst::UseToEndBorrow {
Optional<EndBorrowInst *> operator()(Operand *use) const {
if (auto *ebi = dyn_cast<EndBorrowInst>(use->getUser())) {
return ebi;
}
return None;
}
};

inline auto BeginBorrowInst::getEndBorrows() const -> EndBorrowRange {
return EndBorrowRange(getUses(), UseToEndBorrow());
}

/// Represents a store of a borrowed value into an address. Returns the borrowed
/// address. Must be paired with an end_borrow in its use-def list.
class StoreBorrowInst
Expand Down Expand Up @@ -3133,37 +3159,66 @@ class StoreBorrowInst
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
};

/// Represents the end of a borrow scope for a value or address from another
/// value or address.
/// Represents the end of a borrow scope of a value %val from a
/// value or address %src.
///
/// While %val is "live" in a region then,
///
/// The semantics of the instruction here is that the "dest" SILValue can not be
/// used after this instruction and the "src" SILValue must stay alive up to
/// EndBorrowInst.
/// 1. If %src is an object, it is undefined behavior for %src to be
/// destroyed. This is enforced by the ownership verifier.
///
/// 2. If %src is an address, it is undefined behavior for %src to be
/// destroyed or written to.
class EndBorrowInst
: public InstructionBase<SILInstructionKind::EndBorrowInst,
NonValueInstruction> {
: public UnaryInstructionBase<SILInstructionKind::EndBorrowInst,
NonValueInstruction> {
friend class SILBuilder;

public:
enum {
/// The borrowed value.
BorrowedValue,
/// The original value that was borrowed from.
OriginalValue
};

private:
FixedOperandList<2> Operands;
EndBorrowInst(SILDebugLocation DebugLoc, SILValue BorrowedValue,
SILValue OriginalValue);
EndBorrowInst(SILDebugLocation debugLoc, SILValue borrowedValue)
: UnaryInstructionBase(debugLoc, borrowedValue) {}

public:
SILValue getBorrowedValue() const { return Operands[BorrowedValue].get(); }

SILValue getOriginalValue() const { return Operands[OriginalValue].get(); }
/// Return the value that this end_borrow is ending the borrow of if we are
/// borrowing a single value.
SILValue getSingleOriginalValue() const {
SILValue v = getOperand();
if (auto *bbi = dyn_cast<BeginBorrowInst>(v))
return bbi->getOperand();
if (auto *lbi = dyn_cast<LoadBorrowInst>(v))
return lbi->getOperand();
llvm::errs() << "Can not end borrow for value: " << v;
llvm_unreachable("standard error assertion");
}

ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
/// Return the set of guaranteed values that have scopes ended by this
/// end_borrow.
///
/// Discussion: We can only have multiple values associated with an end_borrow
/// in the case of having Phi arguments with guaranteed inputs. This is
/// necessary to represent certain conditional operations such as:
///
/// class Klass {
/// let k1: Klass
/// let k2: Klass
/// }
///
/// func useKlass(k: Klass) { ... }
/// var boolValue : Bool { ... }
///
/// func f(k: Klass) {
/// useKlass(boolValue ? k.k1 : k.k2)
/// }
///
/// Today, when we SILGen such code, we copy k.k1 and k.k2 before the Phi when
/// it could potentially be avoided. So today this just appends
/// getSingleOriginalValue() to originalValues.
///
/// TODO: Once this changes, this code must be update.
void getOriginalValues(SmallVectorImpl<SILValue> &originalValues) const {
SILValue value = getSingleOriginalValue();
assert(value && "Guaranteed phi arguments are not supported now");
originalValues.emplace_back(value);
}
};

/// Represents the end of a borrow scope for an argument. The reason why this is
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t VERSION_MINOR = 440; // Last change: removed materializeForSet
const uint16_t VERSION_MINOR = 441; // Last change: remove end_borrow src arg

using DeclIDField = BCFixed<31>;

Expand Down
31 changes: 1 addition & 30 deletions lib/ParseSIL/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2681,6 +2681,7 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
UNARY_INSTRUCTION(DestroyValue)
UNARY_INSTRUCTION(CondFail)
UNARY_INSTRUCTION(EndBorrowArgument)
UNARY_INSTRUCTION(EndBorrow)
UNARY_INSTRUCTION(DestructureStruct)
UNARY_INSTRUCTION(DestructureTuple)
REFCOUNTING_INSTRUCTION(UnmanagedReleaseValue)
Expand Down Expand Up @@ -3395,36 +3396,6 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
break;
}

case SILInstructionKind::EndBorrowInst: {
UnresolvedValueName BorrowedFromName, BorrowedValueName;
SourceLoc ToLoc;
Identifier ToToken;
SILType BorrowedFromTy, BorrowedValueTy;

if (parseValueName(BorrowedValueName) ||
parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
"from") ||
parseValueName(BorrowedFromName) ||
P.parseToken(tok::colon, diag::expected_sil_colon_value_ref) ||
parseSILType(BorrowedValueTy) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
parseSILType(BorrowedFromTy) || parseSILDebugLocation(InstLoc, B))
return true;

if (ToToken.str() != "from") {
P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "from");
return true;
}

SILValue BorrowedValue =
getLocalValue(BorrowedValueName, BorrowedValueTy, InstLoc, B);
SILValue BorrowedFrom =
getLocalValue(BorrowedFromName, BorrowedFromTy, InstLoc, B);

ResultVal = B.createEndBorrow(InstLoc, BorrowedValue, BorrowedFrom);
break;
}

case SILInstructionKind::BeginAccessInst:
case SILInstructionKind::BeginUnpairedAccessInst:
case SILInstructionKind::EndAccessInst:
Expand Down
5 changes: 0 additions & 5 deletions lib/SIL/SILInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -790,11 +790,6 @@ StoreBorrowInst::StoreBorrowInst(SILDebugLocation DebugLoc, SILValue Src,
: InstructionBase(DebugLoc, Dest->getType()),
Operands(this, Src, Dest) {}

EndBorrowInst::EndBorrowInst(SILDebugLocation DebugLoc, SILValue Src,
SILValue Dest)
: InstructionBase(DebugLoc),
Operands(this, Src, Dest) {}

EndBorrowArgumentInst::EndBorrowArgumentInst(SILDebugLocation DebugLoc,
SILArgument *Arg)
: UnaryInstructionBase(DebugLoc, SILValue(Arg)) {}
Expand Down
Loading