Skip to content

Commit 72a4209

Browse files
committed
[Compile Time Values] Add mandatory optimization pipeline driver for '@const' globals
1 parent ac60612 commit 72a4209

File tree

9 files changed

+91
-49
lines changed

9 files changed

+91
-49
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/SimplificationPasses.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,6 @@ let ononeSimplificationPass = FunctionPass(name: "onone-simplification") {
4444
}
4545
}
4646

47-
let constPropagationPass = FunctionPass(name: "const-propagation") {
48-
(function: Function, context: FunctionPassContext) in
49-
runSimplification(on: function, context, preserveDebugInfo: true) {
50-
if let i = $0 as? OnoneSimplifiable {
51-
i.simplify($1)
52-
}
53-
}
54-
}
55-
5647
let simplificationPass = FunctionPass(name: "simplification") {
5748
(function: Function, context: FunctionPassContext) in
5849

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ let mandatoryPerformanceOptimizations = ModulePass(name: "mandatory-performance-
4747
}
4848
}
4949

50+
/// Performance the same set of top-down optimization as the above "mandatory-performance-optimizations"
51+
/// pass, but only on the initializers of '@const' globals.
52+
let constGlobalVariableFoldingPass = ModulePass(name: "const-global-variable-folding") {
53+
(moduleContext: ModulePassContext) in
54+
var worklist = FunctionWorklist()
55+
worklist.addAllConstGlobalInitOnceFunctions(of: moduleContext)
56+
optimizeFunctionsTopDown(using: &worklist, moduleContext)
57+
}
58+
5059
private func optimizeFunctionsTopDown(using worklist: inout FunctionWorklist,
5160
_ moduleContext: ModulePassContext) {
5261
while let f = worklist.pop() {
@@ -506,6 +515,15 @@ fileprivate struct FunctionWorklist {
506515
}
507516
}
508517

518+
mutating func addAllConstGlobalInitOnceFunctions(of moduleContext: ModulePassContext) {
519+
for f in moduleContext.functions where f.isGlobalInitOnceFunction {
520+
if let global = f.getInitializedGlobal(),
521+
global.isConst {
522+
pushIfNotVisited(f)
523+
}
524+
}
525+
}
526+
509527
mutating func addCallees(of function: Function) {
510528
for inst in function.instructions {
511529
switch inst {

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ private func registerForSILCombine<InstType: SILCombineSimplifiable>(
6464
private func registerSwiftPasses() {
6565
// Module passes
6666
registerPass(mandatoryPerformanceOptimizations, { mandatoryPerformanceOptimizations.run($0) })
67+
registerPass(constGlobalVariableFoldingPass, { constGlobalVariableFoldingPass.run($0)})
6768
registerPass(readOnlyGlobalVariablesPass, { readOnlyGlobalVariablesPass.run($0) })
6869
registerPass(stackProtection, { stackProtection.run($0) })
6970

@@ -85,7 +86,6 @@ private func registerSwiftPasses() {
8586
registerPass(releaseDevirtualizerPass, { releaseDevirtualizerPass.run($0) })
8687
registerPass(simplificationPass, { simplificationPass.run($0) })
8788
registerPass(ononeSimplificationPass, { ononeSimplificationPass.run($0) })
88-
registerPass(constPropagationPass, { constPropagationPass.run($0) })
8989
registerPass(lateOnoneSimplificationPass, { lateOnoneSimplificationPass.run($0) })
9090
registerPass(cleanupDebugStepsPass, { cleanupDebugStepsPass.run($0) })
9191
registerPass(namedReturnValueOptimization, { namedReturnValueOptimization.run($0) })

SwiftCompilerSources/Sources/SIL/GlobalVariable.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ final public class GlobalVariable : CustomStringConvertible, HasShortDescription
7171
return bridged.mustBeInitializedStatically()
7272
}
7373

74+
public var isConst: Bool {
75+
return bridged.isConstVal()
76+
}
77+
7478
public static func ==(lhs: GlobalVariable, rhs: GlobalVariable) -> Bool {
7579
lhs === rhs
7680
}

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ struct BridgedGlobalVar {
570570
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedInstruction getFirstStaticInitInst() const;
571571
bool canBeInitializedStatically() const;
572572
bool mustBeInitializedStatically() const;
573+
bool isConstVal() const;
573574
};
574575

575576
struct OptionalBridgedGlobalVar {

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,39 @@ LEGACY_PASS(SILDebugInfoGenerator, "sil-debuginfo-gen",
415415
"Generate Debug Information with Source Locations into Textual SIL")
416416
LEGACY_PASS(EarlySROA, "early-sroa",
417417
"Scalar Replacement of Aggregate Stack Objects on high-level SIL")
418-
LEGACY_PASS(SROA, "sroa",
418+
SWIFT_MODULE_PASS(RunUnitTests, "run-unit-tests",
419+
"Runs the compiler internal unit tests")
420+
SWIFT_FUNCTION_PASS(SILPrinter, "sil-printer",
421+
"Test pass which prints the SIL of a function")
422+
SWIFT_MODULE_PASS(FunctionUsesDumper, "dump-function-uses",
423+
"Dump the results of FunctionUses")
424+
SWIFT_MODULE_PASS(MandatoryPerformanceOptimizations, "mandatory-performance-optimizations",
425+
"Performs optimizations for performance-annotated functions")
426+
SWIFT_MODULE_PASS(ConstGlobalVariableFoldingPass, "const-global-variable-folding",
427+
"Performs simplification and folding of @const global variable initializers")
428+
SWIFT_MODULE_PASS(ReadOnlyGlobalVariablesPass, "read-only-global-variables",
429+
"Converts read-only var-globals to let-globals")
430+
SWIFT_MODULE_PASS(StackProtection, "stack-protection",
431+
"Decides which functions need stack protectors")
432+
SWIFT_FUNCTION_PASS(FunctionStackProtection, "function-stack-protection",
433+
"Decides which functions need stack protectors")
434+
PASS(SROA, "sroa",
419435
"Scalar Replacement of Aggregate Stack Objects")
420436
LEGACY_PASS(SROABBArgs, "sroa-bb-args",
421437
"Scalar Replacement of Aggregate SIL Block Arguments")
422-
LEGACY_PASS(SimplifyBBArgs, "simplify-bb-args",
438+
SWIFT_FUNCTION_PASS(Simplification, "simplification",
439+
"Peephole simplifications")
440+
SWIFT_FUNCTION_PASS(OnoneSimplification, "onone-simplification",
441+
"Peephole simplifications which runs at -Onone")
442+
SWIFT_FUNCTION_PASS(LateOnoneSimplification, "late-onone-simplification",
443+
"Peephole simplifications which can only run late in the -Onone pipeline")
444+
SWIFT_FUNCTION_PASS(CleanupDebugSteps, "cleanup-debug-steps",
445+
"Cleanup debug_step instructions for Onone")
446+
SWIFT_FUNCTION_PASS(NamedReturnValueOptimization, "named-return-value-optimization",
447+
"Optimize copies to an indirect return value")
448+
SWIFT_FUNCTION_PASS(StripObjectHeaders, "strip-object-headers",
449+
"Sets the bare flag on objects which don't need their headers")
450+
PASS(SimplifyBBArgs, "simplify-bb-args",
423451
"SIL Block Argument Simplification")
424452
LEGACY_PASS(SpeculativeDevirtualization, "specdevirt",
425453
"Speculative Devirtualization via Guarded Calls")

lib/SIL/Utils/SILBridging.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,11 @@ bool BridgedGlobalVar::mustBeInitializedStatically() const {
329329
return global->mustBeInitializedStatically();
330330
}
331331

332+
bool BridgedGlobalVar::isConstVal() const {
333+
SILGlobalVariable *global = getGlobal();
334+
return global->getDecl()->isConstVal();
335+
}
336+
332337
//===----------------------------------------------------------------------===//
333338
// SILDeclRef
334339
//===----------------------------------------------------------------------===//

lib/SILOptimizer/Mandatory/DiagnoseUnknownCompileTimeValues.cpp

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -91,29 +91,11 @@ class DiagnoseUnknownCompileTimeValues : public SILModuleTransform {
9191
}
9292
}
9393

94-
void verifyStaticallyInitializedGlobal(ConstExprFunctionState &ConstExprState,
95-
SILGlobalVariable &Global,
96-
VarDecl *Decl) {
97-
LLVM_DEBUG(llvm::dbgs()
98-
<< "@const static let " << Decl->getName().str().str()
99-
<< ": " << Decl->getTypeInContext().getString() << " = ";);
100-
auto StaticInitializerValue = Global.getStaticInitializerValue();
101-
assert(StaticInitializerValue && "Expected a static initializer");
102-
if (auto *SI = dyn_cast<StructInst>(StaticInitializerValue)) {
103-
for (auto &SIO : SI->getAllOperands()) {
104-
if (!ConstExprState.getConstantValue(SIO.get())
105-
.containsOnlyConstants()) {
106-
Decl->diagnose(diag::require_const_initializer_for_const);
107-
LLVM_DEBUG(llvm::dbgs() << "Unknown\n";);
108-
} else
109-
LLVM_DEBUG(printSymbolicValueValue(
110-
ConstExprState.getConstantValue(SIO.get()), Allocator));
111-
}
112-
}
113-
}
114-
11594
void verifyInitializeOnceGlobal(ConstExprFunctionState &ConstExprState,
11695
SILGlobalVariable &Global, VarDecl *Decl) {
96+
// TODO: Determine cases if/where this is necessary to perform,
97+
// i.e. where we currently fail to simplify to a statically-initialized
98+
// value.
11799
LLVM_DEBUG(llvm::dbgs()
118100
<< "@const [init_once] let " << Decl->getName().str().str()
119101
<< ": " << Decl->getTypeInContext().getString() << " = ";);
@@ -129,19 +111,11 @@ class DiagnoseUnknownCompileTimeValues : public SILModuleTransform {
129111
for (SILInstruction &I : BB) {
130112
if (auto *GlobalAddr = dyn_cast<GlobalAddrInst>(&I)) {
131113
if (GlobalAddr->getReferencedGlobal() == &Global) {
132-
// Get the sole store to the global addr
133-
// ACTODO: check if single use valid/exists
134-
// Find sole store
135-
// for (auto *use : getNonDebugUses(existentialBox)) {
136-
// worklist.insert(use);
137-
// }
138-
139114
if (auto SingleUse = GlobalAddr->getSingleUse()) {
140115
auto SoleUseUser = SingleUse->getUser();
141116
assert(isa<StoreInst>(SoleUseUser));
142-
auto Value = ConstExprState.getConstantValue(
143-
dyn_cast<StoreInst>(SoleUseUser)->getSrc());
144-
117+
auto src = dyn_cast<StoreInst>(SoleUseUser)->getSrc();
118+
auto Value = ConstExprState.getConstantValue(src);
145119
if (Value.isConstant()) {
146120
LLVM_DEBUG(printSymbolicValueValue(Value, Allocator););
147121
return;
@@ -165,9 +139,29 @@ class DiagnoseUnknownCompileTimeValues : public SILModuleTransform {
165139
for (SILGlobalVariable &G : M->getSILGlobals()) {
166140
if (auto Decl = G.getDecl()) {
167141
if (Decl->isConstVal()) {
168-
if (G.getStaticInitializerValue())
169-
verifyStaticallyInitializedGlobal(ConstExprState, G, Decl);
170-
else
142+
if (G.getStaticInitializerValue()) {
143+
// Presence of a static initializer alone confirms
144+
// this to be a constant value.
145+
LLVM_DEBUG(
146+
llvm::dbgs()
147+
<< "@const static let " << Decl->getName().str().str()
148+
<< ": " << Decl->getTypeInContext().getString() << " = ";
149+
auto StaticInitializerValue = G.getStaticInitializerValue();
150+
assert(StaticInitializerValue &&
151+
"Expected a static initializer");
152+
if (auto *SI = dyn_cast<StructInst>(StaticInitializerValue)) {
153+
for (auto &SIO : SI->getAllOperands()) {
154+
if (!ConstExprState.getConstantValue(SIO.get())
155+
.containsOnlyConstants())
156+
LLVM_DEBUG(llvm::dbgs()
157+
<< "Unknown to the Constant Evaluator\n";);
158+
else
159+
LLVM_DEBUG(printSymbolicValueValue(
160+
ConstExprState.getConstantValue(SIO.get()),
161+
Allocator));
162+
}
163+
});
164+
} else
171165
verifyInitializeOnceGlobal(ConstExprState, G, Decl);
172166
}
173167
}
@@ -244,8 +238,8 @@ class DiagnoseUnknownCompileTimeValues : public SILModuleTransform {
244238
printSymbolicValueValue(Value, Allocator);
245239
});
246240
if (!ConstExprState.getConstantValue(CorrespondingArg).isConstant()) {
247-
// FIXME: Is there a way to get this source loc without going throuh
248-
// the ApplyExpr?
241+
// FIXME: Is there a way to get this source loc without going
242+
// throuh the ApplyExpr?
249243
auto ArgLocation = Apply->getLoc().getSourceLoc();
250244
if (auto ApplyExprNode = Apply->getLoc().getAsASTNode<ApplyExpr>())
251245
ArgLocation = ApplyExprNode->getArgs()[i].getLoc();

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) {
262262
P.addDeadFunctionAndGlobalElimination();
263263
}
264264

265-
P.addConstPropagation();
265+
P.addConstGlobalVariableFoldingPass();
266+
P.addOnoneSimplification();
266267
P.addDiagnoseUnknownCompileTimeValues();
267268

268269
P.addPerformanceDiagnostics();

0 commit comments

Comments
 (0)