Skip to content

Commit 5285bf7

Browse files
authored
Turn off speculative devirtualization by default. (#29359)
Turn off speculative devirtualization by default. Add a flag to support enabling the pass. Fixes rdar://58778959 and rdar://58429282
1 parent 5669985 commit 5285bf7

17 files changed

+40
-24
lines changed

include/swift/AST/SILOptions.h

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class SILOptions {
5757
/// purposes.
5858
bool EnableOSSAOptimizations = true;
5959

60+
/// Controls whether to turn on speculative devirtualization.
61+
/// It is turned off by default.
62+
bool EnableSpeculativeDevirtualization = false;
63+
6064
/// Should we run any SIL performance optimizations
6165
///
6266
/// Useful when you want to enable -O LLVM opts but not -O SIL opts.

include/swift/Option/FrontendOptions.td

+3
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ def disable_ossa_opts : Flag<["-"], "disable-ossa-opts">,
282282
def disable_sil_partial_apply : Flag<["-"], "disable-sil-partial-apply">,
283283
HelpText<"Disable use of partial_apply in SIL generation">;
284284

285+
def enable_spec_devirt : Flag<["-"], "enable-spec-devirt">,
286+
HelpText<"Enable speculative devirtualization pass.">;
287+
285288
def enable_ownership_stripping_after_serialization
286289
: Flag<["-"], "enable-ownership-stripping-after-serialization">,
287290
HelpText<"Strip ownership after serialization">;

lib/Frontend/CompilerInvocation.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
959959

960960
Opts.EnableARCOptimizations &= !Args.hasArg(OPT_disable_arc_opts);
961961
Opts.EnableOSSAOptimizations &= !Args.hasArg(OPT_disable_ossa_opts);
962+
Opts.EnableSpeculativeDevirtualization |= Args.hasArg(OPT_enable_spec_devirt);
962963
Opts.DisableSILPerfOptimizations |= Args.hasArg(OPT_disable_sil_perf_optzns);
963964
Opts.CrossModuleOptimization |= Args.hasArg(OPT_CrossModuleOptimization);
964965
Opts.VerifyAll |= Args.hasArg(OPT_sil_verify_all);

lib/SILOptimizer/PassManager/PassPipeline.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,9 @@ static void addClosureSpecializePassPipeline(SILPassPipelinePlan &P) {
488488
P.addStackPromotion();
489489

490490
// Speculate virtual call targets.
491-
P.addSpeculativeDevirtualization();
491+
if (P.getOptions().EnableSpeculativeDevirtualization) {
492+
P.addSpeculativeDevirtualization();
493+
}
492494

493495
// There should be at least one SILCombine+SimplifyCFG between the
494496
// ClosureSpecializer, etc. and the last inliner. Cleaning up after these

lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ namespace {
596596
void run() override {
597597

598598
auto &CurFn = *getFunction();
599+
599600
// Don't perform speculative devirtualization at -Os.
600601
if (CurFn.optimizeForSize())
601602
return;

test/SILOptimizer/devirt_base_class.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -enable-spec-devirt -O -emit-sil %s | %FileCheck %s
22

33
public class Base1 { @inline(never) func f() -> Int { return 0 } }
44

test/SILOptimizer/devirt_covariant_return.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: %target-swift-frontend -module-name devirt_covariant_return -Xllvm -sil-full-demangle -O -Xllvm -disable-sil-cm-rr-cm=0 -Xllvm -sil-inline-generics=false -primary-file %s -emit-sil -sil-inline-threshold 1000 -Xllvm -sil-disable-pass=ObjectOutliner -sil-verify-all | %FileCheck %s
2+
// RUN: %target-swift-frontend -module-name devirt_covariant_return -Xllvm -sil-full-demangle -enable-spec-devirt -O -Xllvm -disable-sil-cm-rr-cm=0 -Xllvm -sil-inline-generics=false -primary-file %s -emit-sil -sil-inline-threshold 1000 -Xllvm -sil-disable-pass=ObjectOutliner -sil-verify-all | %FileCheck %s
33

44
// Make sure that we can dig all the way through the class hierarchy and
55
// protocol conformances with covariant return types correctly. The verifier

test/SILOptimizer/devirt_default_case.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

2-
// RUN: %target-swift-frontend -O -module-name devirt_default_case -emit-sil %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-NORMAL %s
3-
// RUN: %target-swift-frontend -O -module-name devirt_default_case -emit-sil -enable-testing %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-TESTABLE %s
2+
// RUN: %target-swift-frontend -enable-spec-devirt -O -module-name devirt_default_case -emit-sil %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-NORMAL %s
3+
// RUN: %target-swift-frontend -enable-spec-devirt -O -module-name devirt_default_case -emit-sil -enable-testing %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-TESTABLE %s
44

55
@_silgen_name("action")
66
func action(_ n:Int) -> ()

test/SILOptimizer/devirt_protocol_method_invocations.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: %target-swift-frontend -module-name devirt_protocol_method_invocations -O -Xllvm -sil-disable-pass=ExistentialSpecializer -emit-sil %s | %FileCheck %s
2+
// RUN: %target-swift-frontend -module-name devirt_protocol_method_invocations -enable-spec-devirt -O -Xllvm -sil-disable-pass=ExistentialSpecializer -emit-sil %s | %FileCheck %s
33

44
protocol PPP {
55
func f()

test/SILOptimizer/devirt_speculate.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend %/s -parse-as-library -O -emit-sil -save-optimization-record-path %t.opt.yaml | %FileCheck %s
1+
// RUN: %target-swift-frontend %/s -parse-as-library -enable-spec-devirt -O -emit-sil -save-optimization-record-path %t.opt.yaml | %FileCheck %s
22
// RUN: %FileCheck -check-prefix=YAML -input-file=%t.opt.yaml %s
33
// RUN: %target-swift-frontend %/s -parse-as-library -Osize -emit-sil | %FileCheck %s --check-prefix=OSIZE
44
//

test/SILOptimizer/devirt_speculative_init.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: %target-swift-frontend %s -parse-as-library -O -emit-sil | %FileCheck %s
2+
// RUN: %target-swift-frontend %s -parse-as-library -enable-spec-devirt -O -emit-sil | %FileCheck %s
33
// RUN: %target-swift-frontend %s -parse-as-library -Osize -emit-sil
44
//
55
// Test speculative devirtualization.

test/SILOptimizer/devirt_speculative_nested.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: %target-swift-frontend -module-name devirt_speculative_nested %s -parse-as-library -O -emit-sil | %FileCheck %s
2+
// RUN: %target-swift-frontend -module-name devirt_speculative_nested %s -parse-as-library -enable-spec-devirt -O -emit-sil | %FileCheck %s
33
// RUN: %target-swift-frontend -module-name devirt_speculative_nested %s -parse-as-library -Osize -emit-sil
44
//
55
// Test speculative devirtualization.

test/SILOptimizer/devirt_unbound_generic.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -emit-sil -O %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -emit-sil -enable-spec-devirt -O %s | %FileCheck %s
22

33
// We used to crash on this when trying to devirtualize t.boo(a, 1),
44
// because it is an "apply" with replacement types that contain

test/SILOptimizer/devirt_value_metatypes.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: %target-swift-frontend -module-name devirt_value_metatypes -emit-sil -O %s | %FileCheck %s
2+
// RUN: %target-swift-frontend -module-name devirt_value_metatypes -emit-sil -enable-spec-devirt -O %s | %FileCheck %s
33

44
open class A {
55
@inline(never)

test/SILOptimizer/inline_cache_and_arc.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -parse-as-library -O -emit-sil %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -parse-as-library -enable-spec-devirt -O -emit-sil %s | %FileCheck %s
22
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib,CPU=x86_64
33

44
// Test inline cache with a global class. Make sure the retain|release pair
@@ -19,7 +19,6 @@ public func testit() {
1919
// CHECK-LABEL: sil @{{.*}}testityyF
2020
// CHECK: bb0:
2121
// CHECK-NOT: {{.*(retain|release).*}}
22-
// CHECK: checked_cast_br
2322
// CHECK: bb1{{.*}}:
2423
// CHECK-NOT: {{.*(retain|release).*}}
2524
// CHECK: return

test/SILOptimizer/opt_mode.swift

+11-11
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,6 @@ class B : A {
1515

1616
func donothing(_ x: Int) -> Int { return x }
1717

18-
// CHECK-LABEL: sil {{.*}} [Ospeed] @{{.*}}test_ospeed
19-
// CHECK: checked_cast_br
20-
// CHECK: checked_cast_br
21-
// CHECK: }
22-
// CHECK-IR: define hidden {{.*}}test_ospeed{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
23-
@_optimize(speed)
24-
func test_ospeed(_ a: A) -> Int {
25-
return donothing(a.foo(27))
26-
}
27-
2818
// CHECK-LABEL: sil {{.*}} [Osize] @{{.*}}test_osize
2919
// CHECK: [[M:%[0-9]+]] = class_method
3020
// CHECK: [[A:%[0-9]+]] = apply [[M]]
@@ -46,6 +36,16 @@ func test_onone(_ a: A) -> Int {
4636
return donothing(a.foo(27))
4737
}
4838

39+
// CHECK-LABEL: sil {{.*}} [Ospeed] @{{.*}}test_ospeed
40+
// CHECK: [[M:%[0-9]+]] = class_method
41+
// CHECK: [[A:%[0-9]+]] = apply [[M]]
42+
// CHECK: return [[A]]
43+
// CHECK-IR: define hidden {{.*}}test_ospeed{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
44+
@_optimize(speed)
45+
func test_ospeed(_ a: A) -> Int {
46+
return donothing(a.foo(27))
47+
}
48+
4949

50-
// CHECK-IR: attributes [[NOSIZE_ATTR]] = { "
5150
// CHECK-IR: attributes [[SIZE_ATTR]] = { minsize "
51+
// CHECK-IR: attributes [[NOSIZE_ATTR]] = { "

tools/sil-opt/SILOpt.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ static llvm::cl::opt<bool>
102102
VerifyExclusivity("enable-verify-exclusivity",
103103
llvm::cl::desc("Verify the access markers used to enforce exclusivity."));
104104

105+
static llvm::cl::opt<bool>
106+
EnableSpeculativeDevirtualization("enable-spec-devirt",
107+
llvm::cl::desc("Enable Speculative Devirtualization pass."));
108+
105109
namespace {
106110
enum EnforceExclusivityMode {
107111
Unchecked, // static only
@@ -376,6 +380,8 @@ int main(int argc, char **argv) {
376380
}
377381
}
378382

383+
SILOpts.EnableSpeculativeDevirtualization = EnableSpeculativeDevirtualization;
384+
379385
serialization::ExtendedValidationInfo extendedInfo;
380386
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
381387
Invocation.setUpInputForSILTool(InputFilename, ModuleName,

0 commit comments

Comments
 (0)