Skip to content

Commit fee237e

Browse files
authored
Merge pull request #19124 from gottesmm/pr-1b720840e87378cbb83b63318c7de75740a7b080
[sil] Eliminate the src parameter from end_borrow.
2 parents c6ff9fb + c599539 commit fee237e

File tree

105 files changed

+552
-511
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+552
-511
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,6 @@ struct ErrorBehaviorKind {
6363
/// use with SILPasses. It uses the actual checker as an internal PImpl detail
6464
/// so types/etc do not leak.
6565
struct OwnershipChecker {
66-
/// The module that we are in.
67-
SILModule &Mod;
68-
69-
/// A cache of dead-end basic blocks that we use to determine if we can
70-
/// ignore "leaks".
71-
DeadEndBlocks &DEBlocks;
72-
7366
/// The list of regular users from the last run of the checker.
7467
SmallVector<SILInstruction *, 16> RegularUsers;
7568

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

76+
/// The list of implicit regular users from the last run of the checker.
77+
///
78+
/// This is used to encode end of scope like instructions.
79+
SmallVector<SILInstruction *, 4> ImplicitRegularUsers;
80+
81+
/// The module that we are in.
82+
SILModule &Mod;
83+
84+
/// A cache of dead-end basic blocks that we use to determine if we can
85+
/// ignore "leaks".
86+
DeadEndBlocks &DEBlocks;
87+
8388
bool checkValue(SILValue Value);
8489
};
8590

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -716,10 +716,15 @@ class SILBuilder {
716716
return lowering.emitStore(*this, Loc, Src, DestAddr, Qualifier);
717717
}
718718

719+
EndBorrowInst *createEndBorrow(SILLocation loc, SILValue borrowedValue) {
720+
return insert(new (getModule())
721+
EndBorrowInst(getSILDebugLocation(loc), borrowedValue));
722+
}
723+
719724
EndBorrowInst *createEndBorrow(SILLocation Loc, SILValue BorrowedValue,
720725
SILValue OriginalValue) {
721-
return insert(new (getModule()) EndBorrowInst(
722-
getSILDebugLocation(Loc), BorrowedValue, OriginalValue));
726+
return insert(new (getModule())
727+
EndBorrowInst(getSILDebugLocation(Loc), BorrowedValue));
723728
}
724729

725730
EndBorrowArgumentInst *createEndBorrowArgument(SILLocation Loc,

include/swift/SIL/SILCloner.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,10 +773,9 @@ void SILCloner<ImplClass>::visitStoreBorrowInst(StoreBorrowInst *Inst) {
773773
template <typename ImplClass>
774774
void SILCloner<ImplClass>::visitEndBorrowInst(EndBorrowInst *Inst) {
775775
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
776-
doPostProcess(
777-
Inst, getBuilder().createEndBorrow(getOpLocation(Inst->getLoc()),
778-
getOpValue(Inst->getBorrowedValue()),
779-
getOpValue(Inst->getOriginalValue())));
776+
doPostProcess(Inst, getBuilder().createEndBorrow(
777+
getOpLocation(Inst->getLoc()),
778+
getOpValue(Inst->getOperand()), SILValue()));
780779
}
781780

782781
template <typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3094,6 +3094,8 @@ class LoadBorrowInst :
30943094
LValue->getType().getObjectType()) {}
30953095
};
30963096

3097+
class EndBorrowInst;
3098+
30973099
/// Represents the begin scope of a borrowed value. Must be paired with an
30983100
/// end_borrow instruction in its use-def list.
30993101
class BeginBorrowInst
@@ -3104,8 +3106,32 @@ class BeginBorrowInst
31043106
BeginBorrowInst(SILDebugLocation DebugLoc, SILValue LValue)
31053107
: UnaryInstructionBase(DebugLoc, LValue,
31063108
LValue->getType().getObjectType()) {}
3109+
3110+
private:
3111+
/// Predicate used to filer EndBorrowRange.
3112+
struct UseToEndBorrow;
3113+
3114+
public:
3115+
using EndBorrowRange =
3116+
OptionalTransformRange<use_range, UseToEndBorrow, use_iterator>;
3117+
3118+
/// Find all associated end_borrow instructions for this begin_borrow.
3119+
EndBorrowRange getEndBorrows() const;
31073120
};
31083121

3122+
struct BeginBorrowInst::UseToEndBorrow {
3123+
Optional<EndBorrowInst *> operator()(Operand *use) const {
3124+
if (auto *ebi = dyn_cast<EndBorrowInst>(use->getUser())) {
3125+
return ebi;
3126+
}
3127+
return None;
3128+
}
3129+
};
3130+
3131+
inline auto BeginBorrowInst::getEndBorrows() const -> EndBorrowRange {
3132+
return EndBorrowRange(getUses(), UseToEndBorrow());
3133+
}
3134+
31093135
/// Represents a store of a borrowed value into an address. Returns the borrowed
31103136
/// address. Must be paired with an end_borrow in its use-def list.
31113137
class StoreBorrowInst
@@ -3133,37 +3159,66 @@ class StoreBorrowInst
31333159
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
31343160
};
31353161

3136-
/// Represents the end of a borrow scope for a value or address from another
3137-
/// value or address.
3162+
/// Represents the end of a borrow scope of a value %val from a
3163+
/// value or address %src.
3164+
///
3165+
/// While %val is "live" in a region then,
31383166
///
3139-
/// The semantics of the instruction here is that the "dest" SILValue can not be
3140-
/// used after this instruction and the "src" SILValue must stay alive up to
3141-
/// EndBorrowInst.
3167+
/// 1. If %src is an object, it is undefined behavior for %src to be
3168+
/// destroyed. This is enforced by the ownership verifier.
3169+
///
3170+
/// 2. If %src is an address, it is undefined behavior for %src to be
3171+
/// destroyed or written to.
31423172
class EndBorrowInst
3143-
: public InstructionBase<SILInstructionKind::EndBorrowInst,
3144-
NonValueInstruction> {
3173+
: public UnaryInstructionBase<SILInstructionKind::EndBorrowInst,
3174+
NonValueInstruction> {
31453175
friend class SILBuilder;
31463176

3147-
public:
3148-
enum {
3149-
/// The borrowed value.
3150-
BorrowedValue,
3151-
/// The original value that was borrowed from.
3152-
OriginalValue
3153-
};
3154-
3155-
private:
3156-
FixedOperandList<2> Operands;
3157-
EndBorrowInst(SILDebugLocation DebugLoc, SILValue BorrowedValue,
3158-
SILValue OriginalValue);
3177+
EndBorrowInst(SILDebugLocation debugLoc, SILValue borrowedValue)
3178+
: UnaryInstructionBase(debugLoc, borrowedValue) {}
31593179

31603180
public:
3161-
SILValue getBorrowedValue() const { return Operands[BorrowedValue].get(); }
3162-
3163-
SILValue getOriginalValue() const { return Operands[OriginalValue].get(); }
3181+
/// Return the value that this end_borrow is ending the borrow of if we are
3182+
/// borrowing a single value.
3183+
SILValue getSingleOriginalValue() const {
3184+
SILValue v = getOperand();
3185+
if (auto *bbi = dyn_cast<BeginBorrowInst>(v))
3186+
return bbi->getOperand();
3187+
if (auto *lbi = dyn_cast<LoadBorrowInst>(v))
3188+
return lbi->getOperand();
3189+
llvm::errs() << "Can not end borrow for value: " << v;
3190+
llvm_unreachable("standard error assertion");
3191+
}
31643192

3165-
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
3166-
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
3193+
/// Return the set of guaranteed values that have scopes ended by this
3194+
/// end_borrow.
3195+
///
3196+
/// Discussion: We can only have multiple values associated with an end_borrow
3197+
/// in the case of having Phi arguments with guaranteed inputs. This is
3198+
/// necessary to represent certain conditional operations such as:
3199+
///
3200+
/// class Klass {
3201+
/// let k1: Klass
3202+
/// let k2: Klass
3203+
/// }
3204+
///
3205+
/// func useKlass(k: Klass) { ... }
3206+
/// var boolValue : Bool { ... }
3207+
///
3208+
/// func f(k: Klass) {
3209+
/// useKlass(boolValue ? k.k1 : k.k2)
3210+
/// }
3211+
///
3212+
/// Today, when we SILGen such code, we copy k.k1 and k.k2 before the Phi when
3213+
/// it could potentially be avoided. So today this just appends
3214+
/// getSingleOriginalValue() to originalValues.
3215+
///
3216+
/// TODO: Once this changes, this code must be update.
3217+
void getOriginalValues(SmallVectorImpl<SILValue> &originalValues) const {
3218+
SILValue value = getSingleOriginalValue();
3219+
assert(value && "Guaranteed phi arguments are not supported now");
3220+
originalValues.emplace_back(value);
3221+
}
31673222
};
31683223

31693224
/// Represents the end of a borrow scope for an argument. The reason why this is

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 440; // Last change: removed materializeForSet
58+
const uint16_t VERSION_MINOR = 441; // Last change: remove end_borrow src arg
5959

6060
using DeclIDField = BCFixed<31>;
6161

lib/ParseSIL/ParseSIL.cpp

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2681,6 +2681,7 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
26812681
UNARY_INSTRUCTION(DestroyValue)
26822682
UNARY_INSTRUCTION(CondFail)
26832683
UNARY_INSTRUCTION(EndBorrowArgument)
2684+
UNARY_INSTRUCTION(EndBorrow)
26842685
UNARY_INSTRUCTION(DestructureStruct)
26852686
UNARY_INSTRUCTION(DestructureTuple)
26862687
REFCOUNTING_INSTRUCTION(UnmanagedReleaseValue)
@@ -3395,36 +3396,6 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
33953396
break;
33963397
}
33973398

3398-
case SILInstructionKind::EndBorrowInst: {
3399-
UnresolvedValueName BorrowedFromName, BorrowedValueName;
3400-
SourceLoc ToLoc;
3401-
Identifier ToToken;
3402-
SILType BorrowedFromTy, BorrowedValueTy;
3403-
3404-
if (parseValueName(BorrowedValueName) ||
3405-
parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
3406-
"from") ||
3407-
parseValueName(BorrowedFromName) ||
3408-
P.parseToken(tok::colon, diag::expected_sil_colon_value_ref) ||
3409-
parseSILType(BorrowedValueTy) ||
3410-
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
3411-
parseSILType(BorrowedFromTy) || parseSILDebugLocation(InstLoc, B))
3412-
return true;
3413-
3414-
if (ToToken.str() != "from") {
3415-
P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "from");
3416-
return true;
3417-
}
3418-
3419-
SILValue BorrowedValue =
3420-
getLocalValue(BorrowedValueName, BorrowedValueTy, InstLoc, B);
3421-
SILValue BorrowedFrom =
3422-
getLocalValue(BorrowedFromName, BorrowedFromTy, InstLoc, B);
3423-
3424-
ResultVal = B.createEndBorrow(InstLoc, BorrowedValue, BorrowedFrom);
3425-
break;
3426-
}
3427-
34283399
case SILInstructionKind::BeginAccessInst:
34293400
case SILInstructionKind::BeginUnpairedAccessInst:
34303401
case SILInstructionKind::EndAccessInst:

lib/SIL/SILInstructions.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -790,11 +790,6 @@ StoreBorrowInst::StoreBorrowInst(SILDebugLocation DebugLoc, SILValue Src,
790790
: InstructionBase(DebugLoc, Dest->getType()),
791791
Operands(this, Src, Dest) {}
792792

793-
EndBorrowInst::EndBorrowInst(SILDebugLocation DebugLoc, SILValue Src,
794-
SILValue Dest)
795-
: InstructionBase(DebugLoc),
796-
Operands(this, Src, Dest) {}
797-
798793
EndBorrowArgumentInst::EndBorrowArgumentInst(SILDebugLocation DebugLoc,
799794
SILArgument *Arg)
800795
: UnaryInstructionBase(DebugLoc, SILValue(Arg)) {}

0 commit comments

Comments
 (0)