Skip to content

Commit 0844bbd

Browse files
authored
Merge pull request swiftlang#40738 from eeckstein/rename-dealloc-ref-stack
Rename `dealloc_ref [stack]` and enable StackPromotion for OSSA
2 parents 835beda + 802d11a commit 0844bbd

File tree

62 files changed

+271
-227
lines changed

Some content is hidden

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

62 files changed

+271
-227
lines changed

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ final public class DeallocStackInst : Instruction, UnaryInstruction {
208208
}
209209
}
210210

211+
final public class DeallocStackRefInst : Instruction, UnaryInstruction {
212+
public var allocRef: AllocRefInst { operand as! AllocRefInst }
213+
}
214+
211215
final public class CondFailInst : Instruction, UnaryInstruction {
212216
public override var mayTrap: Bool { true }
213217

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public func registerSILClasses() {
4242
register(EndAccessInst.self)
4343
register(EndBorrowInst.self)
4444
register(DeallocStackInst.self)
45+
register(DeallocStackRefInst.self)
4546
register(CondFailInst.self)
4647
register(FixLifetimeInst.self)
4748
register(DebugValueInst.self)

docs/SIL.rst

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3143,8 +3143,8 @@ optional ``objc`` attribute indicates that the object should be
31433143
allocated using Objective-C's allocation methods (``+allocWithZone:``).
31443144

31453145
The optional ``stack`` attribute indicates that the object can be allocated
3146-
on the stack instead on the heap. In this case the instruction must have
3147-
balanced with a ``dealloc_ref [stack]`` instruction to mark the end of the
3146+
on the stack instead on the heap. In this case the instruction must be
3147+
balanced with a ``dealloc_stack_ref`` instruction to mark the end of the
31483148
object's lifetime.
31493149
Note that the ``stack`` attribute only specifies that stack allocation is
31503150
possible. The final decision on stack allocation is done during llvm IR
@@ -3381,13 +3381,25 @@ project_box
33813381

33823382
Given a ``@box T`` reference, produces the address of the value inside the box.
33833383

3384+
dealloc_stack_ref
3385+
`````````````````
3386+
::
3387+
3388+
sil-instruction ::= 'dealloc_stack_ref' sil-operand
3389+
3390+
dealloc_stack_ref %0 : $T
3391+
// $T must be a class type
3392+
// %0 must be an 'alloc_ref [stack]' instruction
3393+
3394+
Marks the deallocation of the stack space for an ``alloc_ref [stack]``.
3395+
33843396
dealloc_ref
33853397
```````````
33863398
::
33873399

3388-
sil-instruction ::= 'dealloc_ref' ('[' 'stack' ']')? sil-operand
3400+
sil-instruction ::= 'dealloc_ref' sil-operand
33893401

3390-
dealloc_ref [stack] %0 : $T
3402+
dealloc_ref %0 : $T
33913403
// $T must be a class type
33923404

33933405
Deallocates an uninitialized class type instance, bypassing the reference

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,10 +2005,14 @@ class SILBuilder {
20052005
return insert(new (getModule())
20062006
DeallocStackInst(getSILDebugLocation(Loc), operand));
20072007
}
2008-
DeallocRefInst *createDeallocRef(SILLocation Loc, SILValue operand,
2009-
bool canBeOnStack) {
2008+
DeallocStackRefInst *createDeallocStackRef(SILLocation Loc,
2009+
SILValue operand) {
2010+
return insert(new (getModule())
2011+
DeallocStackRefInst(getSILDebugLocation(Loc), operand));
2012+
}
2013+
DeallocRefInst *createDeallocRef(SILLocation Loc, SILValue operand) {
20102014
return insert(new (getModule()) DeallocRefInst(
2011-
getSILDebugLocation(Loc), operand, canBeOnStack));
2015+
getSILDebugLocation(Loc), operand));
20122016
}
20132017
DeallocPartialRefInst *createDeallocPartialRef(SILLocation Loc,
20142018
SILValue operand,

include/swift/SIL/SILCloner.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,8 +2488,16 @@ SILCloner<ImplClass>::visitDeallocRefInst(DeallocRefInst *Inst) {
24882488
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
24892489
recordClonedInstruction(
24902490
Inst, getBuilder().createDeallocRef(getOpLocation(Inst->getLoc()),
2491-
getOpValue(Inst->getOperand()),
2492-
Inst->canAllocOnStack()));
2491+
getOpValue(Inst->getOperand())));
2492+
}
2493+
2494+
template<typename ImplClass>
2495+
void
2496+
SILCloner<ImplClass>::visitDeallocStackRefInst(DeallocStackRefInst *Inst) {
2497+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2498+
recordClonedInstruction(
2499+
Inst, getBuilder().createDeallocStackRef(getOpLocation(Inst->getLoc()),
2500+
getOpValue(Inst->getOperand())));
24932501
}
24942502

24952503
template<typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7619,6 +7619,18 @@ class DeallocStackInst :
76197619
: UnaryInstructionBase(DebugLoc, operand) {}
76207620
};
76217621

7622+
/// Like DeallocStackInst, but for `alloc_ref [stack]`.
7623+
class DeallocStackRefInst
7624+
: public UnaryInstructionBase<SILInstructionKind::DeallocStackRefInst,
7625+
DeallocationInst> {
7626+
friend SILBuilder;
7627+
7628+
DeallocStackRefInst(SILDebugLocation DebugLoc, SILValue Operand)
7629+
: UnaryInstructionBase(DebugLoc, Operand) {}
7630+
public:
7631+
AllocRefInst *getAllocRef() { return cast<AllocRefInst>(getOperand()); }
7632+
};
7633+
76227634
/// Deallocate memory for a reference type instance from a destructor or
76237635
/// failure path of a constructor.
76247636
///
@@ -7632,21 +7644,8 @@ class DeallocRefInst :
76327644
DeallocationInst> {
76337645
friend SILBuilder;
76347646

7635-
private:
7636-
DeallocRefInst(SILDebugLocation DebugLoc, SILValue Operand,
7637-
bool canBeOnStack = false)
7638-
: UnaryInstructionBase(DebugLoc, Operand) {
7639-
SILNode::Bits.DeallocRefInst.OnStack = canBeOnStack;
7640-
}
7641-
7642-
public:
7643-
bool canAllocOnStack() const {
7644-
return SILNode::Bits.DeallocRefInst.OnStack;
7645-
}
7646-
7647-
void setStackAllocatable(bool OnStack) {
7648-
SILNode::Bits.DeallocRefInst.OnStack = OnStack;
7649-
}
7647+
DeallocRefInst(SILDebugLocation DebugLoc, SILValue Operand)
7648+
: UnaryInstructionBase(DebugLoc, Operand) { }
76507649
};
76517650

76527651
/// Deallocate memory for a reference type instance from a failure path of a

include/swift/SIL/SILNode.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,6 @@ class alignas(8) SILNode :
218218
Length : 32
219219
);
220220

221-
SWIFT_INLINE_BITFIELD(DeallocRefInst, DeallocationInst, 1,
222-
OnStack : 1
223-
);
224-
225221
// Ensure that AllocBoxInst bitfield does not overflow.
226222
IBWTO_BITFIELD_EMPTY(AllocBoxInst, AllocationInst);
227223
// Ensure that AllocExistentialBoxInst bitfield does not overflow.

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,8 @@ ABSTRACT_INST(TermInst, SILInstruction)
808808
ABSTRACT_INST(DeallocationInst, SILInstruction)
809809
BRIDGED_NON_VALUE_INST(DeallocStackInst, dealloc_stack,
810810
DeallocationInst, MayHaveSideEffects, DoesNotRelease)
811+
BRIDGED_NON_VALUE_INST(DeallocStackRefInst, dealloc_stack_ref,
812+
DeallocationInst, MayHaveSideEffects, DoesNotRelease)
811813
BRIDGED_NON_VALUE_INST(DeallocRefInst, dealloc_ref,
812814
DeallocationInst, MayHaveSideEffects, DoesNotRelease)
813815
NON_VALUE_INST(DeallocPartialRefInst, dealloc_partial_ref,

include/swift/SILOptimizer/Utils/ValueLifetime.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ class ValueLifetimeAnalysis {
197197
(hasUsersBeforeDef || bb != getDefValueParentBlock());
198198
}
199199

200-
/// Checks if there is a dealloc_ref inside the value's live range.
200+
/// Checks if there is a dealloc_ref or dealloc_stack_ref inside the
201+
/// value's live range.
201202
bool containsDeallocRef(const FrontierImpl &frontier);
202203

203204
/// For debug dumping.

lib/IRGen/IRGenSIL.cpp

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,7 @@ class IRGenSILFunction :
12571257
void visitEndCOWMutationInst(EndCOWMutationInst *i);
12581258
void visitIsEscapingClosureInst(IsEscapingClosureInst *i);
12591259
void visitDeallocStackInst(DeallocStackInst *i);
1260+
void visitDeallocStackRefInst(DeallocStackRefInst *i);
12601261
void visitDeallocBoxInst(DeallocBoxInst *i);
12611262
void visitDeallocRefInst(DeallocRefInst *i);
12621263
void visitDeallocPartialRefInst(DeallocPartialRefInst *i);
@@ -4515,9 +4516,9 @@ void IRGenSILFunction::visitSetDeallocatingInst(SetDeallocatingInst *i) {
45154516
// ...
45164517
// set_deallocating %0 // not needed
45174518
// // code which does not depend on the RC_DEALLOCATING_FLAG flag.
4518-
// dealloc_ref %0 // not needed (stems from the inlined deallocator)
4519+
// dealloc_ref %0 // stems from the inlined deallocator
45194520
// ...
4520-
// dealloc_ref [stack] %0
4521+
// dealloc_stack_ref %0
45214522
SILBasicBlock::iterator Iter(i);
45224523
SILBasicBlock::iterator End = i->getParent()->end();
45234524
for (++Iter; Iter != End; ++Iter) {
@@ -5432,32 +5433,10 @@ void IRGenSILFunction::visitDeallocStackInst(swift::DeallocStackInst *i) {
54325433
allocatedTI.deallocateStack(*this, stackAddr, allocatedType);
54335434
}
54345435

5435-
void IRGenSILFunction::visitDeallocRefInst(swift::DeallocRefInst *i) {
5436-
// Lower the operand.
5436+
void IRGenSILFunction::visitDeallocStackRefInst(DeallocStackRefInst *i) {
54375437
Explosion self = getLoweredExplosion(i->getOperand());
54385438
auto selfValue = self.claimNext();
5439-
auto *ARI = dyn_cast<AllocRefInst>(i->getOperand());
5440-
if (!i->canAllocOnStack()) {
5441-
if (ARI && StackAllocs.count(ARI)) {
5442-
// We can ignore dealloc_refs (without [stack]) for stack allocated
5443-
// objects.
5444-
//
5445-
// %0 = alloc_ref [stack]
5446-
// ...
5447-
// dealloc_ref %0 // not needed (stems from the inlined deallocator)
5448-
// ...
5449-
// dealloc_ref [stack] %0
5450-
return;
5451-
}
5452-
5453-
auto classType = i->getOperand()->getType();
5454-
emitClassDeallocation(*this, classType, selfValue);
5455-
return;
5456-
}
5457-
// It's a dealloc_ref [stack]. Even if the alloc_ref did not allocate the
5458-
// object on the stack, we don't have to deallocate it, because it is
5459-
// deallocated in the final release.
5460-
assert(ARI->canAllocOnStack());
5439+
auto *ARI = i->getAllocRef();
54615440
if (StackAllocs.count(ARI)) {
54625441
if (IGM.IRGen.Opts.EmitStackPromotionChecks) {
54635442
selfValue = Builder.CreateBitCast(selfValue, IGM.RefCountedPtrTy);
@@ -5473,6 +5452,25 @@ void IRGenSILFunction::visitDeallocRefInst(swift::DeallocRefInst *i) {
54735452
}
54745453
}
54755454

5455+
void IRGenSILFunction::visitDeallocRefInst(swift::DeallocRefInst *i) {
5456+
// Lower the operand.
5457+
Explosion self = getLoweredExplosion(i->getOperand());
5458+
auto selfValue = self.claimNext();
5459+
auto *ARI = dyn_cast<AllocRefInst>(i->getOperand());
5460+
if (ARI && StackAllocs.count(ARI)) {
5461+
// We can ignore dealloc_refs for stack allocated objects.
5462+
//
5463+
// %0 = alloc_ref [stack]
5464+
// ...
5465+
// dealloc_ref %0 // not needed (stems from the inlined deallocator)
5466+
// ...
5467+
// dealloc_stack_ref %0
5468+
return;
5469+
}
5470+
auto classType = i->getOperand()->getType();
5471+
emitClassDeallocation(*this, classType, selfValue);
5472+
}
5473+
54765474
void IRGenSILFunction::visitDeallocPartialRefInst(swift::DeallocPartialRefInst *i) {
54775475
Explosion self = getLoweredExplosion(i->getInstance());
54785476
auto selfValue = self.claimNext();

0 commit comments

Comments
 (0)