Skip to content

Commit d58f948

Browse files
committed
Reduce memory footprint of the Swift compiler
Use malloc/free for allocating/freeing SIL instructions instead of using the BumpPtrAllocator. This allows for memory reuse and significantly reduces the memory footprint of the compiler. For example, a peak memory usage during a compilation of the standard library and StdlibUnitTest is reduced by 25%-30%. The performance of the compiler seems to be not affected by this change, i.e. no slowdown is measured. rdar://23303031
1 parent f8029c7 commit d58f948

File tree

5 files changed

+60
-30
lines changed

5 files changed

+60
-30
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ class SILInstruction : public ValueBase,public llvm::ilist_node<SILInstruction>{
8181
: ValueBase(Kind, TypeList), ParentBB(0), DebugScope(DS), Loc(Loc) {}
8282

8383
public:
84+
/// Instructions should be allocated using a dedicated instruction allocation
85+
/// function from the ContextTy.
86+
template <typename ContextTy>
87+
void *operator new(size_t Bytes, const ContextTy &C,
88+
size_t Alignment = alignof(ValueBase)) {
89+
return C.allocateInst(Bytes, Alignment);
90+
}
8491

8592
enum class MemoryBehavior {
8693
None,

include/swift/SIL/SILModule.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -499,12 +499,12 @@ class SILModule {
499499
bool PrintASTDecls = true) const;
500500

501501
/// Allocate memory using the module's internal allocator.
502-
void *allocate(unsigned Size, unsigned Align) const {
503-
if (getASTContext().LangOpts.UseMalloc)
504-
return AlignedAlloc(Size, Align);
502+
void *allocate(unsigned Size, unsigned Align) const;
503+
504+
/// Allocate memory for an instruction using the module's internal allocator.
505+
void *allocateInst(unsigned Size, unsigned Align) const;
506+
505507

506-
return BPA.Allocate(Size, Align);
507-
}
508508

509509
/// \brief Looks up the llvm intrinsic ID and type for the builtin function.
510510
///

lib/SIL/SILInstruction.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,19 @@ void SILInstruction::replaceAllUsesWithUndef() {
167167
}
168168
}
169169

170+
namespace swift {
171+
void deallocate(void *Ptr) {
172+
AlignedFree(Ptr);
173+
}
174+
}
175+
170176
namespace {
171177
class InstructionDestroyer : public SILVisitor<InstructionDestroyer> {
172178
public:
173-
#define VALUE(CLASS, PARENT) void visit##CLASS(CLASS *I) { I->~CLASS(); }
179+
#define VALUE(CLASS, PARENT) void visit##CLASS(CLASS *I) { \
180+
I->~CLASS();\
181+
deallocate(I);\
182+
}
174183
#include "swift/SIL/SILNodes.def"
175184
};
176185
} // end anonymous namespace

lib/SIL/SILInstructions.cpp

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ AllocExistentialBoxInst::create(SILLocation Loc,
136136
ArrayRef<ProtocolConformance *> Conformances,
137137
SILFunction *F) {
138138
SILModule &Mod = F->getModule();
139-
void *Buffer = Mod.allocate(sizeof(AllocExistentialBoxInst),
140-
alignof(AllocExistentialBoxInst));
139+
void *Buffer = Mod.allocateInst(sizeof(AllocExistentialBoxInst),
140+
alignof(AllocExistentialBoxInst));
141141
for (ProtocolConformance *C : Conformances)
142142
declareWitnessTable(Mod, C);
143143
return ::new (Buffer) AllocExistentialBoxInst(Loc,
@@ -152,7 +152,7 @@ BuiltinInst *BuiltinInst::create(SILLocation Loc, Identifier Name,
152152
ArrayRef<Substitution> Substitutions,
153153
ArrayRef<SILValue> Args,
154154
SILFunction &F) {
155-
void *Buffer = F.getModule().allocate(
155+
void *Buffer = F.getModule().allocateInst(
156156
sizeof(BuiltinInst)
157157
+ decltype(Operands)::getExtraSize(Args.size())
158158
+ sizeof(Substitution) * Substitutions.size(),
@@ -209,7 +209,7 @@ bool swift::doesApplyCalleeHaveSemantics(SILValue callee, StringRef semantics) {
209209
}
210210

211211
void *swift::allocateApplyInst(SILFunction &F, size_t size, size_t alignment) {
212-
return F.getModule().allocate(size, alignment);
212+
return F.getModule().allocateInst(size, alignment);
213213
}
214214

215215
PartialApplyInst::PartialApplyInst(SILLocation Loc, SILValue Callee,
@@ -303,14 +303,14 @@ static unsigned getWordsForBitWidth(unsigned bits) {
303303

304304
template<typename INST>
305305
static void *allocateLiteralInstWithTextSize(SILFunction &F, unsigned length) {
306-
return F.getModule().allocate(sizeof(INST) + length, alignof(INST));
306+
return F.getModule().allocateInst(sizeof(INST) + length, alignof(INST));
307307
}
308308

309309
template<typename INST>
310310
static void *allocateLiteralInstWithBitSize(SILFunction &F, unsigned bits) {
311311
unsigned words = getWordsForBitWidth(bits);
312-
return F.getModule().allocate(sizeof(INST) + sizeof(llvm::integerPart)*words,
313-
alignof(INST));
312+
return F.getModule().allocateInst(
313+
sizeof(INST) + sizeof(llvm::integerPart)*words, alignof(INST));
314314
}
315315

316316
IntegerLiteralInst::IntegerLiteralInst(SILLocation Loc, SILType Ty,
@@ -442,7 +442,7 @@ AssignInst::AssignInst(SILLocation Loc, SILValue Src, SILValue Dest)
442442
MarkFunctionEscapeInst *
443443
MarkFunctionEscapeInst::create(SILLocation Loc,
444444
ArrayRef<SILValue> Elements, SILFunction &F) {
445-
void *Buffer = F.getModule().allocate(sizeof(MarkFunctionEscapeInst) +
445+
void *Buffer = F.getModule().allocateInst(sizeof(MarkFunctionEscapeInst) +
446446
decltype(Operands)::getExtraSize(Elements.size()),
447447
alignof(MarkFunctionEscapeInst));
448448
return ::new(Buffer) MarkFunctionEscapeInst(Loc, Elements);
@@ -499,7 +499,7 @@ UnconditionalCheckedCastAddrInst(SILLocation loc,
499499

500500
StructInst *StructInst::create(SILLocation Loc, SILType Ty,
501501
ArrayRef<SILValue> Elements, SILFunction &F) {
502-
void *Buffer = F.getModule().allocate(sizeof(StructInst) +
502+
void *Buffer = F.getModule().allocateInst(sizeof(StructInst) +
503503
decltype(Operands)::getExtraSize(Elements.size()),
504504
alignof(StructInst));
505505
return ::new(Buffer) StructInst(Loc, Ty, Elements);
@@ -512,7 +512,7 @@ StructInst::StructInst(SILLocation Loc, SILType Ty, ArrayRef<SILValue> Elems)
512512

513513
TupleInst *TupleInst::create(SILLocation Loc, SILType Ty,
514514
ArrayRef<SILValue> Elements, SILFunction &F) {
515-
void *Buffer = F.getModule().allocate(sizeof(TupleInst) +
515+
void *Buffer = F.getModule().allocateInst(sizeof(TupleInst) +
516516
decltype(Operands)::getExtraSize(Elements.size()),
517517
alignof(TupleInst));
518518
return ::new(Buffer) TupleInst(Loc, Ty, Elements);
@@ -717,7 +717,7 @@ BranchInst *BranchInst::create(SILLocation Loc,
717717
BranchInst *BranchInst::create(SILLocation Loc,
718718
SILBasicBlock *DestBB, ArrayRef<SILValue> Args,
719719
SILFunction &F) {
720-
void *Buffer = F.getModule().allocate(sizeof(BranchInst) +
720+
void *Buffer = F.getModule().allocateInst(sizeof(BranchInst) +
721721
decltype(Operands)::getExtraSize(Args.size()),
722722
alignof(BranchInst));
723723
return ::new (Buffer) BranchInst(Loc, DestBB, Args);
@@ -752,7 +752,7 @@ CondBranchInst *CondBranchInst::create(SILLocation Loc, SILValue Condition,
752752
Args.append(TrueArgs.begin(), TrueArgs.end());
753753
Args.append(FalseArgs.begin(), FalseArgs.end());
754754

755-
void *Buffer = F.getModule().allocate(sizeof(CondBranchInst) +
755+
void *Buffer = F.getModule().allocateInst(sizeof(CondBranchInst) +
756756
decltype(Operands)::getExtraSize(Args.size()),
757757
alignof(CondBranchInst));
758758
return ::new (Buffer) CondBranchInst(Loc, Condition, TrueBB, FalseBB, Args,
@@ -905,7 +905,7 @@ SwitchValueInst *SwitchValueInst::create(
905905
size_t bufSize = sizeof(SwitchValueInst) +
906906
decltype(Operands)::getExtraSize(Cases.size()) +
907907
sizeof(SILSuccessor) * numSuccessors;
908-
void *buf = F.getModule().allocate(bufSize, alignof(SwitchValueInst));
908+
void *buf = F.getModule().allocateInst(bufSize, alignof(SwitchValueInst));
909909
return ::new (buf) SwitchValueInst(Loc, Operand, DefaultBB, Cases, BBs);
910910
}
911911

@@ -956,7 +956,7 @@ SelectValueInst::create(SILLocation Loc, SILValue Operand, SILType Type,
956956

957957
size_t bufSize = sizeof(SelectValueInst) + decltype(Operands)::getExtraSize(
958958
CaseValuesAndResults.size());
959-
void *buf = F.getModule().allocate(bufSize, alignof(SelectValueInst));
959+
void *buf = F.getModule().allocateInst(bufSize, alignof(SelectValueInst));
960960
return ::new (buf)
961961
SelectValueInst(Loc, Operand, Type, DefaultResult, CaseValuesAndResults);
962962
}
@@ -999,7 +999,7 @@ SelectEnumInstBase::createSelectEnum(SILLocation Loc, SILValue Operand,
999999
// and `CaseBBs.size() + (DefaultBB ? 1 : 0)` values.
10001000
unsigned numCases = CaseValues.size();
10011001

1002-
void *buf = F.getModule().allocate(
1002+
void *buf = F.getModule().allocateInst(
10031003
sizeof(SELECT_ENUM_INST) + sizeof(EnumElementDecl*) * numCases
10041004
+ TailAllocatedOperandList<1>::getExtraSize(numCases + (bool)DefaultValue),
10051005
alignof(SELECT_ENUM_INST));
@@ -1125,7 +1125,7 @@ SwitchEnumInstBase::createSwitchEnum(SILLocation Loc, SILValue Operand,
11251125
unsigned numCases = CaseBBs.size();
11261126
unsigned numSuccessors = numCases + (DefaultBB ? 1 : 0);
11271127

1128-
void *buf = F.getModule().allocate(sizeof(SWITCH_ENUM_INST)
1128+
void *buf = F.getModule().allocateInst(sizeof(SWITCH_ENUM_INST)
11291129
+ sizeof(EnumElementDecl*) * numCases
11301130
+ sizeof(SILSuccessor) * numSuccessors,
11311131
alignof(SWITCH_ENUM_INST));
@@ -1195,8 +1195,8 @@ DynamicMethodBranchInst *DynamicMethodBranchInst::create(
11951195
SILBasicBlock *HasMethodBB,
11961196
SILBasicBlock *NoMethodBB,
11971197
SILFunction &F) {
1198-
void *Buffer = F.getModule().allocate(sizeof(DynamicMethodBranchInst),
1199-
alignof(DynamicMethodBranchInst));
1198+
void *Buffer = F.getModule().allocateInst(sizeof(DynamicMethodBranchInst),
1199+
alignof(DynamicMethodBranchInst));
12001200
return ::new (Buffer) DynamicMethodBranchInst(Loc, Operand, Member,
12011201
HasMethodBB, NoMethodBB);
12021202
}
@@ -1238,7 +1238,7 @@ WitnessMethodInst::create(SILLocation Loc, CanType LookupType,
12381238
SILValue OpenedExistential, bool Volatile) {
12391239
SILModule &Mod = F->getModule();
12401240
void *Buffer =
1241-
Mod.allocate(sizeof(WitnessMethodInst), alignof(WitnessMethodInst));
1241+
Mod.allocateInst(sizeof(WitnessMethodInst), alignof(WitnessMethodInst));
12421242

12431243
declareWitnessTable(Mod, Conformance);
12441244
return ::new (Buffer) WitnessMethodInst(Loc, LookupType, Conformance, Member,
@@ -1252,8 +1252,8 @@ InitExistentialAddrInst::create(SILLocation Loc, SILValue Existential,
12521252
ArrayRef<ProtocolConformance *> Conformances,
12531253
SILFunction *F) {
12541254
SILModule &Mod = F->getModule();
1255-
void *Buffer = Mod.allocate(sizeof(InitExistentialAddrInst),
1256-
alignof(InitExistentialAddrInst));
1255+
void *Buffer = Mod.allocateInst(sizeof(InitExistentialAddrInst),
1256+
alignof(InitExistentialAddrInst));
12571257
for (ProtocolConformance *C : Conformances)
12581258
declareWitnessTable(Mod, C);
12591259
return ::new (Buffer) InitExistentialAddrInst(Loc, Existential,
@@ -1269,8 +1269,8 @@ InitExistentialRefInst::create(SILLocation Loc, SILType ExistentialType,
12691269
ArrayRef<ProtocolConformance *> Conformances,
12701270
SILFunction *F) {
12711271
SILModule &Mod = F->getModule();
1272-
void *Buffer = Mod.allocate(sizeof(InitExistentialRefInst),
1273-
alignof(InitExistentialRefInst));
1272+
void *Buffer = Mod.allocateInst(sizeof(InitExistentialRefInst),
1273+
alignof(InitExistentialRefInst));
12741274
for (ProtocolConformance *C : Conformances) {
12751275
if (!C)
12761276
continue;
@@ -1307,7 +1307,7 @@ InitExistentialMetatypeInst::create(SILLocation loc,
13071307
unsigned size = sizeof(InitExistentialMetatypeInst);
13081308
size += conformances.size() * sizeof(ProtocolConformance *);
13091309

1310-
void *buffer = M.allocate(size, alignof(InitExistentialMetatypeInst));
1310+
void *buffer = M.allocateInst(size, alignof(InitExistentialMetatypeInst));
13111311
for (ProtocolConformance *conformance : conformances)
13121312
if (!M.lookUpWitnessTable(conformance, false).first)
13131313
declareWitnessTable(M, conformance);

lib/SIL/SILModule.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,20 @@ SILModule::~SILModule() {
124124
delete (SILTypeListUniquingType*)TypeListUniquing;
125125
}
126126

127+
void *SILModule::allocate(unsigned Size, unsigned Align) const {
128+
if (getASTContext().LangOpts.UseMalloc)
129+
return AlignedAlloc(Size, Align);
130+
131+
return BPA.Allocate(Size, Align);
132+
}
133+
134+
void *SILModule::allocateInst(unsigned Size, unsigned Align) const {
135+
if (true || getASTContext().LangOpts.UseMalloc)
136+
return AlignedAlloc(Size, Align);
137+
138+
return BPA.Allocate(Size, Align);
139+
}
140+
127141
SILWitnessTable *
128142
SILModule::createWitnessTableDeclaration(ProtocolConformance *C,
129143
SILLinkage linkage) {

0 commit comments

Comments
 (0)