Skip to content

Commit 9583261

Browse files
authored
Merge pull request #29326 from eeckstein/irgen-for-merge-functions
IRGen: in multi-threaded compilation, create all specializations of a function in the same LLVM module.
2 parents 5a75996 + cabcecc commit 9583261

File tree

6 files changed

+46
-1
lines changed

6 files changed

+46
-1
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,10 @@ class SILFunction
863863
validateSubclassScope(getClassSubclassScope(), isThunk(), Info);
864864
SpecializationInfo = Info;
865865
}
866+
867+
/// If this function is a specialization, return the original function from
868+
/// which this function was specialized.
869+
const SILFunction *getOriginOfSpecialization() const;
866870

867871
/// Retrieve the generic environment containing the mapping from interface
868872
/// types to context archetypes for this function. Only present if the

lib/IRGen/GenDecl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,16 @@ void IRGenerator::addLazyFunction(SILFunction *f) {
12091209
assert(!FinishedEmittingLazyDefinitions);
12101210
LazyFunctionDefinitions.push_back(f);
12111211

1212+
if (const SILFunction *orig = f->getOriginOfSpecialization()) {
1213+
// f is a specialization. Try to emit all specializations of the same
1214+
// original function into the same IGM. This increases the chances that
1215+
// specializations are merged by LLVM's function merging.
1216+
auto iter =
1217+
IGMForSpecializations.insert(std::make_pair(orig, CurrentIGM)).first;
1218+
DefaultIGMForFunction.insert(std::make_pair(f, iter->second));
1219+
return;
1220+
}
1221+
12121222
if (auto *dc = f->getDeclContext())
12131223
if (dc->getParentSourceFile())
12141224
return;

lib/IRGen/IRGenModule.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,13 @@ class IRGenerator {
204204
// Stores the IGM from which a function is referenced the first time.
205205
// It is used if a function has no source-file association.
206206
llvm::DenseMap<SILFunction *, IRGenModule *> DefaultIGMForFunction;
207-
207+
208+
// The IGMs where sepecializations of functions are emitted. The key is the
209+
// non-specialized function.
210+
// Storing all specializations of a function in the same IGM increases the
211+
// chances of function merging.
212+
llvm::DenseMap<const SILFunction *, IRGenModule *> IGMForSpecializations;
213+
208214
// The IGM of the first source file.
209215
IRGenModule *PrimaryIGM = nullptr;
210216

lib/SIL/SILFunction.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,17 @@ bool SILFunction::hasForeignBody() const {
167167
return SILDeclRef::isClangGenerated(getClangNode());
168168
}
169169

170+
const SILFunction *SILFunction::getOriginOfSpecialization() const {
171+
if (!isSpecialization())
172+
return nullptr;
173+
174+
const SILFunction *p = getSpecializationInfo()->getParent();
175+
while (p->isSpecialization()) {
176+
p = p->getSpecializationInfo()->getParent();
177+
}
178+
return p;
179+
}
180+
170181
void SILFunction::numberValues(llvm::DenseMap<const SILNode*, unsigned> &
171182
ValueToNumberMap) const {
172183
unsigned idx = 0;

test/IRGen/Inputs/multithread_module/main.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ public struct MyStruct : MyProto {
2323
return x + 3
2424
}
2525

26+
public func mutateMyStructArray(_ arr: inout [MyStruct], _ x: MyStruct) {
27+
arr.append(x)
28+
}
29+
2630
public var g1 = 234
2731

2832
let i = testit(27)

test/IRGen/multithread_module.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,18 @@ func callproto(_ p: MyProto) {
5858
print(p.protofunc())
5959
}
6060

61+
public func mutateBaseArray(_ arr: inout [Base], _ x: Base) {
62+
arr.append(x)
63+
}
64+
65+
6166
// Check the llvm IR files:
6267

68+
// Check if all specializations from stdlib functions are created in the same LLVM module.
69+
70+
// CHECK-MAINLL-DAG: define {{.*}} @"$sSa16_createNewBuffer14bufferIsUnique15minimumCapacity13growForAppendySb_SiSbtF4test8MyStructV_Tg5"
71+
// CHECK-MAINLL-DAG: define {{.*}} @"$sSa16_createNewBuffer14bufferIsUnique15minimumCapacity13growForAppendySb_SiSbtF4test4BaseC_Tg5"
72+
6373
// Check if the DI filename is correct and not "<unknown>".
6474

6575
// CHECK-MAINLL: [[F:![0-9]+]] = !DIFile(filename: "{{.*}}IRGen/Inputs/multithread_module/main.swift", directory: "{{.*}}")

0 commit comments

Comments
 (0)