Skip to content

Commit a48591d

Browse files
committed
Sema: Tail-allocate Constraint::TheFix
Most constraints don't have a fix, so we can tail-allocate the fix. This saves 16 bytes per constraint, because it also eliminates some padding.
1 parent 308b4f4 commit a48591d

File tree

2 files changed

+62
-34
lines changed

2 files changed

+62
-34
lines changed

include/swift/Sema/Constraint.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ enum RememberChoice_t : bool {
344344

345345
/// A constraint between two type variables.
346346
class Constraint final : public llvm::ilist_node<Constraint>,
347-
private llvm::TrailingObjects<Constraint, TypeVariableType *> {
347+
private llvm::TrailingObjects<Constraint, TypeVariableType *, ConstraintFix *> {
348348
friend TrailingObjects;
349349

350350
/// The kind of constraint.
@@ -353,8 +353,8 @@ class Constraint final : public llvm::ilist_node<Constraint>,
353353
/// The kind of restriction placed on this constraint.
354354
ConversionRestrictionKind Restriction : 8;
355355

356-
/// The fix to be applied to the constraint before visiting it.
357-
ConstraintFix *TheFix = nullptr;
356+
/// Whether we have a fix.
357+
unsigned HasFix : 1;
358358

359359
/// Whether the \c Restriction field is valid.
360360
unsigned HasRestriction : 1;
@@ -514,6 +514,14 @@ class Constraint final : public llvm::ilist_node<Constraint>,
514514
return { getTrailingObjects<TypeVariableType *>(), NumTypeVariables };
515515
}
516516

517+
size_t numTrailingObjects(OverloadToken<TypeVariableType *>) const {
518+
return NumTypeVariables;
519+
}
520+
521+
size_t numTrailingObjects(OverloadToken<ConstraintFix *>) const {
522+
return HasFix ? 1 : 0;
523+
}
524+
517525
public:
518526
/// Create a new constraint.
519527
static Constraint *create(ConstraintSystem &cs, ConstraintKind Kind,
@@ -616,7 +624,11 @@ class Constraint final : public llvm::ilist_node<Constraint>,
616624
}
617625

618626
/// Retrieve the fix associated with this constraint.
619-
ConstraintFix *getFix() const { return TheFix; }
627+
ConstraintFix *getFix() const {
628+
if (HasFix)
629+
return *getTrailingObjects<ConstraintFix *>();
630+
return nullptr;
631+
}
620632

621633
/// Whether this constraint is active, i.e., in the worklist.
622634
bool isActive() const { return IsActive; }

lib/Sema/Constraint.cpp

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ using namespace constraints;
3030
Constraint::Constraint(ConstraintKind kind, ArrayRef<Constraint *> constraints,
3131
bool isIsolated, ConstraintLocator *locator,
3232
SmallPtrSetImpl<TypeVariableType *> &typeVars)
33-
: Kind(kind), HasRestriction(false), IsActive(false), IsDisabled(false),
34-
IsDisabledForPerformance(false), RememberChoice(false), IsFavored(false),
35-
IsIsolated(isIsolated), NumTypeVariables(typeVars.size()),
33+
: Kind(kind), HasFix(false), HasRestriction(false), IsActive(false),
34+
IsDisabled(false), IsDisabledForPerformance(false), RememberChoice(false),
35+
IsFavored(false), IsIsolated(isIsolated), NumTypeVariables(typeVars.size()),
3636
Nested(constraints), Locator(locator) {
3737
assert(kind == ConstraintKind::Disjunction ||
3838
kind == ConstraintKind::Conjunction);
@@ -50,9 +50,9 @@ Constraint::Constraint(ConstraintKind kind, ArrayRef<Constraint *> constraints,
5050
Constraint::Constraint(ConstraintKind Kind, Type First, Type Second,
5151
ConstraintLocator *locator,
5252
SmallPtrSetImpl<TypeVariableType *> &typeVars)
53-
: Kind(Kind), HasRestriction(false), IsActive(false), IsDisabled(false),
54-
IsDisabledForPerformance(false), RememberChoice(false), IsFavored(false),
55-
IsIsolated(false),
53+
: Kind(Kind), HasFix(false), HasRestriction(false), IsActive(false),
54+
IsDisabled(false), IsDisabledForPerformance(false), RememberChoice(false),
55+
IsFavored(false), IsIsolated(false),
5656
NumTypeVariables(typeVars.size()), Types{First, Second, Type()},
5757
Locator(locator) {
5858
switch (Kind) {
@@ -131,9 +131,9 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second,
131131
Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, Type Third,
132132
ConstraintLocator *locator,
133133
SmallPtrSetImpl<TypeVariableType *> &typeVars)
134-
: Kind(Kind), HasRestriction(false), IsActive(false), IsDisabled(false),
135-
IsDisabledForPerformance(false), RememberChoice(false), IsFavored(false),
136-
IsIsolated(false),
134+
: Kind(Kind), HasFix(false), HasRestriction(false), IsActive(false),
135+
IsDisabled(false), IsDisabledForPerformance(false), RememberChoice(false),
136+
IsFavored(false), IsIsolated(false),
137137
NumTypeVariables(typeVars.size()), Types{First, Second, Third},
138138
Locator(locator) {
139139
switch (Kind) {
@@ -197,9 +197,9 @@ Constraint::Constraint(ConstraintKind kind, Type first, Type second,
197197
FunctionRefKind functionRefKind,
198198
ConstraintLocator *locator,
199199
SmallPtrSetImpl<TypeVariableType *> &typeVars)
200-
: Kind(kind), HasRestriction(false), IsActive(false), IsDisabled(false),
201-
IsDisabledForPerformance(false), RememberChoice(false), IsFavored(false),
202-
IsIsolated(false),
200+
: Kind(kind), HasFix(false), HasRestriction(false), IsActive(false),
201+
IsDisabled(false), IsDisabledForPerformance(false), RememberChoice(false),
202+
IsFavored(false), IsIsolated(false),
203203
NumTypeVariables(typeVars.size()), Member{first, second, {member}, useDC},
204204
Locator(locator) {
205205
assert(kind == ConstraintKind::ValueMember ||
@@ -217,9 +217,10 @@ Constraint::Constraint(ConstraintKind kind, Type first, Type second,
217217
FunctionRefKind functionRefKind,
218218
ConstraintLocator *locator,
219219
SmallPtrSetImpl<TypeVariableType *> &typeVars)
220-
: Kind(kind), HasRestriction(false), IsActive(false), IsDisabled(false),
221-
IsDisabledForPerformance(false), RememberChoice(false), IsFavored(false),
222-
IsIsolated(false), NumTypeVariables(typeVars.size()), Locator(locator) {
220+
: Kind(kind), HasFix(false), HasRestriction(false), IsActive(false),
221+
IsDisabled(false), IsDisabledForPerformance(false), RememberChoice(false),
222+
IsFavored(false), IsIsolated(false), NumTypeVariables(typeVars.size()),
223+
Locator(locator) {
223224
Member.First = first;
224225
Member.Second = second;
225226
Member.Member.Ref = requirement;
@@ -237,19 +238,21 @@ Constraint::Constraint(ConstraintKind kind, Type first, Type second,
237238
Constraint::Constraint(Type type, OverloadChoice choice, DeclContext *useDC,
238239
ConstraintFix *fix, ConstraintLocator *locator,
239240
SmallPtrSetImpl<TypeVariableType *> &typeVars)
240-
: Kind(ConstraintKind::BindOverload), TheFix(fix), HasRestriction(false),
241+
: Kind(ConstraintKind::BindOverload), HasFix(fix != nullptr), HasRestriction(false),
241242
IsActive(false), IsDisabled(bool(fix)), IsDisabledForPerformance(false),
242243
RememberChoice(false), IsFavored(false), IsIsolated(false),
243244
NumTypeVariables(typeVars.size()), Overload{type, choice, useDC},
244245
Locator(locator) {
245246
std::copy(typeVars.begin(), typeVars.end(), getTypeVariablesBuffer().begin());
247+
if (fix)
248+
*getTrailingObjects<ConstraintFix *>() = fix;
246249
}
247250

248251
Constraint::Constraint(ConstraintKind kind,
249252
ConversionRestrictionKind restriction, Type first,
250253
Type second, ConstraintLocator *locator,
251254
SmallPtrSetImpl<TypeVariableType *> &typeVars)
252-
: Kind(kind), Restriction(restriction), HasRestriction(true),
255+
: Kind(kind), Restriction(restriction), HasFix(false), HasRestriction(true),
253256
IsActive(false), IsDisabled(false), IsDisabledForPerformance(false),
254257
RememberChoice(false), IsFavored(false), IsIsolated(false),
255258
NumTypeVariables(typeVars.size()), Types{first, second, Type()},
@@ -262,20 +265,22 @@ Constraint::Constraint(ConstraintKind kind,
262265
Constraint::Constraint(ConstraintKind kind, ConstraintFix *fix, Type first,
263266
Type second, ConstraintLocator *locator,
264267
SmallPtrSetImpl<TypeVariableType *> &typeVars)
265-
: Kind(kind), TheFix(fix), HasRestriction(false), IsActive(false),
268+
: Kind(kind), HasFix(fix != nullptr), HasRestriction(false), IsActive(false),
266269
IsDisabled(false), IsDisabledForPerformance(false), RememberChoice(false),
267270
IsFavored(false), IsIsolated(false),
268271
NumTypeVariables(typeVars.size()), Types{first, second, Type()},
269272
Locator(locator) {
270273
assert(!first.isNull());
271274
assert(!second.isNull());
272275
std::copy(typeVars.begin(), typeVars.end(), getTypeVariablesBuffer().begin());
276+
if (fix)
277+
*getTrailingObjects<ConstraintFix *>() = fix;
273278
}
274279

275280
Constraint::Constraint(ASTNode node, ContextualTypeInfo context,
276281
bool isDiscarded, ConstraintLocator *locator,
277282
SmallPtrSetImpl<TypeVariableType *> &typeVars)
278-
: Kind(ConstraintKind::SyntacticElement), TheFix(nullptr),
283+
: Kind(ConstraintKind::SyntacticElement), HasFix(false),
279284
HasRestriction(false), IsActive(false), IsDisabled(false),
280285
IsDisabledForPerformance(false), RememberChoice(false), IsFavored(false),
281286
IsIsolated(false),
@@ -833,7 +838,8 @@ Constraint *Constraint::create(ConstraintSystem &cs, ConstraintKind kind,
833838
second->is<ProtocolType>());
834839

835840
// Create the constraint.
836-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
841+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
842+
typeVars.size(), /*hasFix=*/0);
837843
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
838844
return ::new (mem) Constraint(kind, first, second, locator, typeVars);
839845
}
@@ -852,7 +858,8 @@ Constraint *Constraint::create(ConstraintSystem &cs, ConstraintKind kind,
852858
if (third->hasTypeVariable())
853859
third->getTypeVariables(typeVars);
854860

855-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
861+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
862+
typeVars.size(), /*hasFix=*/0);
856863
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
857864
return ::new (mem) Constraint(kind,
858865
first, second, third,
@@ -892,7 +899,8 @@ Constraint *Constraint::createMember(ConstraintSystem &cs, ConstraintKind kind,
892899
second->getTypeVariables(typeVars);
893900

894901
// Create the constraint.
895-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
902+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
903+
typeVars.size(), /*hasFix=*/0);
896904
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
897905
return new (mem) Constraint(kind, first, second, member, useDC,
898906
functionRefKind, locator, typeVars);
@@ -912,7 +920,8 @@ Constraint *Constraint::createValueWitness(
912920
second->getTypeVariables(typeVars);
913921

914922
// Create the constraint.
915-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
923+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
924+
typeVars.size(), /*hasFix=*/0);
916925
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
917926
return new (mem) Constraint(kind, first, second, requirement, useDC,
918927
functionRefKind, locator, typeVars);
@@ -938,7 +947,8 @@ Constraint *Constraint::createRestricted(ConstraintSystem &cs,
938947
second->getTypeVariables(typeVars);
939948

940949
// Create the constraint.
941-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
950+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
951+
typeVars.size(), /*hasFix=*/0);
942952
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
943953
return new (mem) Constraint(kind, restriction, first, second, locator,
944954
typeVars);
@@ -955,7 +965,8 @@ Constraint *Constraint::createFixed(ConstraintSystem &cs, ConstraintKind kind,
955965
second->getTypeVariables(typeVars);
956966

957967
// Create the constraint.
958-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
968+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
969+
typeVars.size(), fix ? 1 : 0);
959970
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
960971
return new (mem) Constraint(kind, fix, first, second, locator, typeVars);
961972
}
@@ -974,7 +985,8 @@ Constraint *Constraint::createFixedChoice(ConstraintSystem &cs, Type type,
974985
}
975986

976987
// Create the constraint.
977-
unsigned size = totalSizeToAlloc<TypeVariableType *>(typeVars.size());
988+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
989+
typeVars.size(), fix ? 1 : 0);
978990
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
979991
return new (mem) Constraint(type, choice, useDC, fix, locator, typeVars);
980992
}
@@ -1044,7 +1056,8 @@ Constraint *Constraint::createDisjunction(ConstraintSystem &cs,
10441056
#endif
10451057

10461058
// Create the disjunction constraint.
1047-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
1059+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
1060+
typeVars.size(), /*hasFix=*/0);
10481061
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
10491062
auto disjunction = new (mem)
10501063
Constraint(ConstraintKind::Disjunction, cs.allocateCopy(constraints),
@@ -1063,7 +1076,8 @@ Constraint *Constraint::createConjunction(
10631076
// because each have to be solved in isolation.
10641077

10651078
assert(!constraints.empty() && "Empty conjunction constraint");
1066-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
1079+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
1080+
typeVars.size(), /*hasFix=*/0);
10671081
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
10681082
auto conjunction = new (mem)
10691083
Constraint(ConstraintKind::Conjunction, cs.allocateCopy(constraints),
@@ -1083,7 +1097,8 @@ Constraint *Constraint::createApplicableFunction(
10831097
calleeType->getTypeVariables(typeVars);
10841098

10851099
// Create the constraint.
1086-
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
1100+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
1101+
typeVars.size(), /*hasFix=*/0);
10871102
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
10881103
auto constraint = new (mem) Constraint(
10891104
ConstraintKind::ApplicableFunction, argumentFnType, calleeType, locator,
@@ -1125,7 +1140,8 @@ Constraint *Constraint::createSyntacticElement(ConstraintSystem &cs,
11251140
if (auto contextTy = context.getType())
11261141
contextTy->getTypeVariables(typeVars);
11271142

1128-
unsigned size = totalSizeToAlloc<TypeVariableType *>(typeVars.size());
1143+
auto size = totalSizeToAlloc<TypeVariableType *, ConstraintFix *>(
1144+
typeVars.size(), /*hasFix=*/0);
11291145
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
11301146
return new (mem) Constraint(node, context, isDiscarded, locator, typeVars);
11311147
}

0 commit comments

Comments
 (0)