Skip to content

Commit f664be4

Browse files
authored
Merge pull request #29122 from zoecarver/optimize/global-var-init
Update global init optimization to work with vars
2 parents a498004 + f8c4c45 commit f664be4

File tree

2 files changed

+46
-9
lines changed

2 files changed

+46
-9
lines changed

lib/SILOptimizer/IPO/GlobalOpt.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ class SILGlobalOpt {
121121
bool run();
122122

123123
protected:
124+
/// Checks if a given global variable is assigned only once.
125+
bool isAssignedOnlyOnceInInitializer(SILGlobalVariable *SILG,
126+
SILFunction *globalAddrF);
127+
124128
/// Reset all the maps of global variables.
125129
void reset();
126130

@@ -637,15 +641,26 @@ static SILFunction *genGetterFromInit(SILOptFunctionBuilder &FunctionBuilder,
637641
return GetterF;
638642
}
639643

640-
/// Checks if a given global variable is assigned only once.
641-
static bool isAssignedOnlyOnceInInitializer(SILGlobalVariable *SILG) {
644+
bool SILGlobalOpt::isAssignedOnlyOnceInInitializer(SILGlobalVariable *SILG,
645+
SILFunction *globalAddrF) {
642646
if (SILG->isLet())
643647
return true;
644-
// TODO: If we can prove that a given global variable
645-
// is assigned only once, during initialization, then
646-
// we can treat it as if it is a let.
647-
// If this global is internal or private, it should be
648-
return false;
648+
649+
// If we should skip this, it is probably because there are multiple stores.
650+
// Return false if there are multiple stores or no stores.
651+
if (GlobalVarSkipProcessing.count(SILG) || !GlobalVarStore.count(SILG) ||
652+
// Check if there is more than one use the global addr function. If there
653+
// is only one use, it must be the use that we are trying to optimize, so
654+
// that is OK. If there is more than one use, one of the other uses may
655+
// have a store attached to it which means there may be more than one
656+
// assignment, so return false.
657+
(GlobalInitCallMap.count(globalAddrF) &&
658+
GlobalInitCallMap[globalAddrF].size() != 1))
659+
return false;
660+
661+
// Otherwise, return true if this can't be used externally (false, otherwise).
662+
return !isPossiblyUsedExternally(SILG->getLinkage(),
663+
SILG->getModule().isWholeModule());
649664
}
650665

651666
/// Replace load sequence which may contain
@@ -691,7 +706,7 @@ replaceLoadsByKnownValue(BuiltinInst *CallToOnce, SILFunction *AddrF,
691706
LLVM_DEBUG(llvm::dbgs() << "GlobalOpt: replacing loads with known value for "
692707
<< SILG->getName() << '\n');
693708

694-
assert(isAssignedOnlyOnceInInitializer(SILG) &&
709+
assert(isAssignedOnlyOnceInInitializer(SILG, AddrF) &&
695710
"The value of the initializer should be known at compile-time");
696711
assert(SILG->getDecl() &&
697712
"Decl corresponding to the global variable should be known");
@@ -804,7 +819,7 @@ void SILGlobalOpt::optimizeInitializer(SILFunction *AddrF,
804819
<< SILG->getName() << '\n');
805820

806821
// Remove "once" call from the addressor.
807-
if (!isAssignedOnlyOnceInInitializer(SILG) || !SILG->getDecl()) {
822+
if (!isAssignedOnlyOnceInInitializer(SILG, AddrF) || !SILG->getDecl()) {
808823
LLVM_DEBUG(llvm::dbgs() << "GlobalOpt: building static initializer for "
809824
<< SILG->getName() << '\n');
810825

test/SILOptimizer/globalopt_global_propagation.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,25 @@ let IT2 = (100, 200, 300)
227227
public func test_let_tuple_wrapped_ints() -> Int {
228228
return IT1.0.0 + IT2.1
229229
}
230+
231+
class Foo {
232+
fileprivate static var x: Int = 0
233+
}
234+
235+
// CHECK-LABEL: sil @$s28globalopt_global_propagation25test_optimize_init_staticSiyF
236+
// CHECK: bb0:
237+
// CHECK-NOT: global_addr
238+
// CHECK-NEXT: integer_literal
239+
// CHECK-NEXT: struct
240+
// CHECK-NEXT: return
241+
242+
// CHECK-WMO-LABEL: sil @$s28globalopt_global_propagation25test_optimize_init_staticSiyF
243+
// CHECK-WMO: bb0:
244+
// CHECK-WMO-NOT: global_addr
245+
// CHECK-WMO-NEXT: integer_literal
246+
// CHECK-WMO-NEXT: struct
247+
// CHECK-WMO-NEXT: return
248+
public func test_optimize_init_static() -> Int {
249+
return Foo.x
250+
}
251+

0 commit comments

Comments
 (0)