Skip to content

Commit 65208c0

Browse files
committed
SIL: efficiently store SILLocation in SILInstruction
Store the 1-byte kindAndFlags of SILLocation in the instruction's SILNode bitfield and only store SILLocation::storage in SILInstruction directly. This reduces the space for the location from 2 to 1 word in SILInstruction.
1 parent ec64f2a commit 65208c0

File tree

4 files changed

+45
-23
lines changed

4 files changed

+45
-23
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,17 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
323323

324324
/// A backreference to the containing basic block. This is maintained by
325325
/// ilist_traits<SILInstruction>.
326-
SILBasicBlock *ParentBB;
326+
SILBasicBlock *ParentBB = nullptr;
327327

328-
/// This instruction's containing lexical scope and source location
329-
/// used for debug info and diagnostics.
330-
SILDebugLocation Location;
328+
/// This instruction's containing lexical scope for debug info.
329+
const SILDebugScope *debugScope = nullptr;
330+
331+
/// This instructions source location for diagnostics and debug info.
332+
///
333+
/// To reduce space, this is only the storage of the SILLocation. The
334+
/// location's kindAndFlags is stored in the SILNode inline bitfields.
335+
SILLocation::Storage locationStorage;
331336

332-
SILInstruction() = delete;
333337
void operator=(const SILInstruction &) = delete;
334338
void operator delete(void *Ptr, size_t) = delete;
335339

@@ -360,8 +364,7 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
360364
SILInstructionResultArray getResultsImpl() const;
361365

362366
protected:
363-
SILInstruction(SILDebugLocation DebugLoc) :
364-
ParentBB(nullptr), Location(DebugLoc) {
367+
SILInstruction() {
365368
NumCreatedInstructions++;
366369
}
367370

@@ -423,14 +426,25 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
423426
SILModule &getModule() const;
424427

425428
/// This instruction's source location (AST node).
426-
SILLocation getLoc() const;
427-
const SILDebugScope *getDebugScope() const;
428-
SILDebugLocation getDebugLocation() const { return Location; }
429+
SILLocation getLoc() const {
430+
return SILLocation(locationStorage,
431+
asSILNode()->Bits.SILInstruction.LocationKindAndFlags);
432+
}
433+
const SILDebugScope *getDebugScope() const { return debugScope; }
434+
SILDebugLocation getDebugLocation() const {
435+
return SILDebugLocation(getLoc(), debugScope);
436+
}
429437

430438
/// Sets the debug location.
431439
/// Note: Usually it should not be needed to use this function as the location
432440
/// is already set in when creating an instruction.
433-
void setDebugLocation(SILDebugLocation Loc) { Location = Loc; }
441+
void setDebugLocation(SILDebugLocation debugLoc) {
442+
debugScope = debugLoc.getScope();
443+
SILLocation loc = debugLoc.getLocation();
444+
asSILNode()->Bits.SILInstruction.LocationKindAndFlags =
445+
loc.kindAndFlags.packedKindAndFlags;
446+
locationStorage = loc.storage;
447+
}
434448

435449
/// This method unlinks 'self' from the containing basic block and deletes it.
436450
void eraseFromParent();
@@ -758,7 +772,9 @@ class NonSingleValueInstruction : public SILInstruction, public SILNode {
758772
friend struct SILNodeOffsetChecker;
759773
public:
760774
NonSingleValueInstruction(SILInstructionKind kind, SILDebugLocation loc)
761-
: SILInstruction(loc), SILNode((SILNodeKind)kind) {}
775+
: SILInstruction(), SILNode((SILNodeKind)kind) {
776+
setDebugLocation(loc);
777+
}
762778

763779
using SILInstruction::operator new;
764780
using SILInstruction::dumpInContext;
@@ -929,8 +945,9 @@ class SingleValueInstruction : public SILInstruction, public ValueBase {
929945
public:
930946
SingleValueInstruction(SILInstructionKind kind, SILDebugLocation loc,
931947
SILType type)
932-
: SILInstruction(loc),
933-
ValueBase(ValueKind(kind), type) {}
948+
: SILInstruction(), ValueBase(ValueKind(kind), type) {
949+
setDebugLocation(loc);
950+
}
934951

935952
using SILInstruction::operator new;
936953
using SILInstruction::dumpInContext;

include/swift/SIL/SILLocation.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ class SILLocation {
119119
};
120120

121121
private:
122+
friend class SILInstruction;
123+
122124
/// Each kind corresponds to a union member in `Storage`.
123125
enum StorageKind : uint8_t {
124126
/// For usages see the struct `FilenameAndLocation`.
@@ -164,6 +166,7 @@ class SILLocation {
164166
/// Contains the LocationKind, StorageKind and some extra flags.
165167
/// This fits nicely in a single byte. If for some reason we need more flags
166168
/// it's possible to extend this to e.g. a uint16_t.
169+
/// But SILNode::Bits.LocationKindAndFlags must be updated accordingly.
167170
union KindAndFlags {
168171
KindAndFlags() : packedKindAndFlags(0) {}
169172
KindAndFlags(LocationKind kind, StorageKind storageKind)
@@ -266,6 +269,10 @@ class SILLocation {
266269
SILLocation(SourceLoc L, LocationKind K)
267270
: storage(L), kindAndFlags(K, SourceLocKind) {}
268271

272+
// Used by SILInstruction.
273+
SILLocation(Storage storage, uint8_t packedKindAndFlags) :
274+
storage(storage), kindAndFlags(packedKindAndFlags) {}
275+
269276
public:
270277
// When an ASTNode gets implicitly converted into a SILLocation we
271278
// construct a RegularLocation. Since RegularLocations represent the majority

include/swift/SIL/SILNode.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ class alignas(8) SILNode {
124124
enum { NumSILAccessEnforcementBits = 2 };
125125

126126
protected:
127+
friend class SILInstruction;
128+
127129
union { uint64_t OpaqueBits;
128130

129131
SWIFT_INLINE_BITFIELD_BASE(SILNode, bitmax(NumSILNodeKindBits,8),
@@ -145,7 +147,9 @@ class alignas(8) SILNode {
145147
Index : 32
146148
);
147149

148-
SWIFT_INLINE_BITFIELD_EMPTY(SILInstruction, SILNode);
150+
SWIFT_INLINE_BITFIELD(SILInstruction, SILNode, 8,
151+
LocationKindAndFlags : 8
152+
);
149153

150154
// Special handling for UnaryInstructionWithTypeDependentOperandsBase
151155
SWIFT_INLINE_BITFIELD(IBWTO, SILNode, 64-NumSILNodeBits,
@@ -227,7 +231,7 @@ class alignas(8) SILNode {
227231
OnStack : 1,
228232
NumTailTypes : 32-1-1-NumAllocationInstBits
229233
);
230-
static_assert(32-1-1-NumAllocationInstBits >= 16, "Reconsider bitfield use?");
234+
static_assert(32-1-1-NumAllocationInstBits >= 14, "Reconsider bitfield use?");
231235

232236
UIWTDOB_BITFIELD_EMPTY(AllocValueBufferInst, AllocationInst);
233237

lib/SIL/IR/SILInstruction.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,14 @@ using namespace Lowering;
3636
// Instruction-specific properties on SILValue
3737
//===----------------------------------------------------------------------===//
3838

39-
SILLocation SILInstruction::getLoc() const { return Location.getLocation(); }
40-
41-
const SILDebugScope *SILInstruction::getDebugScope() const {
42-
return Location.getScope();
43-
}
44-
4539
void SILInstruction::setDebugScope(const SILDebugScope *DS) {
4640
if (getDebugScope() && getDebugScope()->InlinedCallSite)
4741
assert(DS->InlinedCallSite && "throwing away inlined scope info");
4842

4943
assert(DS->getParentFunction() == getFunction() &&
5044
"scope belongs to different function");
5145

52-
Location = SILDebugLocation(getLoc(), DS);
46+
debugScope = DS;
5347
}
5448

5549
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)