Skip to content

Commit 45b84b8

Browse files
authored
Merge pull request #39053 from gmittert/TypeLayoutEnhancementsUpstream
TypeLayout: Use AlignedGroups instead of ScalarLayouts
2 parents e460a7d + b3c9316 commit 45b84b8

File tree

9 files changed

+1048
-198
lines changed

9 files changed

+1048
-198
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ class IRGenOptions {
335335
/// vw functions instead of outlined copy/destroy functions.
336336
unsigned UseTypeLayoutValueHandling : 1;
337337

338+
/// Also force structs to be lowered to aligned group TypeLayouts rather than
339+
/// using TypeInfo entries.
340+
unsigned ForceStructTypeLayouts : 1;
341+
338342
/// Instrument code to generate profiling information.
339343
unsigned GenerateProfile : 1;
340344

@@ -413,7 +417,7 @@ class IRGenOptions {
413417
ForcePublicLinkage(false), LazyInitializeClassMetadata(false),
414418
LazyInitializeProtocolConformances(false), DisableLegacyTypeInfo(false),
415419
PrespecializeGenericMetadata(false), UseIncrementalLLVMCodeGen(true),
416-
UseTypeLayoutValueHandling(true),
420+
UseTypeLayoutValueHandling(true), ForceStructTypeLayouts(false),
417421
GenerateProfile(false), EnableDynamicReplacementChaining(false),
418422
DisableRoundTripDebugTypes(false), DisableDebuggerShadowCopies(false),
419423
DisableConcreteTypeMetadataMangledNameAccessors(false),

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,9 @@ def enable_type_layouts : Flag<["-"], "enable-type-layout">,
830830
def disable_type_layouts : Flag<["-"], "disable-type-layout">,
831831
HelpText<"Disable type layout based lowering">;
832832

833+
def force_struct_type_layouts : Flag<["-"], "force-struct-type-layouts">,
834+
HelpText<"Force type layout based lowering for structs">;
835+
833836
def disable_interface_lockfile : Flag<["-"], "disable-interface-lock">,
834837
HelpText<"Don't lock interface file when building module">;
835838

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,9 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
17241724
Opts.UseTypeLayoutValueHandling = false;
17251725
}
17261726

1727+
Opts.ForceStructTypeLayouts = Args.hasArg(OPT_force_struct_type_layouts) &&
1728+
Opts.UseTypeLayoutValueHandling;
1729+
17271730
// This is set to true by default.
17281731
Opts.UseIncrementalLLVMCodeGen &=
17291732
!Args.hasArg(OPT_disable_incremental_llvm_codegeneration);

lib/IRGen/GenDiffFunc.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "swift/AST/Decl.h"
19+
#include "swift/AST/IRGenOptions.h"
1920
#include "swift/AST/Pattern.h"
2021
#include "swift/AST/Types.h"
2122
#include "swift/SIL/SILModule.h"
@@ -118,7 +119,25 @@ class DifferentiableFuncTypeInfo final
118119

119120
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
120121
SILType T) const override {
121-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
122+
if (!IGM.getOptions().ForceStructTypeLayouts || !areFieldsABIAccessible()) {
123+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
124+
}
125+
126+
if (getFields().empty()) {
127+
return IGM.typeLayoutCache.getEmptyEntry();
128+
}
129+
130+
std::vector<TypeLayoutEntry *> fields;
131+
for (auto &field : getFields()) {
132+
auto fieldTy = field.getType(IGM, T);
133+
fields.push_back(field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy));
134+
}
135+
136+
if (fields.size() == 1) {
137+
return fields[0];
138+
}
139+
140+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
122141
}
123142

124143
llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF) const { return None; }
@@ -272,7 +291,25 @@ class LinearFuncTypeInfo final
272291

273292
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
274293
SILType T) const override {
275-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
294+
if (!IGM.getOptions().ForceStructTypeLayouts || !areFieldsABIAccessible()) {
295+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
296+
}
297+
298+
if (getFields().empty()) {
299+
return IGM.typeLayoutCache.getEmptyEntry();
300+
}
301+
302+
std::vector<TypeLayoutEntry *> fields;
303+
for (auto &field : getFields()) {
304+
auto fieldTy = field.getType(IGM, T);
305+
fields.push_back(field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy));
306+
}
307+
308+
if (fields.size() == 1) {
309+
return fields[0];
310+
}
311+
312+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
276313
}
277314

278315
llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF) const { return None; }

lib/IRGen/GenStruct.cpp

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,27 @@ namespace {
354354

355355
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
356356
SILType T) const override {
357-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
357+
if (!IGM.getOptions().ForceStructTypeLayouts) {
358+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
359+
}
360+
if (!areFieldsABIAccessible()) {
361+
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
362+
}
363+
364+
std::vector<TypeLayoutEntry *> fields;
365+
for (auto &field : getFields()) {
366+
auto fieldTy = field.getType(IGM, T);
367+
fields.push_back(
368+
field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy));
369+
}
370+
assert(!fields.empty() &&
371+
"Empty structs should not be LoadableClangRecordTypeInfo");
372+
373+
if (fields.size() == 1) {
374+
return fields[0];
375+
}
376+
377+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
358378
}
359379

360380
void initializeFromParams(IRGenFunction &IGF, Explosion &params,
@@ -520,7 +540,25 @@ namespace {
520540

521541
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
522542
SILType T) const override {
523-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
543+
if (!IGM.getOptions().ForceStructTypeLayouts || getCXXDestructor(T) ||
544+
!areFieldsABIAccessible()) {
545+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
546+
}
547+
548+
std::vector<TypeLayoutEntry *> fields;
549+
for (auto &field : getFields()) {
550+
auto fieldTy = field.getType(IGM, T);
551+
fields.push_back(
552+
field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy));
553+
}
554+
assert(!fields.empty() &&
555+
"Empty structs should not be AddressOnlyRecordTypeInfo");
556+
557+
if (fields.size() == 1) {
558+
return fields[0];
559+
}
560+
561+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
524562
}
525563

526564
void initializeFromParams(IRGenFunction &IGF, Explosion &params,
@@ -583,7 +621,30 @@ namespace {
583621

584622
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
585623
SILType T) const override {
586-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
624+
if (!IGM.getOptions().ForceStructTypeLayouts) {
625+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
626+
}
627+
628+
if (!areFieldsABIAccessible()) {
629+
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
630+
}
631+
632+
if (getFields().empty()) {
633+
return IGM.typeLayoutCache.getEmptyEntry();
634+
}
635+
636+
std::vector<TypeLayoutEntry *> fields;
637+
for (auto &field : getFields()) {
638+
auto fieldTy = field.getType(IGM, T);
639+
fields.push_back(
640+
field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy));
641+
}
642+
643+
if (fields.size() == 1) {
644+
return fields[0];
645+
}
646+
647+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
587648
}
588649

589650
void initializeFromParams(IRGenFunction &IGF, Explosion &params,
@@ -622,7 +683,28 @@ namespace {
622683

623684
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
624685
SILType T) const override {
625-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
686+
if (!IGM.getOptions().ForceStructTypeLayouts) {
687+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
688+
}
689+
690+
if (!areFieldsABIAccessible()) {
691+
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
692+
}
693+
694+
std::vector<TypeLayoutEntry *> fields;
695+
for (auto &field : getFields()) {
696+
auto fieldTy = field.getType(IGM, T);
697+
fields.push_back(
698+
field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy));
699+
}
700+
assert(!fields.empty() &&
701+
"Empty structs should not be FixedStructTypeInfo");
702+
703+
if (fields.size() == 1) {
704+
return fields[0];
705+
}
706+
707+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
626708
}
627709

628710
llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF) const {
@@ -708,7 +790,7 @@ namespace {
708790
return fields[0];
709791
}
710792

711-
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1, false);
793+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
712794
}
713795

714796
// We have an indirect schema.

lib/IRGen/GenTuple.cpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
//
2121
//===----------------------------------------------------------------------===//
2222

23-
#include "swift/AST/Types.h"
2423
#include "swift/AST/Decl.h"
24+
#include "swift/AST/IRGenOptions.h"
2525
#include "swift/AST/Pattern.h"
26+
#include "swift/AST/Types.h"
2627
#include "swift/SIL/SILModule.h"
2728
#include "swift/SIL/SILType.h"
2829
#include "llvm/IR/DerivedTypes.h"
@@ -231,7 +232,23 @@ namespace {
231232

232233
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
233234
SILType T) const override {
234-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
235+
if (!IGM.getOptions().ForceStructTypeLayouts) {
236+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
237+
}
238+
if (getFields().empty()) {
239+
return IGM.typeLayoutCache.getEmptyEntry();
240+
}
241+
242+
std::vector<TypeLayoutEntry *> fields;
243+
for (auto &field : getFields()) {
244+
auto fieldTy = field.getType(IGM, T);
245+
fields.push_back(
246+
field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy));
247+
}
248+
if (fields.size() == 1) {
249+
return fields[0];
250+
}
251+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
235252
}
236253

237254
llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF) const {
@@ -260,7 +277,24 @@ namespace {
260277

261278
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
262279
SILType T) const override {
263-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
280+
if (!IGM.getOptions().ForceStructTypeLayouts) {
281+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
282+
}
283+
if (getFields().empty()) {
284+
return IGM.typeLayoutCache.getEmptyEntry();
285+
}
286+
287+
std::vector<TypeLayoutEntry *> fields;
288+
for (auto &field : getFields()) {
289+
auto fieldTy = field.getType(IGM, T);
290+
fields.push_back(
291+
field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy));
292+
}
293+
if (fields.size() == 1) {
294+
return fields[0];
295+
}
296+
297+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
264298
}
265299

266300
llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF) const {
@@ -329,10 +363,9 @@ namespace {
329363
return fields[0];
330364
}
331365

332-
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1, false);
366+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(fields, 1);
333367
}
334368

335-
336369
llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
337370
llvm::Value *numEmptyCases,
338371
Address structAddr,

0 commit comments

Comments
 (0)