Skip to content

Commit b08710d

Browse files
committed
SIL: add a bare attribute to alloc_ref
The `bare` attribute indicates that the object header is not used throughout the lifetime of the object. This means, no reference counting operations are performed on the object and its metadata is not used. The header of bare objects doesn't need to be initialized.
1 parent 9d76be8 commit b08710d

File tree

20 files changed

+92
-20
lines changed

20 files changed

+92
-20
lines changed

SwiftCompilerSources/Sources/Optimizer/PassManager/Context.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,14 @@ extension RefCountingInst {
430430
}
431431
}
432432

433+
extension AllocRefInst {
434+
func setIsBare(_ context: some MutatingContext) {
435+
context.notifyInstructionsChanged()
436+
bridged.AllocRefInst_setIsBare()
437+
context.notifyInstructionChanged(self)
438+
}
439+
}
440+
433441
extension TermInst {
434442
func replaceBranchTarget(from fromBlock: BasicBlock, to toBlock: BasicBlock, _ context: some MutatingContext) {
435443
context.notifyBranchesChanged()

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,7 @@ public class AllocRefInstBase : SingleValueInstruction, Allocation {
837837
}
838838

839839
final public class AllocRefInst : AllocRefInstBase {
840+
public var isBare: Bool { bridged.AllocRefInst_isBare() }
840841
}
841842

842843
final public class AllocRefDynamicInst : AllocRefInstBase {

docs/SIL.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3816,6 +3816,7 @@ alloc_ref
38163816
::
38173817

38183818
sil-instruction ::= 'alloc_ref'
3819+
('[' 'bare' ']')?
38193820
('[' 'objc' ']')?
38203821
('[' 'stack' ']')?
38213822
('[' 'tail_elems' sil-type '*' sil-operand ']')*
@@ -3842,6 +3843,11 @@ possible. The final decision on stack allocation is done during llvm IR
38423843
generation. This is because the decision also depends on the object size,
38433844
which is not necessarily known at SIL level.
38443845

3846+
The ``bare`` attribute indicates that the object header is not used throughout
3847+
the lifetime of the object. This means, no reference counting operations are
3848+
performed on the object and its metadata is not used. The header of bare
3849+
objects doesn't need to be initialized.
3850+
38453851
The optional ``tail_elems`` attributes specifies the amount of space to be
38463852
reserved for tail-allocated arrays of given element types and element counts.
38473853
If there are more than one ``tail_elems`` attributes then the tail arrays are

include/swift/SIL/SILBridging.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,14 @@ struct BridgedInstruction {
760760
getAs<swift::AllocRefInstBase>()->setStackAllocatable();
761761
}
762762

763+
bool AllocRefInst_isBare() const {
764+
return getAs<swift::AllocRefInst>()->isBare();
765+
}
766+
767+
void AllocRefInst_setIsBare() const {
768+
getAs<swift::AllocRefInst>()->setBare(true);
769+
}
770+
763771
inline void TermInst_replaceBranchTarget(BridgedBasicBlock from, BridgedBasicBlock to) const;
764772

765773
SwiftInt KeyPathInst_getNumComponents() const {

include/swift/SIL/SILBuilder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,14 +446,14 @@ class SILBuilder {
446446
}
447447

448448
AllocRefInst *createAllocRef(SILLocation Loc, SILType ObjectType,
449-
bool objc, bool canAllocOnStack,
449+
bool objc, bool canAllocOnStack, bool isBare,
450450
ArrayRef<SILType> ElementTypes,
451451
ArrayRef<SILValue> ElementCountOperands) {
452452
// AllocRefInsts expand to function calls and can therefore not be
453453
// counted towards the function prologue.
454454
assert(!Loc.isInPrologue());
455455
return insert(AllocRefInst::create(getSILDebugLocation(Loc), getFunction(),
456-
ObjectType, objc, canAllocOnStack,
456+
ObjectType, objc, canAllocOnStack, isBare,
457457
ElementTypes, ElementCountOperands));
458458
}
459459

include/swift/SIL/SILCloner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ SILCloner<ImplClass>::visitAllocRefInst(AllocRefInst *Inst) {
922922
}
923923
auto *NewInst = getBuilder().createAllocRef(getOpLocation(Inst->getLoc()),
924924
getOpType(Inst->getType()),
925-
Inst->isObjC(), Inst->canAllocOnStack(),
925+
Inst->isObjC(), Inst->canAllocOnStack(), Inst->isBare(),
926926
ElemTypes, CountArgs);
927927
recordClonedInstruction(Inst, NewInst);
928928
}

include/swift/SIL/SILInstruction.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,14 +2206,22 @@ class AllocRefInstBase : public AllocationInst {
22062206
AllocRefInstBase(SILInstructionKind Kind,
22072207
SILDebugLocation DebugLoc,
22082208
SILType ObjectType,
2209-
bool objc, bool canBeOnStack,
2209+
bool objc, bool canBeOnStack, bool isBare,
22102210
ArrayRef<SILType> ElementTypes);
22112211

22122212
SILType *getTypeStorage();
22132213
const SILType *getTypeStorage() const {
22142214
return const_cast<AllocRefInstBase*>(this)->getTypeStorage();
22152215
}
22162216

2217+
bool isBare() const {
2218+
return sharedUInt8().AllocRefInstBase.isBare;
2219+
}
2220+
2221+
void setBare(bool isBare = true) {
2222+
sharedUInt8().AllocRefInstBase.isBare = isBare;
2223+
}
2224+
22172225
public:
22182226
unsigned getNumTailTypes() const {
22192227
return sharedUInt8().AllocRefInstBase.numTailTypes;
@@ -2285,23 +2293,31 @@ class AllocRefInst final
22852293

22862294
AllocRefInst(SILDebugLocation DebugLoc, SILFunction &F,
22872295
SILType ObjectType,
2288-
bool objc, bool canBeOnStack,
2296+
bool objc, bool canBeOnStack, bool isBare,
22892297
ArrayRef<SILType> ElementTypes,
22902298
ArrayRef<SILValue> AllOperands)
22912299
: InstructionBaseWithTrailingOperands(AllOperands, DebugLoc, ObjectType,
2292-
objc, canBeOnStack, ElementTypes) {
2300+
objc, canBeOnStack, isBare, ElementTypes) {
22932301
assert(AllOperands.size() >= ElementTypes.size());
22942302
std::uninitialized_copy(ElementTypes.begin(), ElementTypes.end(),
22952303
getTrailingObjects<SILType>());
22962304
}
22972305

22982306
static AllocRefInst *create(SILDebugLocation DebugLoc, SILFunction &F,
22992307
SILType ObjectType,
2300-
bool objc, bool canBeOnStack,
2308+
bool objc, bool canBeOnStack, bool isBare,
23012309
ArrayRef<SILType> ElementTypes,
23022310
ArrayRef<SILValue> ElementCountOperands);
23032311

23042312
public:
2313+
bool isBare() const {
2314+
return AllocRefInstBase::isBare();
2315+
}
2316+
2317+
void setBare(bool isBare = true) {
2318+
AllocRefInstBase::setBare(isBare);
2319+
}
2320+
23052321
ArrayRef<Operand> getTypeDependentOperands() const {
23062322
return getAllOperands().slice(getNumTailTypes());
23072323
}
@@ -2332,7 +2348,7 @@ class AllocRefDynamicInst final
23322348
ArrayRef<SILType> ElementTypes,
23332349
ArrayRef<SILValue> AllOperands)
23342350
: InstructionBaseWithTrailingOperands(AllOperands, DebugLoc, ty, objc,
2335-
canBeOnStack, ElementTypes) {
2351+
canBeOnStack, /*isBare=*/ false, ElementTypes) {
23362352
assert(AllOperands.size() >= ElementTypes.size() + 1);
23372353
std::uninitialized_copy(ElementTypes.begin(), ElementTypes.end(),
23382354
getTrailingObjects<SILType>());

include/swift/SIL/SILNode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ class alignas(8) SILNode :
228228
SHARED_FIELD(AllocRefInstBase, uint8_t
229229
objC : 1,
230230
onStack : 1,
231+
isBare : 1, // Only used in AllocRefInst
231232
numTailTypes: NumAllocRefTailTypesBits);
232233

233234
SHARED_FIELD(BeginBorrowInst, uint8_t

lib/SIL/IR/SILInstructions.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,12 @@ AllocPackInst *AllocPackInst::create(SILDebugLocation loc,
317317
AllocRefInstBase::AllocRefInstBase(SILInstructionKind Kind,
318318
SILDebugLocation Loc,
319319
SILType ObjectType,
320-
bool objc, bool canBeOnStack,
320+
bool objc, bool canBeOnStack, bool isBare,
321321
ArrayRef<SILType> ElementTypes)
322322
: AllocationInst(Kind, Loc, ObjectType) {
323323
sharedUInt8().AllocRefInstBase.objC = objc;
324324
sharedUInt8().AllocRefInstBase.onStack = canBeOnStack;
325+
sharedUInt8().AllocRefInstBase.isBare = isBare;
325326
sharedUInt8().AllocRefInstBase.numTailTypes = ElementTypes.size();
326327
assert(sharedUInt8().AllocRefInstBase.numTailTypes ==
327328
ElementTypes.size() && "Truncation");
@@ -330,7 +331,7 @@ AllocRefInstBase::AllocRefInstBase(SILInstructionKind Kind,
330331

331332
AllocRefInst *AllocRefInst::create(SILDebugLocation Loc, SILFunction &F,
332333
SILType ObjectType,
333-
bool objc, bool canBeOnStack,
334+
bool objc, bool canBeOnStack, bool isBare,
334335
ArrayRef<SILType> ElementTypes,
335336
ArrayRef<SILValue> ElementCountOperands) {
336337
assert(ElementTypes.size() == ElementCountOperands.size());
@@ -341,7 +342,7 @@ AllocRefInst *AllocRefInst::create(SILDebugLocation Loc, SILFunction &F,
341342
auto Size = totalSizeToAlloc<swift::Operand, SILType>(AllOperands.size(),
342343
ElementTypes.size());
343344
auto Buffer = F.getModule().allocateInst(Size, alignof(AllocRefInst));
344-
return ::new (Buffer) AllocRefInst(Loc, F, ObjectType, objc, canBeOnStack,
345+
return ::new (Buffer) AllocRefInst(Loc, F, ObjectType, objc, canBeOnStack, isBare,
345346
ElementTypes, AllOperands);
346347
}
347348

lib/SIL/IR/SILPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
14521452
}
14531453

14541454
void visitAllocRefInst(AllocRefInst *ARI) {
1455+
if (ARI->isBare())
1456+
*this << "[bare] ";
14551457
printAllocRefInstBase(ARI);
14561458
*this << ARI->getType();
14571459
}

0 commit comments

Comments
 (0)